1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 // Icon cache is used for drawing node icons; it caches icons 36 // and reuses them for successive draws 37 38 #ifndef __NU_ICON_CACHE__ 39 #define __NU_ICON_CACHE__ 40 41 #include <Bitmap.h> 42 #include <Mime.h> 43 #include <String.h> 44 45 #include "AutoLock.h" 46 #include "ObjectList.h" 47 #include "OpenHashTable.h" 48 #include "Utilities.h" 49 50 // Icon cache splits icons into two caches - the shared cache, likely to get the 51 // most hits and the node cache. Every icon that is found in a mime based 52 // structure goes into the shared cache, only files that have their own private 53 // icon use the node cache; 54 // Entries are only deleted from the shared cache if an icon for a mime type changes, 55 // this makes async icon drawing easier. Node cache deletes it's entries whenever a 56 // file gets deleted. 57 58 // if a view ever uses the cache to draw in async mode, it needs to call 59 // it when it is being destroyed 60 61 namespace BPrivate { 62 63 class Model; 64 class ModelNodeLazyOpener; 65 class LazyBitmapAllocator; 66 class SharedIconCache; 67 class SharedCacheEntry; 68 69 enum IconDrawMode { 70 // Different states of icon drawing 71 kSelected = 0x01, 72 kNotFocused = 0x02, // Tracker window 73 kOpen = 0x04, // open folder, trash 74 kNotEmpty = 0x08, // full trash 75 kDisabled = 0x10, // inactive nav menu entry 76 kActive = 0x20, // active home dir, boot volume 77 kLink = 0x40, // symbolic link 78 kTrackerSpecialized = 0x80, 79 80 // some common combinations 81 kNormalIcon = 0, 82 kSelectedIcon = kSelected, 83 kSelectedInBackgroundIcon = kSelected | kNotFocused, 84 kOpenIcon = kOpen, 85 kOpenSelectedIcon = kSelected | kOpen, 86 kOpenSelectedInBackgroundIcon = kSelected | kNotFocused | kOpen, 87 kFullIcon = kNotEmpty, 88 kFullSelectedIcon = kNotEmpty | kOpen, 89 kDimmedIcon 90 }; 91 92 #define NORMAL_ICON_ONLY kNormalIcon 93 // replace use of these defines with mode once the respective getters 94 // can get non-plain icons 95 96 97 // Where did an icon come from 98 enum IconSource { 99 kUnknownSource, 100 kUnknownNotFromNode, // icon origin not known but determined not to be from 101 // the node itself 102 kTrackerDefault, // file has no type, Tracker provides generic, folder, 103 // symlink or app 104 kTrackerSupplied, // home directory, boot volume, trash, etc. 105 kMetaMime, // from BMimeType 106 kPreferredAppForType, // have a preferred application for a type, has an icon 107 kPreferredAppForNode, // have a preferred application for this node, 108 // has an icon 109 kVolume, 110 kNode 111 }; 112 113 class IconCacheEntry { 114 // aliased entries don't own their icons, just point 115 // to some other entry that does 116 117 // This is used for icons that are defined by a preferred app for 118 // a metamime, types that do not have an icon get to point to 119 // generic, etc. 120 121 public: 122 IconCacheEntry(); 123 ~IconCacheEntry(); 124 125 void SetAliasFor(const SharedIconCache *, const SharedCacheEntry *); 126 static IconCacheEntry *ResolveIfAlias(const SharedIconCache *, IconCacheEntry *); 127 IconCacheEntry *ResolveIfAlias(const SharedIconCache *); 128 129 void SetIcon(BBitmap *bitmap, IconDrawMode mode, icon_size size, 130 bool create = false); 131 132 bool HaveIconBitmap(IconDrawMode mode, icon_size size) const; 133 bool CanConstructBitmap(IconDrawMode mode, icon_size size) const; 134 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode, 135 IconDrawMode &alternate, icon_size size); 136 BBitmap *ConstructBitmap(BBitmap *constructFrom, IconDrawMode requestedMode, 137 IconDrawMode constructFromMode, icon_size size, 138 LazyBitmapAllocator *); 139 BBitmap *ConstructBitmap(IconDrawMode requestedMode, icon_size size, 140 LazyBitmapAllocator *); 141 // same as above, always uses normal icon as source 142 143 bool IconHitTest(BPoint, IconDrawMode, icon_size) const; 144 // given a point, returns true if a non-transparent pixel was hit 145 146 void RetireIcons(BObjectList<BBitmap> *retiredBitmapList); 147 // can't just delete icons, they may be still drawing 148 // async; instead, put them on the retired list and 149 // only delete the list if it grows too much, way after 150 // the icon finishes drawing 151 // 152 // This could fail if we retire a lot of icons (10 * 1024) 153 // while we are drawing them, shouldn't be a practical problem 154 155 protected: 156 157 BBitmap *IconForMode(IconDrawMode mode, icon_size size) const; 158 void SetIconForMode(BBitmap *bitmap, IconDrawMode mode, icon_size size); 159 160 // list of most common icons 161 BBitmap *fLargeIcon; 162 BBitmap *fMiniIcon; 163 BBitmap *fHilitedLargeIcon; 164 BBitmap *fHilitedMiniIcon; 165 int32 fAliasForIndex; 166 167 // list of other icon kinds would be added here 168 169 friend class SharedIconCache; 170 friend class NodeIconCache; 171 }; 172 173 class SimpleIconCache { 174 public: 175 SimpleIconCache(const char *); 176 virtual ~SimpleIconCache() {} 177 178 virtual void Draw(IconCacheEntry *, BView *, BPoint, IconDrawMode mode, 179 icon_size size, bool async = false) = 0; 180 virtual void Draw(IconCacheEntry *, BView *, BPoint , IconDrawMode , 181 icon_size , void (*)(BView *, BPoint, BBitmap *, void *), void * = NULL) = 0; 182 183 bool Lock(); 184 void Unlock(); 185 bool IsLocked() const; 186 187 private: 188 Benaphore fLock; 189 }; 190 191 class SharedCacheEntry : public IconCacheEntry { 192 public: 193 SharedCacheEntry(); 194 SharedCacheEntry(const char *fileType, const char *appSignature = 0); 195 196 void Draw(BView *, BPoint, IconDrawMode mode, icon_size size, 197 bool async = false); 198 199 void Draw(BView *, BPoint , IconDrawMode , icon_size , 200 void (*)(BView *, BPoint, BBitmap *, void *), void * = NULL); 201 202 const char *FileType() const; 203 const char *AppSignature() const; 204 205 // hash table support 206 uint32 Hash() const; 207 static uint32 Hash(const char *fileType, const char *appSignature = 0); 208 bool operator==(const SharedCacheEntry &) const; 209 void SetTo(const char *fileType, const char *appSignature = 0); 210 211 int32 fNext; 212 private: 213 BString fFileType; 214 BString fAppSignature; 215 216 friend class SharedIconCache; 217 }; 218 219 class SharedCacheEntryArray : public OpenHashElementArray<SharedCacheEntry> { 220 // SharedIconCache stores all it's elements in this array 221 public: 222 SharedCacheEntryArray(int32 initialSize); 223 SharedCacheEntry *Add(); 224 }; 225 226 class SharedIconCache : public SimpleIconCache { 227 // SharedIconCache is used for icons that come from the mime database 228 public: 229 SharedIconCache(); 230 231 virtual void Draw(IconCacheEntry *, BView *, BPoint, IconDrawMode mode, 232 icon_size size, bool async = false); 233 virtual void Draw(IconCacheEntry *, BView *, BPoint , IconDrawMode , 234 icon_size , void (*)(BView *, BPoint, BBitmap *, void *), void * = NULL); 235 236 SharedCacheEntry *FindItem(const char *fileType, const char *appSignature = 0) 237 const; 238 SharedCacheEntry *AddItem(const char *fileType, const char *appSignature = 0); 239 SharedCacheEntry *AddItem(SharedCacheEntry **outstandingEntry, const char *fileType, 240 const char *appSignature = 0); 241 // same as previous AddItem, updates the pointer to outstandingEntry, because 242 // adding to the hash table makes any pending pointer invalid 243 void IconChanged(SharedCacheEntry *); 244 245 void SetAliasFor(IconCacheEntry *alias, const SharedCacheEntry *original) const; 246 IconCacheEntry *ResolveIfAlias(IconCacheEntry *entry) const; 247 int32 EntryIndex(const SharedCacheEntry *entry) const; 248 249 void RemoveAliasesTo(int32 index); 250 251 private: 252 OpenHashTable<SharedCacheEntry, SharedCacheEntryArray> fHashTable; 253 SharedCacheEntryArray fElementArray; 254 BObjectList<BBitmap> fRetiredBitmaps; 255 // icons are drawn asynchronously, can't just delete them 256 // right away, instead have to place them onto the retired bitmap list 257 // and wait for the next sync to delete them 258 }; 259 260 class NodeCacheEntry : public IconCacheEntry { 261 public: 262 NodeCacheEntry(bool permanent = false); 263 NodeCacheEntry(const node_ref *, bool permanent = false); 264 void Draw(BView *, BPoint, IconDrawMode mode, icon_size size, 265 bool async = false); 266 267 void Draw(BView *, BPoint , IconDrawMode , icon_size , 268 void (*)(BView *, BPoint, BBitmap *, void *), void * = NULL); 269 270 const node_ref *Node() const; 271 272 uint32 Hash() const; 273 static uint32 Hash(const node_ref *); 274 bool operator==(const NodeCacheEntry &) const; 275 void SetTo(const node_ref *); 276 void MakePermanent(); 277 bool Permanent() const; 278 279 int32 fNext; 280 private: 281 node_ref fRef; 282 bool fPermanent; 283 // special cache entry that has to be deleted explicitly 284 285 friend class NodeIconCache; 286 }; 287 288 class NodeCacheEntryArray : public OpenHashElementArray<NodeCacheEntry> { 289 // NodeIconCache stores all it's elements in this array 290 public: 291 NodeCacheEntryArray(int32 initialSize); 292 NodeCacheEntry *Add(); 293 }; 294 295 class NodeIconCache : public SimpleIconCache { 296 // NodeIconCache is used for nodes that define their own icons 297 public: 298 NodeIconCache(); 299 300 virtual void Draw(IconCacheEntry *, BView *, BPoint, IconDrawMode , 301 icon_size , bool async = false); 302 303 virtual void Draw(IconCacheEntry *, BView *, BPoint , IconDrawMode , 304 icon_size , void (*)(BView *, BPoint, BBitmap *, void *), void * = 0); 305 306 NodeCacheEntry *FindItem(const node_ref *) const; 307 NodeCacheEntry *AddItem(const node_ref *, bool permanent = false); 308 NodeCacheEntry *AddItem(NodeCacheEntry **outstandingEntry, const node_ref *); 309 // same as previous AddItem, updates the pointer to outstandingEntry, because 310 // adding to the hash table makes any pending pointer invalid 311 void Deleting(const node_ref *); 312 // model for this node is getting deleted (not necessarily the node itself) 313 void Removing(const node_ref *); 314 // used by permanent NodeIconCache entries, when an entry gets deleted 315 void Deleting(const BView *); 316 void IconChanged(const Model *); 317 318 319 void RemoveAliasesTo(int32 index); 320 321 private: 322 OpenHashTable<NodeCacheEntry, NodeCacheEntryArray> fHashTable; 323 NodeCacheEntryArray fElementArray; 324 }; 325 326 const int32 kColorTransformTableSize = 256; 327 328 class IconCache { 329 public: 330 IconCache(); 331 332 void Draw(Model *, BView *, BPoint where, IconDrawMode mode, 333 icon_size size, bool async = false); 334 // draw an icon for a model, load the icon from the appropriate 335 // location if not cached already 336 337 void SyncDraw(Model *, BView *, BPoint , IconDrawMode , 338 icon_size , void (*)(BView *, BPoint, BBitmap *, void *), 339 void *passThruState = 0); 340 // draw an icon for a model, load the icon from the appropriate 341 // location if not cached already; only works for sync draws, 342 // once the call returns, the bitmap may be deleted 343 344 // preload calls used to ensure successive cache hit for the respective 345 // icon, used for common tracker types, etc; Not calling these should only 346 // cause a slowdown 347 void Preload(Model *, IconDrawMode mode, icon_size size, bool permanent = false); 348 status_t Preload(const char *mimeType, IconDrawMode mode, icon_size size); 349 350 void Deleting(const Model *); 351 // hook to manage unloading icons for nodes that are going away 352 void Removing(const Model *model); 353 // used by permanent NodeIconCache entries, when an entry gets 354 // deleted 355 void Deleting(const BView *); 356 // hook to manage deleting draw view caches for views that are 357 // going away 358 359 // icon changed calls, used when a node or a file type has an icon changed 360 // the icons for the node/file type will be flushed and re-cached during 361 // the next draw 362 void IconChanged(Model *); 363 void IconChanged(const char *mimeType, const char *appSignature); 364 365 bool IsIconFrom(const Model *, const char *mimeType, 366 const char *appSignature) const; 367 // called when metamime database changed to figure out which models 368 // to redraw 369 370 bool IconHitTest(BPoint, const Model *, IconDrawMode , icon_size ); 371 372 // utility calls for building specialized icons 373 BBitmap *MakeSelectedIcon(const BBitmap *normal, icon_size, 374 LazyBitmapAllocator *); 375 376 377 static bool NeedsDeletionNotification(IconSource); 378 379 static IconCache *sIconCache; 380 381 private: 382 383 // shared calls 384 IconCacheEntry *Preload(AutoLock<SimpleIconCache> *nodeCache, 385 AutoLock<SimpleIconCache> *sharedCache, 386 AutoLock<SimpleIconCache> **resultingLockedCache, 387 Model *, IconDrawMode mode, icon_size size, bool permanent); 388 // preload uses lazy locking, returning the cache we decided 389 // to use to get the icon 390 // <resultingLockedCache> may be null if we don't care 391 392 // shared mime-based icon retrieval calls 393 IconCacheEntry *GetIconForPreferredApp(const char *mimeTypeSignature, 394 const char *preferredApp, IconDrawMode mode, icon_size size, 395 LazyBitmapAllocator *, IconCacheEntry *); 396 IconCacheEntry *GetIconFromFileTypes(ModelNodeLazyOpener *, IconSource &source, 397 IconDrawMode mode, icon_size size, LazyBitmapAllocator *, 398 IconCacheEntry *); 399 IconCacheEntry *GetIconFromMetaMime(const char *fileType, IconDrawMode mode, 400 icon_size size, LazyBitmapAllocator *, 401 IconCacheEntry *); 402 IconCacheEntry *GetVolumeIcon(AutoLock<SimpleIconCache> *nodeCache, 403 AutoLock<SimpleIconCache> *sharedCache, 404 AutoLock<SimpleIconCache> **resultingLockedCache, 405 Model *, IconSource &, IconDrawMode mode, 406 icon_size size, LazyBitmapAllocator *); 407 IconCacheEntry *GetRootIcon(AutoLock<SimpleIconCache> *nodeCache, 408 AutoLock<SimpleIconCache> *sharedCache, 409 AutoLock<SimpleIconCache> **resultingLockedCache, 410 Model *, IconSource &, IconDrawMode mode, 411 icon_size size, LazyBitmapAllocator *); 412 IconCacheEntry *GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 413 AutoLock<SimpleIconCache> *sharedCache, 414 AutoLock<SimpleIconCache> **resultingLockedCache, 415 Model *, IconSource &, IconDrawMode mode, 416 icon_size size, LazyBitmapAllocator *); 417 IconCacheEntry *GetNodeIcon(ModelNodeLazyOpener *, 418 AutoLock<SimpleIconCache> *nodeCache, 419 AutoLock<SimpleIconCache> **resultingLockedCache, 420 Model *, IconSource &, IconDrawMode mode, 421 icon_size size, LazyBitmapAllocator *, IconCacheEntry *, bool permanent); 422 IconCacheEntry *GetGenericIcon(AutoLock<SimpleIconCache> *sharedCache, 423 AutoLock<SimpleIconCache> **resultingLockedCache, 424 Model *, IconSource &, IconDrawMode mode, 425 icon_size size, LazyBitmapAllocator *, IconCacheEntry *); 426 IconCacheEntry *GetFallbackIcon(AutoLock<SimpleIconCache> *sharedCacheLocker, 427 AutoLock<SimpleIconCache> **resultingOpenCache, 428 Model *model, IconDrawMode mode, icon_size size, 429 LazyBitmapAllocator *lazyBitmap, IconCacheEntry *entry); 430 431 BBitmap *MakeTransformedIcon(const BBitmap *, icon_size, 432 int32 colorTransformTable [], LazyBitmapAllocator *); 433 434 NodeIconCache fNodeCache; 435 SharedIconCache fSharedCache; 436 437 void InitHiliteTable(); 438 439 int32 fHiliteTable[kColorTransformTableSize]; 440 bool fInitHiliteTable; 441 // on if we still need to initialize the hilite table 442 }; 443 444 445 class LazyBitmapAllocator { 446 // Utility class used when we aren't sure that we will keep a bitmap, 447 // need a bitmap or be able to construct it properly 448 public: 449 LazyBitmapAllocator(icon_size size, 450 color_space colorSpace = kDefaultIconDepth, 451 bool preallocate = false); 452 ~LazyBitmapAllocator(); 453 454 BBitmap *Get(); 455 BBitmap *Adopt(); 456 457 private: 458 BBitmap *fBitmap; 459 icon_size fSize; 460 color_space fColorSpace; 461 }; 462 463 // nothing but inlines after here 464 465 inline const char * 466 SharedCacheEntry::FileType() const 467 { 468 return fFileType.String(); 469 } 470 471 inline const char * 472 SharedCacheEntry::AppSignature() const 473 { 474 return fAppSignature.String(); 475 } 476 477 inline bool 478 IconCache::NeedsDeletionNotification(IconSource from) 479 { 480 return from == kNode; 481 } 482 483 inline IconCacheEntry * 484 SharedIconCache::ResolveIfAlias(IconCacheEntry *entry) const 485 { 486 if (entry->fAliasForIndex < 0) 487 return entry; 488 489 return fHashTable.ElementAt(entry->fAliasForIndex); 490 } 491 492 inline int32 493 SharedIconCache::EntryIndex(const SharedCacheEntry *entry) const 494 { 495 return fHashTable.ElementIndex(entry); 496 } 497 498 } // namespace BPrivate 499 500 using namespace BPrivate; 501 502 #endif 503