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 #ifndef _NU_ICON_CACHE_H 35 #define _NU_ICON_CACHE_H 36 37 38 // Icon cache is used for drawing node icons; it caches icons 39 // and reuses them for successive draws 40 41 42 #include <Bitmap.h> 43 #include <ObjectList.h> 44 #include <Mime.h> 45 #include <String.h> 46 47 #include "AutoLock.h" 48 #include "HashSet.h" 49 #include "Utilities.h" 50 51 52 // Icon cache splits icons into two caches - the shared cache, likely to 53 // get the most hits and the node cache. Every icon that is found in a 54 // mime-based structure goes into the shared cache, only files that have 55 // their own private icon use the node cache; 56 // Entries are only deleted from the shared cache if an icon for a mime type 57 // changes, this makes async icon drawing easier. Node cache deletes it's 58 // entries whenever a file gets deleted. 59 60 // if a view ever uses the cache to draw in async mode, it needs to call 61 // it when it is being destroyed 62 63 namespace BPrivate { 64 65 class Model; 66 class ModelNodeLazyOpener; 67 class LazyBitmapAllocator; 68 class SharedIconCache; 69 class SharedCacheEntry; 70 71 enum IconDrawMode { 72 // Different states of icon drawing 73 kSelected = 0x01, 74 kNotFocused = 0x02, // Tracker window 75 kOpen = 0x04, // open folder, trash 76 kNotEmpty = 0x08, // full trash 77 kDisabled = 0x10, // inactive nav menu entry 78 kActive = 0x20, // active home dir, boot volume 79 kLink = 0x40, // symbolic link 80 kTrackerSpecialized = 0x80, 81 82 // some common combinations 83 kNormalIcon = 0, 84 kSelectedIcon = kSelected, 85 kSelectedInBackgroundIcon = kSelected | kNotFocused, 86 kOpenIcon = kOpen, 87 kOpenSelectedIcon = kSelected | kOpen, 88 kOpenSelectedInBackgroundIcon = kSelected | kNotFocused | kOpen, 89 kFullIcon = kNotEmpty, 90 kFullSelectedIcon = kNotEmpty | kOpen, 91 kDimmedIcon 92 }; 93 94 95 #define NORMAL_ICON_ONLY kNormalIcon 96 // replace use of these defines with mode once the respective getters 97 // can get non-plain icons 98 99 100 // Where did an icon come from 101 enum IconSource { 102 kUnknownSource, 103 kUnknownNotFromNode, // icon origin not known but determined not 104 // to be from the node itself 105 kTrackerDefault, // file has no type, Tracker provides generic, 106 // folder, symlink or app 107 kTrackerSupplied, // home directory, boot volume, trash, etc. 108 kMetaMime, // from BMimeType 109 kPreferredAppForType, // have a preferred application for a type, 110 // has an icon 111 kPreferredAppForNode, // have a preferred application for this node, 112 // has an icon 113 kVolume, 114 kNode 115 }; 116 117 118 template<typename Class> 119 struct SelfHashing { 120 typedef typename Class::HashKeyType KeyType; 121 typedef Class ValueType; 122 123 size_t HashKey(KeyType key) const 124 { 125 return Class::Hash(key); 126 } 127 128 size_t Hash(ValueType* value) const 129 { 130 return value->Hash(); 131 } 132 133 bool Compare(KeyType key, ValueType* value) const 134 { 135 return *value == key; 136 } 137 138 ValueType*& GetLink(ValueType* value) const 139 { 140 return value->HashNext(); 141 } 142 }; 143 144 145 class IconCacheEntry { 146 // aliased entries don't own their icons, just point 147 // to some other entry that does 148 149 // This is used for icons that are defined by a preferred app for 150 // a metamime, types that do not have an icon get to point to 151 // generic, etc. 152 153 public: 154 IconCacheEntry(); 155 ~IconCacheEntry(); 156 157 void SetAliasFor(const SharedIconCache* sharedCache, 158 const SharedCacheEntry* entry); 159 static IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache, 160 IconCacheEntry* entry); 161 IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache); 162 163 void SetIcon(BBitmap* bitmap, IconDrawMode mode, icon_size size, 164 bool create = false); 165 166 bool HaveIconBitmap(IconDrawMode mode, icon_size size) const; 167 bool CanConstructBitmap(IconDrawMode mode, icon_size size) const; 168 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode, 169 IconDrawMode &alternate, icon_size size); 170 BBitmap* ConstructBitmap(BBitmap* constructFrom, 171 IconDrawMode requestedMode, IconDrawMode constructFromMode, 172 icon_size size, LazyBitmapAllocator*); 173 BBitmap* ConstructBitmap(IconDrawMode requestedMode, icon_size size, 174 LazyBitmapAllocator*); 175 // same as above, always uses normal icon as source 176 177 bool IconHitTest(BPoint, IconDrawMode, icon_size) const; 178 // given a point, returns true if a non-transparent pixel was hit 179 180 void RetireIcons(BObjectList<BBitmap>* retiredBitmapList); 181 // can't just delete icons, they may be still drawing 182 // async; instead, put them on the retired list and 183 // only delete the list if it grows too much, way after 184 // the icon finishes drawing 185 // 186 // This could fail if we retire a lot of icons (10 * 1024) 187 // while we are drawing them, shouldn't be a practical problem 188 189 protected: 190 BBitmap* IconForMode(IconDrawMode mode, icon_size size) const; 191 void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, icon_size size); 192 193 // list of most common icons 194 BBitmap* fLargeIcon; 195 BBitmap* fHighlightedLargeIcon; 196 BBitmap* fMiniIcon; 197 BBitmap* fHighlightedMiniIcon; 198 199 const IconCacheEntry* fAliasTo; 200 201 // list of other icon kinds would be added here 202 203 friend class SharedIconCache; 204 friend class NodeIconCache; 205 }; 206 207 208 class SimpleIconCache { 209 public: 210 SimpleIconCache(const char*); 211 virtual ~SimpleIconCache() {} 212 213 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 214 icon_size size, bool async = false) = 0; 215 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 216 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 217 void* = NULL) = 0; 218 219 bool Lock(); 220 void Unlock(); 221 bool IsLocked() const; 222 223 private: 224 Benaphore fLock; 225 }; 226 227 228 class SharedCacheEntry : public IconCacheEntry { 229 public: 230 SharedCacheEntry(); 231 SharedCacheEntry(const char* fileType, const char* appSignature = 0); 232 233 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 234 bool async = false); 235 236 void Draw(BView*, BPoint, IconDrawMode, icon_size, 237 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 238 239 const char* FileType() const; 240 const char* AppSignature() const; 241 242 public: 243 // hash table support 244 struct TypeAndSignature { 245 const char* type, *signature; 246 TypeAndSignature(const char* t, const char* s) 247 : type(t), signature(s) {} 248 }; 249 typedef TypeAndSignature HashKeyType; 250 static size_t Hash(const TypeAndSignature& typeAndSignature); 251 252 size_t Hash() const; 253 SharedCacheEntry*& HashNext() { return fNext; } 254 bool operator==(const TypeAndSignature& typeAndSignature) const; 255 256 private: 257 SharedCacheEntry* fNext; 258 259 BString fFileType; 260 BString fAppSignature; 261 262 friend class SharedIconCache; 263 }; 264 265 266 class SharedIconCache : public SimpleIconCache { 267 // SharedIconCache is used for icons that come from the mime database 268 public: 269 SharedIconCache(); 270 271 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 272 icon_size size, bool async = false); 273 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 274 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 275 276 SharedCacheEntry* FindItem(const char* fileType, 277 const char* appSignature = 0) const; 278 SharedCacheEntry* AddItem(const char* fileType, 279 const char* appSignature = 0); 280 void IconChanged(SharedCacheEntry*); 281 282 void SetAliasFor(IconCacheEntry* entry, 283 const SharedCacheEntry* original) const; 284 IconCacheEntry* ResolveIfAlias(IconCacheEntry* entry) const; 285 286 void RemoveAliasesTo(SharedCacheEntry* alias); 287 288 private: 289 typedef BOpenHashTable<SelfHashing<SharedCacheEntry> > EntryHashTable; 290 EntryHashTable fHashTable; 291 292 BObjectList<BBitmap> fRetiredBitmaps; 293 // icons are drawn asynchronously, can't just delete them right away, 294 // instead have to place them onto the retired bitmap list and wait 295 // for the next sync to delete them 296 }; 297 298 299 class NodeCacheEntry : public IconCacheEntry { 300 public: 301 NodeCacheEntry(bool permanent = false); 302 NodeCacheEntry(const node_ref*, bool permanent = false); 303 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 304 bool async = false); 305 306 void Draw(BView*, BPoint, IconDrawMode, icon_size, 307 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 308 309 const node_ref* Node() const; 310 311 bool Permanent() const; 312 313 public: 314 // hash table support 315 typedef const node_ref* HashKeyType; 316 static size_t Hash(const node_ref* node); 317 318 size_t Hash() const; 319 NodeCacheEntry*& HashNext() { return fNext; } 320 bool operator==(const node_ref* ref) const; 321 322 private: 323 NodeCacheEntry* fNext; 324 325 node_ref fRef; 326 bool fPermanent; 327 // special cache entry that has to be deleted explicitly 328 329 friend class NodeIconCache; 330 }; 331 332 333 class NodeIconCache : public SimpleIconCache { 334 // NodeIconCache is used for nodes that define their own icons 335 public: 336 NodeIconCache(); 337 338 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 339 icon_size, bool async = false); 340 341 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 342 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = 0); 343 344 NodeCacheEntry* FindItem(const node_ref*) const; 345 NodeCacheEntry* AddItem(const node_ref*, bool permanent = false); 346 void Deleting(const node_ref*); 347 // model for this node is getting deleted 348 // (not necessarily the node itself) 349 void Removing(const node_ref*); 350 // used by permanent NodeIconCache entries, when an entry gets deleted 351 void Deleting(const BView*); 352 void IconChanged(const Model*); 353 354 void RemoveAliasesTo(SharedCacheEntry* alias); 355 356 private: 357 typedef BOpenHashTable<SelfHashing<NodeCacheEntry> > EntryHashTable; 358 EntryHashTable fHashTable; 359 }; 360 361 362 const int32 kColorTransformTableSize = 256; 363 364 365 class IconCache { 366 public: 367 IconCache(); 368 369 void Draw(Model*, BView*, BPoint where, IconDrawMode mode, 370 icon_size size, bool async = false); 371 // draw an icon for a model, load the icon from the appropriate 372 // location if not cached already 373 374 void SyncDraw(Model*, BView*, BPoint, IconDrawMode, 375 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 376 void* passThruState = 0); 377 // draw an icon for a model, load the icon from the appropriate 378 // location if not cached already; only works for sync draws, 379 // once the call returns, the bitmap may be deleted 380 381 // preload calls used to ensure successive cache hit for the respective 382 // icon, used for common tracker types, etc; Not calling these should only 383 // cause a slowdown 384 void Preload(Model*, IconDrawMode mode, icon_size size, 385 bool permanent = false); 386 status_t Preload(const char* mimeType, IconDrawMode mode, icon_size size); 387 388 void Deleting(const Model*); 389 // hook to manage unloading icons for nodes that are going away 390 void Removing(const Model* model); 391 // used by permanent NodeIconCache entries, when an entry gets 392 // deleted 393 void Deleting(const BView*); 394 // hook to manage deleting draw view caches for views that are 395 // going away 396 397 // icon changed calls, used when a node or a file type has an icon changed 398 // the icons for the node/file type will be flushed and re-cached during 399 // the next draw 400 void IconChanged(Model*); 401 void IconChanged(const char* mimeType, const char* appSignature); 402 403 bool IsIconFrom(const Model*, const char* mimeType, 404 const char* appSignature) const; 405 // called when metamime database changed to figure out which models 406 // to redraw 407 408 bool IconHitTest(BPoint, const Model*, IconDrawMode, icon_size); 409 410 // utility calls for building specialized icons 411 BBitmap* MakeSelectedIcon(const BBitmap* normal, icon_size, 412 LazyBitmapAllocator*); 413 414 static bool NeedsDeletionNotification(IconSource); 415 416 static IconCache* sIconCache; 417 418 private: 419 // shared calls 420 IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache, 421 AutoLock<SimpleIconCache>* sharedCache, 422 AutoLock<SimpleIconCache>** resultingLockedCache, 423 Model*, IconDrawMode mode, icon_size size, bool permanent); 424 // preload uses lazy locking, returning the cache we decided 425 // to use to get the icon 426 // <resultingLockedCache> may be null if we don't care 427 428 // shared mime-based icon retrieval calls 429 IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature, 430 const char* preferredApp, IconDrawMode mode, icon_size size, 431 LazyBitmapAllocator*, IconCacheEntry*); 432 IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*, 433 IconSource &source, IconDrawMode mode, icon_size size, 434 LazyBitmapAllocator*, IconCacheEntry*); 435 IconCacheEntry* GetIconFromMetaMime(const char* fileType, 436 IconDrawMode mode, icon_size size, LazyBitmapAllocator*, 437 IconCacheEntry*); 438 IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache, 439 AutoLock<SimpleIconCache>* sharedCache, 440 AutoLock<SimpleIconCache>** resultingLockedCache, 441 Model*, IconSource&, IconDrawMode mode, 442 icon_size size, LazyBitmapAllocator*); 443 IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache, 444 AutoLock<SimpleIconCache>* sharedCache, 445 AutoLock<SimpleIconCache>** resultingLockedCache, 446 Model*, IconSource&, IconDrawMode mode, 447 icon_size size, LazyBitmapAllocator*); 448 IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 449 AutoLock<SimpleIconCache>* sharedCache, 450 AutoLock<SimpleIconCache>** resultingLockedCache, 451 Model*, IconSource&, IconDrawMode mode, 452 icon_size size, LazyBitmapAllocator*); 453 IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *, 454 AutoLock<SimpleIconCache>* nodeCache, 455 AutoLock<SimpleIconCache>** resultingLockedCache, 456 Model*, IconSource&, IconDrawMode mode, 457 icon_size size, LazyBitmapAllocator*, IconCacheEntry*, 458 bool permanent); 459 IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache, 460 AutoLock<SimpleIconCache>** resultingLockedCache, 461 Model*, IconSource&, IconDrawMode mode, 462 icon_size size, LazyBitmapAllocator*, IconCacheEntry*); 463 IconCacheEntry* GetFallbackIcon( 464 AutoLock<SimpleIconCache>* sharedCacheLocker, 465 AutoLock<SimpleIconCache>** resultingOpenCache, 466 Model* model, IconDrawMode mode, icon_size size, 467 LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry); 468 469 BBitmap* MakeTransformedIcon(const BBitmap*, icon_size, 470 int32 colorTransformTable [], LazyBitmapAllocator*); 471 472 NodeIconCache fNodeCache; 473 SharedIconCache fSharedCache; 474 475 void InitHighlightTable(); 476 477 int32 fHighlightTable[kColorTransformTableSize]; 478 bool fInitHighlightTable; 479 // whether or not we need to initialize the highlight table 480 }; 481 482 483 class LazyBitmapAllocator { 484 // Utility class used when we aren't sure that we will keep a bitmap, 485 // need a bitmap or be able to construct it properly 486 public: 487 LazyBitmapAllocator(icon_size size, 488 color_space colorSpace = kDefaultIconDepth, 489 bool preallocate = false); 490 ~LazyBitmapAllocator(); 491 492 BBitmap* Get(); 493 BBitmap* Adopt(); 494 495 private: 496 BBitmap* fBitmap; 497 icon_size fSize; 498 color_space fColorSpace; 499 }; 500 501 502 // inlines follow 503 504 inline const char* 505 SharedCacheEntry::FileType() const 506 { 507 return fFileType.String(); 508 } 509 510 511 inline const char* 512 SharedCacheEntry::AppSignature() const 513 { 514 return fAppSignature.String(); 515 } 516 517 518 inline bool 519 IconCache::NeedsDeletionNotification(IconSource from) 520 { 521 return from == kNode; 522 } 523 524 525 inline IconCacheEntry* 526 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const 527 { 528 if (entry->fAliasTo == NULL) 529 return entry; 530 531 return const_cast<IconCacheEntry*>(entry->fAliasTo); 532 } 533 534 535 } // namespace BPrivate 536 537 using namespace BPrivate; 538 539 540 #endif // _NU_ICON_CACHE_H 541