xref: /haiku/src/kits/tracker/IconCache.h (revision 8c78892580f132d10e624aef96f835df8d94bf19)
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