xref: /haiku/src/kits/tracker/IconCache.h (revision ca8ed5ea660fb6275799a3b7f138b201c41a667b)
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 "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* sharedCache,
131 		const SharedCacheEntry* entry);
132 	static IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache,
133 		IconCacheEntry* entry);
134 	IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache);
135 
136 	void SetIcon(BBitmap* bitmap, IconDrawMode mode, icon_size size,
137 		bool create = false);
138 
139 	bool HaveIconBitmap(IconDrawMode mode, icon_size size) const;
140 	bool CanConstructBitmap(IconDrawMode mode, icon_size size) const;
141 	static bool AlternateModeForIconConstructing(IconDrawMode requestedMode,
142 		IconDrawMode &alternate, icon_size size);
143 	BBitmap* ConstructBitmap(BBitmap* constructFrom,
144 		IconDrawMode requestedMode, IconDrawMode constructFromMode,
145 		icon_size size, LazyBitmapAllocator*);
146 	BBitmap* ConstructBitmap(IconDrawMode requestedMode, icon_size size,
147 		LazyBitmapAllocator*);
148 		// same as above, always uses normal icon as source
149 
150 	bool IconHitTest(BPoint, IconDrawMode, icon_size) const;
151 		// given a point, returns true if a non-transparent pixel was hit
152 
153 	void RetireIcons(BObjectList<BBitmap>* retiredBitmapList);
154 		// can't just delete icons, they may be still drawing
155 		// async; instead, put them on the retired list and
156 		// only delete the list if it grows too much, way after
157 		// the icon finishes drawing
158 		//
159 		// This could fail if we retire a lot of icons (10 * 1024)
160 		// while we are drawing them, shouldn't be a practical problem
161 
162 protected:
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* fHighlightedLargeIcon;
169 	BBitmap* fMiniIcon;
170 	BBitmap* fHighlightedMiniIcon;
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* entry,
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 	SharedCacheEntryArray fElementArray;
266 	OpenHashTable<SharedCacheEntry, SharedCacheEntryArray> fHashTable;
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 	void RemoveAliasesTo(int32 index);
337 
338 private:
339 	NodeCacheEntryArray fElementArray;
340 	OpenHashTable<NodeCacheEntry, NodeCacheEntryArray> fHashTable;
341 };
342 
343 
344 const int32 kColorTransformTableSize = 256;
345 
346 
347 class IconCache {
348 public:
349 	IconCache();
350 
351 	void Draw(Model*, BView*, BPoint where, IconDrawMode mode,
352 		icon_size size, bool async = false);
353 		// draw an icon for a model, load the icon from the appropriate
354 		// location if not cached already
355 
356 	void SyncDraw(Model*, BView*, BPoint, IconDrawMode,
357 		icon_size, void (*)(BView*, BPoint, BBitmap*, void*),
358 		void* passThruState = 0);
359 		// draw an icon for a model, load the icon from the appropriate
360 		// location if not cached already; only works for sync draws,
361 		// once the call returns, the bitmap may be deleted
362 
363 	// preload calls used to ensure successive cache hit for the respective
364 	// icon, used for common tracker types, etc; Not calling these should only
365 	// cause a slowdown
366 	void Preload(Model*, IconDrawMode mode, icon_size size,
367 		bool permanent = false);
368 	status_t Preload(const char* mimeType, IconDrawMode mode, icon_size size);
369 
370 	void Deleting(const Model*);
371 		// hook to manage unloading icons for nodes that are going away
372 	void Removing(const Model* model);
373 		// used by permanent NodeIconCache entries, when an entry gets
374 		// deleted
375 	void Deleting(const BView*);
376 		// hook to manage deleting draw view caches for views that are
377 		// going away
378 
379 	// icon changed calls, used when a node or a file type has an icon changed
380 	// the icons for the node/file type will be flushed and re-cached during
381 	// the next draw
382 	void IconChanged(Model*);
383 	void IconChanged(const char* mimeType, const char* appSignature);
384 
385 	bool IsIconFrom(const Model*, const char* mimeType,
386 		const char* appSignature) const;
387 		// called when metamime database changed to figure out which models
388 		// to redraw
389 
390 	bool IconHitTest(BPoint, const Model*, IconDrawMode, icon_size);
391 
392 	// utility calls for building specialized icons
393 	BBitmap* MakeSelectedIcon(const BBitmap* normal, icon_size,
394 		LazyBitmapAllocator*);
395 
396 	static bool NeedsDeletionNotification(IconSource);
397 
398 	static IconCache* sIconCache;
399 
400 private:
401 	// shared calls
402 	IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache,
403 		AutoLock<SimpleIconCache>* sharedCache,
404 		AutoLock<SimpleIconCache>** resultingLockedCache,
405 		Model*, IconDrawMode mode, icon_size size, bool permanent);
406 		// preload uses lazy locking, returning the cache we decided
407 		// to use to get the icon
408 		// <resultingLockedCache> may be null if we don't care
409 
410 	// shared mime-based icon retrieval calls
411 	IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature,
412 		const char* preferredApp, IconDrawMode mode, icon_size size,
413 		 LazyBitmapAllocator*, IconCacheEntry*);
414 	IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*,
415 		IconSource &source, IconDrawMode mode, icon_size size,
416 		LazyBitmapAllocator*, IconCacheEntry*);
417 	IconCacheEntry* GetIconFromMetaMime(const char* fileType,
418 		IconDrawMode mode, icon_size size, LazyBitmapAllocator*,
419 		IconCacheEntry*);
420 	IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache,
421 		AutoLock<SimpleIconCache>* sharedCache,
422 		AutoLock<SimpleIconCache>** resultingLockedCache,
423 		Model*, IconSource&, IconDrawMode mode,
424 		icon_size size, LazyBitmapAllocator*);
425 	IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache,
426 		AutoLock<SimpleIconCache>* sharedCache,
427 		AutoLock<SimpleIconCache>** resultingLockedCache,
428 		Model*, IconSource&, IconDrawMode mode,
429 		icon_size size, LazyBitmapAllocator*);
430 	IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache,
431 		AutoLock<SimpleIconCache>* sharedCache,
432 		AutoLock<SimpleIconCache>** resultingLockedCache,
433 		Model*, IconSource&, IconDrawMode mode,
434 		icon_size size, LazyBitmapAllocator*);
435 	IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *,
436 		AutoLock<SimpleIconCache>* nodeCache,
437 		AutoLock<SimpleIconCache>** resultingLockedCache,
438 		Model*, IconSource&, IconDrawMode mode,
439 		icon_size size, LazyBitmapAllocator*, IconCacheEntry*,
440 		bool permanent);
441 	IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache,
442 		AutoLock<SimpleIconCache>** resultingLockedCache,
443 		Model*, IconSource&, IconDrawMode mode,
444 		icon_size size, LazyBitmapAllocator*, IconCacheEntry*);
445 	IconCacheEntry* GetFallbackIcon(
446 		AutoLock<SimpleIconCache>* sharedCacheLocker,
447 		AutoLock<SimpleIconCache>** resultingOpenCache,
448 		Model* model, IconDrawMode mode, icon_size size,
449 		LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry);
450 
451 	BBitmap* MakeTransformedIcon(const BBitmap*, icon_size,
452 		int32 colorTransformTable [], LazyBitmapAllocator*);
453 
454 	NodeIconCache fNodeCache;
455 	SharedIconCache fSharedCache;
456 
457 	void InitHighlightTable();
458 
459 	int32 fHighlightTable[kColorTransformTableSize];
460 	bool fInitHighlightTable;
461 		// whether or not we need to initialize the highlight table
462 };
463 
464 
465 class LazyBitmapAllocator {
466 	// Utility class used when we aren't sure that we will keep a bitmap,
467 	// need a bitmap or be able to construct it properly
468 public:
469 	LazyBitmapAllocator(icon_size size,
470 		color_space colorSpace = kDefaultIconDepth,
471 		bool preallocate = false);
472 	~LazyBitmapAllocator();
473 
474 	BBitmap* Get();
475 	BBitmap* Adopt();
476 
477 private:
478 	BBitmap* fBitmap;
479 	icon_size fSize;
480 	color_space fColorSpace;
481 };
482 
483 
484 // inlines follow
485 
486 inline const char*
487 SharedCacheEntry::FileType() const
488 {
489 	return fFileType.String();
490 }
491 
492 
493 inline const char*
494 SharedCacheEntry::AppSignature() const
495 {
496 	return fAppSignature.String();
497 }
498 
499 
500 inline bool
501 IconCache::NeedsDeletionNotification(IconSource from)
502 {
503 	return from == kNode;
504 }
505 
506 
507 inline IconCacheEntry*
508 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const
509 {
510 	if (entry->fAliasForIndex < 0)
511 		return entry;
512 
513 	return fHashTable.ElementAt(entry->fAliasForIndex);
514 }
515 
516 
517 inline int32
518 SharedIconCache::EntryIndex(const SharedCacheEntry* entry) const
519 {
520 	return fHashTable.ElementIndex(entry);
521 }
522 
523 } // namespace BPrivate
524 
525 using namespace BPrivate;
526 
527 
528 #endif	// _NU_ICON_CACHE_H
529