1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All 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
63namespace BPrivate {
64
65class Model;
66class ModelNodeLazyOpener;
67class LazyBitmapAllocator;
68class SharedIconCache;
69class SharedCacheEntry;
70
71enum 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
101enum 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
118class 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
126public:
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
162protected:
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
180class SimpleIconCache {
181public:
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
195private:
196	Benaphore fLock;
197};
198
199
200class SharedCacheEntry : public IconCacheEntry {
201public:
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;
221private:
222	BString fFileType;
223	BString fAppSignature;
224
225	friend class SharedIconCache;
226};
227
228
229class SharedCacheEntryArray : public OpenHashElementArray<SharedCacheEntry> {
230	// SharedIconCache stores all it's elements in this array
231public:
232	SharedCacheEntryArray(int32 initialSize);
233	SharedCacheEntry* Add();
234};
235
236
237class SharedIconCache : public SimpleIconCache {
238	// SharedIconCache is used for icons that come from the mime database
239public:
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
264private:
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
274class NodeCacheEntry : public IconCacheEntry {
275public:
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;
294private:
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
303class NodeCacheEntryArray : public OpenHashElementArray<NodeCacheEntry> {
304	// NodeIconCache stores all it's elements in this array
305public:
306	NodeCacheEntryArray(int32 initialSize);
307	NodeCacheEntry* Add();
308};
309
310
311class NodeIconCache : public SimpleIconCache {
312	// NodeIconCache is used for nodes that define their own icons
313public:
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
338private:
339	NodeCacheEntryArray fElementArray;
340	OpenHashTable<NodeCacheEntry, NodeCacheEntryArray> fHashTable;
341};
342
343
344const int32 kColorTransformTableSize = 256;
345
346
347class IconCache {
348public:
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
400private:
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
465class 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
468public:
469	LazyBitmapAllocator(icon_size size,
470		color_space colorSpace = kDefaultIconDepth,
471		bool preallocate = false);
472	~LazyBitmapAllocator();
473
474	BBitmap* Get();
475	BBitmap* Adopt();
476
477private:
478	BBitmap* fBitmap;
479	icon_size fSize;
480	color_space fColorSpace;
481};
482
483
484// inlines follow
485
486inline const char*
487SharedCacheEntry::FileType() const
488{
489	return fFileType.String();
490}
491
492
493inline const char*
494SharedCacheEntry::AppSignature() const
495{
496	return fAppSignature.String();
497}
498
499
500inline bool
501IconCache::NeedsDeletionNotification(IconSource from)
502{
503	return from == kNode;
504}
505
506
507inline IconCacheEntry*
508SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const
509{
510	if (entry->fAliasForIndex < 0)
511		return entry;
512
513	return fHashTable.ElementAt(entry->fAliasForIndex);
514}
515
516
517inline int32
518SharedIconCache::EntryIndex(const SharedCacheEntry* entry) const
519{
520	return fHashTable.ElementIndex(entry);
521}
522
523} // namespace BPrivate
524
525using namespace BPrivate;
526
527
528#endif	// _NU_ICON_CACHE_H
529