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