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 class GenerateThumbnailJob;
71
72 enum IconDrawMode {
73 // Different states of icon drawing
74 kSelected = 0x01,
75 kNotFocused = 0x02, // Tracker window
76 kOpen = 0x04, // open folder, trash
77 kNotEmpty = 0x08, // full trash
78 kDisabled = 0x10, // inactive nav menu entry
79 kActive = 0x20, // active home dir, boot volume
80 kLink = 0x40, // symbolic link
81 kTrackerSpecialized = 0x80,
82
83 // some common combinations
84 kNormalIcon = 0,
85 kSelectedIcon = kSelected,
86 kSelectedInBackgroundIcon = kSelected | kNotFocused,
87 kOpenIcon = kOpen,
88 kOpenSelectedIcon = kSelected | kOpen,
89 kOpenSelectedInBackgroundIcon = kSelected | kNotFocused | kOpen,
90 kFullIcon = kNotEmpty,
91 kFullSelectedIcon = kNotEmpty | kOpen,
92 kDimmedIcon
93 };
94
95
96 #define NORMAL_ICON_ONLY kNormalIcon
97 // replace use of these defines with mode once the respective getters
98 // can get non-plain icons
99
100
101 // Where did an icon come from
102 enum IconSource {
103 kUnknownSource,
104 kUnknownNotFromNode, // icon origin not known but determined not
105 // to be from the node itself
106 kTrackerDefault, // file has no type, Tracker provides generic,
107 // folder, symlink or app
108 kTrackerSupplied, // home directory, boot volume, trash, etc.
109 kMetaMime, // from BMimeType
110 kPreferredAppForType, // have a preferred application for a type,
111 // has an icon
112 kPreferredAppForNode, // have a preferred application for this node,
113 // has an icon
114 kVolume,
115 kNode
116 };
117
118
119 template<typename Class>
120 struct SelfHashing {
121 typedef typename Class::HashKeyType KeyType;
122 typedef Class ValueType;
123
HashKeySelfHashing124 size_t HashKey(KeyType key) const
125 {
126 return Class::Hash(key);
127 }
128
HashSelfHashing129 size_t Hash(ValueType* value) const
130 {
131 return value->Hash();
132 }
133
CompareSelfHashing134 bool Compare(KeyType key, ValueType* value) const
135 {
136 return *value == key;
137 }
138
GetLinkSelfHashing139 ValueType*& GetLink(ValueType* value) const
140 {
141 return value->HashNext();
142 }
143 };
144
145
146 class IconCacheEntry {
147 // aliased entries don't own their icons, just point
148 // to some other entry that does
149
150 // This is used for icons that are defined by a preferred app for
151 // a metamime, types that do not have an icon get to point to
152 // generic, etc.
153
154 public:
155 IconCacheEntry();
156 ~IconCacheEntry();
157
158 void SetAliasFor(const SharedIconCache* sharedCache,
159 const SharedCacheEntry* entry);
160 static IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache,
161 IconCacheEntry* entry);
162 IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache);
163
164 void SetIcon(BBitmap* bitmap, IconDrawMode mode, BSize size);
165
166 bool HaveIconBitmap(IconDrawMode mode, BSize size) const;
167 bool CanConstructBitmap(IconDrawMode mode, BSize size) const;
168 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode,
169 IconDrawMode &alternate, BSize size);
170 BBitmap* ConstructBitmap(BBitmap* constructFrom,
171 IconDrawMode requestedMode, IconDrawMode constructFromMode,
172 BSize size, LazyBitmapAllocator*);
173 BBitmap* ConstructBitmap(IconDrawMode requestedMode, BSize size,
174 LazyBitmapAllocator*);
175 // same as above, always uses normal icon as source
176
177 bool IconHitTest(BPoint, IconDrawMode, BSize) 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, BSize size) const;
191 void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, BSize 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*);
~SimpleIconCache()211 virtual ~SimpleIconCache() {}
212
213 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode,
214 BSize size, bool async = false) = 0;
215 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
216 BSize, 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, BSize size,
234 bool async = false);
235
236 void Draw(BView*, BPoint, IconDrawMode, BSize,
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;
TypeAndSignatureTypeAndSignature246 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;
HashNext()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 BSize size, bool async = false);
273 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
274 BSize, 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, BSize size,
304 bool async = false);
305
306 void Draw(BView*, BPoint, IconDrawMode, BSize,
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;
HashNext()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 BSize, bool async = false);
340
341 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
342 BSize, 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 BSize 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 BSize, 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, BSize size,
385 bool permanent = false);
386 status_t Preload(const char* mimeType, IconDrawMode mode, BSize 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, BSize);
409
410 // utility calls for building specialized icons
411 BBitmap* MakeSelectedIcon(const BBitmap* normal, BSize,
412 LazyBitmapAllocator*);
413
414 static bool NeedsDeletionNotification(IconSource);
415
416 static IconCache* sIconCache;
417 static BSize sMiniIconSize;
418
419 private:
420 // shared calls
421 IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache,
422 AutoLock<SimpleIconCache>* sharedCache,
423 AutoLock<SimpleIconCache>** resultingLockedCache,
424 Model*, IconDrawMode mode, BSize size, bool permanent);
425 // preload uses lazy locking, returning the cache we decided
426 // to use to get the icon
427 // <resultingLockedCache> may be null if we don't care
428
429 // shared mime-based icon retrieval calls
430 IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature,
431 const char* preferredApp, IconDrawMode mode, BSize size,
432 LazyBitmapAllocator*, IconCacheEntry*);
433 IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*,
434 IconSource &source, IconDrawMode mode, BSize size,
435 LazyBitmapAllocator*, IconCacheEntry*);
436 IconCacheEntry* GetIconFromMetaMime(const char* fileType,
437 IconDrawMode mode, BSize size, LazyBitmapAllocator*,
438 IconCacheEntry*);
439 IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache,
440 AutoLock<SimpleIconCache>* sharedCache,
441 AutoLock<SimpleIconCache>** resultingLockedCache,
442 Model*, IconSource&, IconDrawMode mode,
443 BSize size, LazyBitmapAllocator*);
444 IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache,
445 AutoLock<SimpleIconCache>* sharedCache,
446 AutoLock<SimpleIconCache>** resultingLockedCache,
447 Model*, IconSource&, IconDrawMode mode,
448 BSize size, LazyBitmapAllocator*);
449 IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache,
450 AutoLock<SimpleIconCache>* sharedCache,
451 AutoLock<SimpleIconCache>** resultingLockedCache,
452 Model*, IconSource&, IconDrawMode mode,
453 BSize size, LazyBitmapAllocator*);
454 IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *,
455 AutoLock<SimpleIconCache>* nodeCache,
456 AutoLock<SimpleIconCache>** resultingLockedCache,
457 Model*, IconSource&, IconDrawMode mode,
458 BSize size, LazyBitmapAllocator*, IconCacheEntry*,
459 bool permanent);
460 IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache,
461 AutoLock<SimpleIconCache>** resultingLockedCache,
462 Model*, IconSource&, IconDrawMode mode,
463 BSize size, LazyBitmapAllocator*, IconCacheEntry*);
464 IconCacheEntry* GetFallbackIcon(
465 AutoLock<SimpleIconCache>* sharedCacheLocker,
466 AutoLock<SimpleIconCache>** resultingOpenCache,
467 Model* model, IconDrawMode mode, BSize size,
468 LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry);
469
470 BBitmap* MakeTransformedIcon(const BBitmap*, BSize,
471 int32 colorTransformTable [], LazyBitmapAllocator*);
472
473 private:
474 NodeIconCache fNodeCache;
475 SharedIconCache fSharedCache;
476
477 void InitHighlightTable();
478
479 int32 fHighlightTable[kColorTransformTableSize];
480 bool fInitHighlightTable;
481 // whether or not we need to initialize the highlight table
482
483 friend class BPrivate::GenerateThumbnailJob;
484 };
485
486
487 class LazyBitmapAllocator {
488 // Utility class used when we aren't sure that we will keep a bitmap,
489 // need a bitmap or be able to construct it properly
490 public:
491 LazyBitmapAllocator(BSize size,
492 color_space colorSpace = kDefaultIconDepth,
493 bool preallocate = false);
494 ~LazyBitmapAllocator();
495
496 BBitmap* Get();
497 BBitmap* Adopt();
498
499 private:
500 BBitmap* fBitmap;
501 BSize fSize;
502 color_space fColorSpace;
503 };
504
505
506 // inlines follow
507
508 inline const char*
FileType()509 SharedCacheEntry::FileType() const
510 {
511 return fFileType.String();
512 }
513
514
515 inline const char*
AppSignature()516 SharedCacheEntry::AppSignature() const
517 {
518 return fAppSignature.String();
519 }
520
521
522 inline bool
NeedsDeletionNotification(IconSource from)523 IconCache::NeedsDeletionNotification(IconSource from)
524 {
525 return from == kNode;
526 }
527
528
529 inline IconCacheEntry*
ResolveIfAlias(IconCacheEntry * entry)530 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const
531 {
532 if (entry->fAliasTo == NULL)
533 return entry;
534
535 return const_cast<IconCacheEntry*>(entry->fAliasTo);
536 }
537
538
539 } // namespace BPrivate
540
541 using namespace BPrivate;
542
543
544 #endif // _NU_ICON_CACHE_H
545