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