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__ 35 #define __NU_ICON_CACHE__ 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 <Mime.h> 44 #include <String.h> 45 46 #include "AutoLock.h" 47 #include "ObjectList.h" 48 #include "OpenHashTable.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 class IconCacheEntry { 119 // aliased entries don't own their icons, just point 120 // to some other entry that does 121 122 // This is used for icons that are defined by a preferred app for 123 // a metamime, types that do not have an icon get to point to 124 // generic, etc. 125 126 public: 127 IconCacheEntry(); 128 ~IconCacheEntry(); 129 130 void SetAliasFor(const SharedIconCache*, const SharedCacheEntry*); 131 static IconCacheEntry* ResolveIfAlias(const SharedIconCache*, 132 IconCacheEntry*); 133 IconCacheEntry* ResolveIfAlias(const SharedIconCache*); 134 135 void SetIcon(BBitmap* bitmap, IconDrawMode mode, icon_size size, 136 bool create = false); 137 138 bool HaveIconBitmap(IconDrawMode mode, icon_size size) const; 139 bool CanConstructBitmap(IconDrawMode mode, icon_size size) const; 140 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode, 141 IconDrawMode &alternate, icon_size size); 142 BBitmap* ConstructBitmap(BBitmap* constructFrom, 143 IconDrawMode requestedMode, IconDrawMode constructFromMode, 144 icon_size size, LazyBitmapAllocator*); 145 BBitmap* ConstructBitmap(IconDrawMode requestedMode, icon_size size, 146 LazyBitmapAllocator*); 147 // same as above, always uses normal icon as source 148 149 bool IconHitTest(BPoint, IconDrawMode, icon_size) const; 150 // given a point, returns true if a non-transparent pixel was hit 151 152 void RetireIcons(BObjectList<BBitmap>* retiredBitmapList); 153 // can't just delete icons, they may be still drawing 154 // async; instead, put them on the retired list and 155 // only delete the list if it grows too much, way after 156 // the icon finishes drawing 157 // 158 // This could fail if we retire a lot of icons (10 * 1024) 159 // while we are drawing them, shouldn't be a practical problem 160 161 protected: 162 163 BBitmap* IconForMode(IconDrawMode mode, icon_size size) const; 164 void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, icon_size size); 165 166 // list of most common icons 167 BBitmap* fLargeIcon; 168 BBitmap* fMiniIcon; 169 BBitmap* fHilitedLargeIcon; 170 BBitmap* fHilitedMiniIcon; 171 int32 fAliasForIndex; 172 173 // list of other icon kinds would be added here 174 175 friend class SharedIconCache; 176 friend class NodeIconCache; 177 }; 178 179 180 class SimpleIconCache { 181 public: 182 SimpleIconCache(const char*); 183 virtual ~SimpleIconCache() {} 184 185 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 186 icon_size size, bool async = false) = 0; 187 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 188 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 189 void* = NULL) = 0; 190 191 bool Lock(); 192 void Unlock(); 193 bool IsLocked() const; 194 195 private: 196 Benaphore fLock; 197 }; 198 199 200 class SharedCacheEntry : public IconCacheEntry { 201 public: 202 SharedCacheEntry(); 203 SharedCacheEntry(const char* fileType, const char* appSignature = 0); 204 205 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 206 bool async = false); 207 208 void Draw(BView*, BPoint, IconDrawMode, icon_size, 209 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 210 211 const char* FileType() const; 212 const char* AppSignature() const; 213 214 // hash table support 215 uint32 Hash() const; 216 static uint32 Hash(const char* fileType, const char* appSignature = 0); 217 bool operator==(const SharedCacheEntry &) const; 218 void SetTo(const char* fileType, const char* appSignature = 0); 219 220 int32 fNext; 221 private: 222 BString fFileType; 223 BString fAppSignature; 224 225 friend class SharedIconCache; 226 }; 227 228 229 class SharedCacheEntryArray : public OpenHashElementArray<SharedCacheEntry> { 230 // SharedIconCache stores all it's elements in this array 231 public: 232 SharedCacheEntryArray(int32 initialSize); 233 SharedCacheEntry* Add(); 234 }; 235 236 237 class SharedIconCache : public SimpleIconCache { 238 // SharedIconCache is used for icons that come from the mime database 239 public: 240 SharedIconCache(); 241 242 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 243 icon_size size, bool async = false); 244 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 245 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 246 247 SharedCacheEntry* FindItem(const char* fileType, 248 const char* appSignature = 0) const; 249 SharedCacheEntry* AddItem(const char* fileType, 250 const char* appSignature = 0); 251 SharedCacheEntry* AddItem(SharedCacheEntry** outstandingEntry, 252 const char* fileType, const char* appSignature = 0); 253 // same as previous AddItem, updates the pointer to outstandingEntry, 254 // because adding to the hash table makes any pending pointer invalid 255 void IconChanged(SharedCacheEntry*); 256 257 void SetAliasFor(IconCacheEntry* alias, 258 const SharedCacheEntry* original) const; 259 IconCacheEntry* ResolveIfAlias(IconCacheEntry* entry) const; 260 int32 EntryIndex(const SharedCacheEntry* entry) const; 261 262 void RemoveAliasesTo(int32 index); 263 264 private: 265 OpenHashTable<SharedCacheEntry, SharedCacheEntryArray> fHashTable; 266 SharedCacheEntryArray fElementArray; 267 BObjectList<BBitmap> fRetiredBitmaps; 268 // icons are drawn asynchronously, can't just delete them right away, 269 // instead have to place them onto the retired bitmap list and wait 270 // for the next sync to delete them 271 }; 272 273 274 class NodeCacheEntry : public IconCacheEntry { 275 public: 276 NodeCacheEntry(bool permanent = false); 277 NodeCacheEntry(const node_ref*, bool permanent = false); 278 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 279 bool async = false); 280 281 void Draw(BView*, BPoint, IconDrawMode, icon_size, 282 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 283 284 const node_ref* Node() const; 285 286 uint32 Hash() const; 287 static uint32 Hash(const node_ref*); 288 bool operator==(const NodeCacheEntry&) const; 289 void SetTo(const node_ref*); 290 void MakePermanent(); 291 bool Permanent() const; 292 293 int32 fNext; 294 private: 295 node_ref fRef; 296 bool fPermanent; 297 // special cache entry that has to be deleted explicitly 298 299 friend class NodeIconCache; 300 }; 301 302 303 class NodeCacheEntryArray : public OpenHashElementArray<NodeCacheEntry> { 304 // NodeIconCache stores all it's elements in this array 305 public: 306 NodeCacheEntryArray(int32 initialSize); 307 NodeCacheEntry* Add(); 308 }; 309 310 311 class NodeIconCache : public SimpleIconCache { 312 // NodeIconCache is used for nodes that define their own icons 313 public: 314 NodeIconCache(); 315 316 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 317 icon_size, bool async = false); 318 319 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 320 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = 0); 321 322 NodeCacheEntry* FindItem(const node_ref*) const; 323 NodeCacheEntry* AddItem(const node_ref*, bool permanent = false); 324 NodeCacheEntry* AddItem(NodeCacheEntry** outstandingEntry, 325 const node_ref*); 326 // same as previous AddItem, updates the pointer to outstandingEntry, 327 // because adding to the hash table makes any pending pointer invalid 328 void Deleting(const node_ref*); 329 // model for this node is getting deleted 330 // (not necessarily the node itself) 331 void Removing(const node_ref*); 332 // used by permanent NodeIconCache entries, when an entry gets deleted 333 void Deleting(const BView*); 334 void IconChanged(const Model*); 335 336 337 void RemoveAliasesTo(int32 index); 338 339 private: 340 OpenHashTable<NodeCacheEntry, NodeCacheEntryArray> fHashTable; 341 NodeCacheEntryArray fElementArray; 342 }; 343 344 345 const int32 kColorTransformTableSize = 256; 346 347 348 class IconCache { 349 public: 350 IconCache(); 351 352 void Draw(Model*, BView*, BPoint where, IconDrawMode mode, 353 icon_size size, bool async = false); 354 // draw an icon for a model, load the icon from the appropriate 355 // location if not cached already 356 357 void SyncDraw(Model*, BView*, BPoint, IconDrawMode, 358 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 359 void* passThruState = 0); 360 // draw an icon for a model, load the icon from the appropriate 361 // location if not cached already; only works for sync draws, 362 // once the call returns, the bitmap may be deleted 363 364 // preload calls used to ensure successive cache hit for the respective 365 // icon, used for common tracker types, etc; Not calling these should only 366 // cause a slowdown 367 void Preload(Model*, IconDrawMode mode, icon_size size, 368 bool permanent = false); 369 status_t Preload(const char* mimeType, IconDrawMode mode, icon_size size); 370 371 void Deleting(const Model*); 372 // hook to manage unloading icons for nodes that are going away 373 void Removing(const Model* model); 374 // used by permanent NodeIconCache entries, when an entry gets 375 // deleted 376 void Deleting(const BView*); 377 // hook to manage deleting draw view caches for views that are 378 // going away 379 380 // icon changed calls, used when a node or a file type has an icon changed 381 // the icons for the node/file type will be flushed and re-cached during 382 // the next draw 383 void IconChanged(Model*); 384 void IconChanged(const char* mimeType, const char* appSignature); 385 386 bool IsIconFrom(const Model*, const char* mimeType, 387 const char* appSignature) const; 388 // called when metamime database changed to figure out which models 389 // to redraw 390 391 bool IconHitTest(BPoint, const Model*, IconDrawMode, icon_size); 392 393 // utility calls for building specialized icons 394 BBitmap* MakeSelectedIcon(const BBitmap* normal, icon_size, 395 LazyBitmapAllocator*); 396 397 static bool NeedsDeletionNotification(IconSource); 398 399 static IconCache* sIconCache; 400 401 private: 402 // shared calls 403 IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache, 404 AutoLock<SimpleIconCache>* sharedCache, 405 AutoLock<SimpleIconCache>** resultingLockedCache, 406 Model*, IconDrawMode mode, icon_size size, bool permanent); 407 // preload uses lazy locking, returning the cache we decided 408 // to use to get the icon 409 // <resultingLockedCache> may be null if we don't care 410 411 // shared mime-based icon retrieval calls 412 IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature, 413 const char* preferredApp, IconDrawMode mode, icon_size size, 414 LazyBitmapAllocator*, IconCacheEntry*); 415 IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*, 416 IconSource &source, IconDrawMode mode, icon_size size, 417 LazyBitmapAllocator*, IconCacheEntry*); 418 IconCacheEntry* GetIconFromMetaMime(const char* fileType, 419 IconDrawMode mode, icon_size size, LazyBitmapAllocator*, 420 IconCacheEntry*); 421 IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache, 422 AutoLock<SimpleIconCache>* sharedCache, 423 AutoLock<SimpleIconCache>** resultingLockedCache, 424 Model*, IconSource&, IconDrawMode mode, 425 icon_size size, LazyBitmapAllocator*); 426 IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache, 427 AutoLock<SimpleIconCache>* sharedCache, 428 AutoLock<SimpleIconCache>** resultingLockedCache, 429 Model*, IconSource&, IconDrawMode mode, 430 icon_size size, LazyBitmapAllocator*); 431 IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 432 AutoLock<SimpleIconCache>* sharedCache, 433 AutoLock<SimpleIconCache>** resultingLockedCache, 434 Model*, IconSource&, IconDrawMode mode, 435 icon_size size, LazyBitmapAllocator*); 436 IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *, 437 AutoLock<SimpleIconCache>* nodeCache, 438 AutoLock<SimpleIconCache>** resultingLockedCache, 439 Model*, IconSource&, IconDrawMode mode, 440 icon_size size, LazyBitmapAllocator*, IconCacheEntry*, 441 bool permanent); 442 IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache, 443 AutoLock<SimpleIconCache>** resultingLockedCache, 444 Model*, IconSource&, IconDrawMode mode, 445 icon_size size, LazyBitmapAllocator*, IconCacheEntry*); 446 IconCacheEntry* GetFallbackIcon( 447 AutoLock<SimpleIconCache>* sharedCacheLocker, 448 AutoLock<SimpleIconCache>** resultingOpenCache, 449 Model* model, IconDrawMode mode, icon_size size, 450 LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry); 451 452 BBitmap* MakeTransformedIcon(const BBitmap*, icon_size, 453 int32 colorTransformTable [], LazyBitmapAllocator*); 454 455 NodeIconCache fNodeCache; 456 SharedIconCache fSharedCache; 457 458 void InitHiliteTable(); 459 460 int32 fHiliteTable[kColorTransformTableSize]; 461 bool fInitHiliteTable; 462 // on if we still need to initialize the hilite table 463 }; 464 465 466 class LazyBitmapAllocator { 467 // Utility class used when we aren't sure that we will keep a bitmap, 468 // need a bitmap or be able to construct it properly 469 public: 470 LazyBitmapAllocator(icon_size size, 471 color_space colorSpace = kDefaultIconDepth, 472 bool preallocate = false); 473 ~LazyBitmapAllocator(); 474 475 BBitmap* Get(); 476 BBitmap* Adopt(); 477 478 private: 479 BBitmap* fBitmap; 480 icon_size fSize; 481 color_space fColorSpace; 482 }; 483 484 485 // inlines follow 486 487 inline const char* 488 SharedCacheEntry::FileType() const 489 { 490 return fFileType.String(); 491 } 492 493 494 inline const char* 495 SharedCacheEntry::AppSignature() const 496 { 497 return fAppSignature.String(); 498 } 499 500 501 inline bool 502 IconCache::NeedsDeletionNotification(IconSource from) 503 { 504 return from == kNode; 505 } 506 507 508 inline IconCacheEntry* 509 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const 510 { 511 if (entry->fAliasForIndex < 0) 512 return entry; 513 514 return fHashTable.ElementAt(entry->fAliasForIndex); 515 } 516 517 518 inline int32 519 SharedIconCache::EntryIndex(const SharedCacheEntry* entry) const 520 { 521 return fHashTable.ElementIndex(entry); 522 } 523 524 } // namespace BPrivate 525 526 using namespace BPrivate; 527 528 #endif 529