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 // Difrent 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 an 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 icon 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 315 // deleted 316 void Deleting(const BView *); 317 void IconChanged(const Model *); 318 319 320 void RemoveAliasesTo(int32 index); 321 322 private: 323 OpenHashTable<NodeCacheEntry, NodeCacheEntryArray> fHashTable; 324 NodeCacheEntryArray fElementArray; 325 }; 326 327 const int32 kColorTransformTableSize = 256; 328 329 class IconCache { 330 public: 331 IconCache(); 332 333 void Draw(Model *, BView *, BPoint where, IconDrawMode mode, 334 icon_size size, bool async = false); 335 // draw an icon for a model, load the icon from the appropriate 336 // location if not cached already 337 338 void SyncDraw(Model *, BView *, BPoint , IconDrawMode , 339 icon_size , void (*)(BView *, BPoint, BBitmap *, void *), 340 void *passThruState = 0); 341 // draw an icon for a model, load the icon from the appropriate 342 // location if not cached already; only works for sync draws, 343 // once the call returns, the bitmap may be deleted 344 345 // preload calls used to ensure successive cache hit for the respective 346 // icon, used for common tracker types, etc; Not calling these should only 347 // cause a slowdown 348 void Preload(Model *, IconDrawMode mode, icon_size size, bool permanent = false); 349 status_t Preload(const char *mimeType, IconDrawMode mode, icon_size size); 350 351 void Deleting(const Model *); 352 // hook to manage unloading icons for nodes that are going away 353 void Removing(const Model *model); 354 // used by permanent NodeIconCache entries, when an entry gets 355 // deleted 356 void Deleting(const BView *); 357 // hook to manage deleting draw view caches for views that are 358 // going away 359 360 // icon changed calls, used when a node or a file type has an icon changed 361 // the icons for the node/file type will be flushed and re-cached during 362 // the next draw 363 void IconChanged(Model *); 364 void IconChanged(const char *mimeType, const char *appSignature); 365 366 bool IsIconFrom(const Model *, const char *mimeType, 367 const char *appSignature) const; 368 // called when metamime database changed to figure out which models 369 // to redraw 370 371 bool IconHitTest(BPoint, const Model *, IconDrawMode , icon_size ); 372 373 // utility calls for building specialized icons 374 BBitmap *MakeSelectedIcon(const BBitmap *normal, icon_size, 375 LazyBitmapAllocator *); 376 377 378 static bool NeedsDeletionNotification(IconSource); 379 380 static IconCache *sIconCache; 381 382 private: 383 384 // shared calls 385 IconCacheEntry *Preload(AutoLock<SimpleIconCache> *nodeCache, 386 AutoLock<SimpleIconCache> *sharedCache, 387 AutoLock<SimpleIconCache> **resultingLockedCache, 388 Model *, IconDrawMode mode, icon_size size, bool permanent); 389 // preload uses lazy locking, returning the cache we decided 390 // to use to get the icon 391 // <resultingLockedCache> may be null if we don't care 392 393 // shared mime-based icon retrieval calls 394 IconCacheEntry *GetIconForPreferredApp(const char *mimeTypeSignature, 395 const char *preferredApp, IconDrawMode mode, icon_size size, 396 LazyBitmapAllocator *, IconCacheEntry *); 397 IconCacheEntry *GetIconFromFileTypes(ModelNodeLazyOpener *, IconSource &source, 398 IconDrawMode mode, icon_size size, LazyBitmapAllocator *, 399 IconCacheEntry *); 400 IconCacheEntry *GetIconFromMetaMime(const char *fileType, IconDrawMode mode, 401 icon_size size, LazyBitmapAllocator *, 402 IconCacheEntry *); 403 IconCacheEntry *GetVolumeIcon(AutoLock<SimpleIconCache> *nodeCache, 404 AutoLock<SimpleIconCache> *sharedCache, 405 AutoLock<SimpleIconCache> **resultingLockedCache, 406 Model *, IconSource &, IconDrawMode mode, 407 icon_size size, LazyBitmapAllocator *); 408 IconCacheEntry *GetRootIcon(AutoLock<SimpleIconCache> *nodeCache, 409 AutoLock<SimpleIconCache> *sharedCache, 410 AutoLock<SimpleIconCache> **resultingLockedCache, 411 Model *, IconSource &, IconDrawMode mode, 412 icon_size size, LazyBitmapAllocator *); 413 IconCacheEntry *GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 414 AutoLock<SimpleIconCache> *sharedCache, 415 AutoLock<SimpleIconCache> **resultingLockedCache, 416 Model *, IconSource &, IconDrawMode mode, 417 icon_size size, LazyBitmapAllocator *); 418 IconCacheEntry *GetNodeIcon(ModelNodeLazyOpener *, 419 AutoLock<SimpleIconCache> *nodeCache, 420 AutoLock<SimpleIconCache> **resultingLockedCache, 421 Model *, IconSource &, IconDrawMode mode, 422 icon_size size, LazyBitmapAllocator *, IconCacheEntry *, bool permanent); 423 IconCacheEntry *GetGenericIcon(AutoLock<SimpleIconCache> *sharedCache, 424 AutoLock<SimpleIconCache> **resultingLockedCache, 425 Model *, IconSource &, IconDrawMode mode, 426 icon_size size, LazyBitmapAllocator *, IconCacheEntry *); 427 IconCacheEntry *GetFallbackIcon(AutoLock<SimpleIconCache> *sharedCacheLocker, 428 AutoLock<SimpleIconCache> **resultingOpenCache, 429 Model *model, IconDrawMode mode, icon_size size, 430 LazyBitmapAllocator *lazyBitmap, IconCacheEntry *entry); 431 432 BBitmap *MakeTransformedIcon(const BBitmap *, icon_size, 433 int32 colorTransformTable [], LazyBitmapAllocator *); 434 435 NodeIconCache fNodeCache; 436 SharedIconCache fSharedCache; 437 438 void InitHiliteTable(); 439 440 int32 fHiliteTable[kColorTransformTableSize]; 441 bool fInitHiliteTable; 442 // on if we still need to initialize the hilite table 443 }; 444 445 446 class LazyBitmapAllocator { 447 // Utility class used when we aren't sure that we will keep a bitmap, 448 // need a bitmap or be able to construct it properly 449 public: 450 LazyBitmapAllocator(icon_size size, 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