#ifndef _NU_ICON_CACHE_H
#define _NU_ICON_CACHE_H
#include <Bitmap.h>
#include <ObjectList.h>
#include <Mime.h>
#include <String.h>
#include "AutoLock.h"
#include "HashSet.h"
#include "Utilities.h"
namespace BPrivate {
class Model;
class ModelNodeLazyOpener;
class LazyBitmapAllocator;
class SharedIconCache;
class SharedCacheEntry;
class GenerateThumbnailJob;
enum IconDrawMode {
kSelected = 0x01,
kNotFocused = 0x02,
kOpen = 0x04,
kNotEmpty = 0x08,
kDisabled = 0x10,
kActive = 0x20,
kLink = 0x40,
kTrackerSpecialized = 0x80,
kNormalIcon = 0,
kSelectedIcon = kSelected,
kSelectedInBackgroundIcon = kSelected | kNotFocused,
kOpenIcon = kOpen,
kOpenSelectedIcon = kSelected | kOpen,
kOpenSelectedInBackgroundIcon = kSelected | kNotFocused | kOpen,
kFullIcon = kNotEmpty,
kFullSelectedIcon = kNotEmpty | kOpen,
kDimmedIcon
};
#define NORMAL_ICON_ONLY kNormalIcon
enum IconSource {
kUnknownSource,
kUnknownNotFromNode,
kTrackerDefault,
kTrackerSupplied,
kMetaMime,
kPreferredAppForType,
kPreferredAppForNode,
kVolume,
kNode
};
template<typename Class>
struct SelfHashing {
typedef typename Class::HashKeyType KeyType;
typedef Class ValueType;
size_t HashKey(KeyType key) const
{
return Class::Hash(key);
}
size_t Hash(ValueType* value) const
{
return value->Hash();
}
bool Compare(KeyType key, ValueType* value) const
{
return *value == key;
}
ValueType*& GetLink(ValueType* value) const
{
return value->HashNext();
}
};
class IconCacheEntry {
public:
IconCacheEntry();
~IconCacheEntry();
void SetAliasFor(const SharedIconCache* sharedCache,
const SharedCacheEntry* entry);
static IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache,
IconCacheEntry* entry);
IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache);
void SetIcon(BBitmap* bitmap, IconDrawMode mode, BSize size);
bool HaveIconBitmap(IconDrawMode mode, BSize size) const;
bool CanConstructBitmap(IconDrawMode mode, BSize size) const;
static bool AlternateModeForIconConstructing(IconDrawMode requestedMode,
IconDrawMode &alternate, BSize size);
BBitmap* ConstructBitmap(BBitmap* constructFrom,
IconDrawMode requestedMode, IconDrawMode constructFromMode,
BSize size, LazyBitmapAllocator*);
BBitmap* ConstructBitmap(IconDrawMode requestedMode, BSize size,
LazyBitmapAllocator*);
bool IconHitTest(BPoint, IconDrawMode, BSize) const;
void RetireIcons(BObjectList<BBitmap, true>* retiredBitmapList);
protected:
BBitmap* IconForMode(IconDrawMode mode, BSize size) const;
void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, BSize size);
BBitmap* fLargeIcon;
BBitmap* fHighlightedLargeIcon;
BBitmap* fMiniIcon;
BBitmap* fHighlightedMiniIcon;
const IconCacheEntry* fAliasTo;
friend class SharedIconCache;
friend class NodeIconCache;
};
class SimpleIconCache {
public:
SimpleIconCache(const char*);
virtual ~SimpleIconCache() {}
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode,
BSize size, bool async = false) = 0;
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
BSize, void (*)(BView*, BPoint, BBitmap*, void*),
void* = NULL) = 0;
bool Lock();
void Unlock();
bool IsLocked() const;
private:
Benaphore fLock;
};
class SharedCacheEntry : public IconCacheEntry {
public:
SharedCacheEntry();
SharedCacheEntry(const char* fileType, const char* appSignature = 0);
void Draw(BView*, BPoint, IconDrawMode mode, BSize size,
bool async = false);
void Draw(BView*, BPoint, IconDrawMode, BSize,
void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL);
const char* FileType() const;
const char* AppSignature() const;
public:
struct TypeAndSignature {
const char* type, *signature;
TypeAndSignature(const char* t, const char* s)
: type(t), signature(s) {}
};
typedef TypeAndSignature HashKeyType;
static size_t Hash(const TypeAndSignature& typeAndSignature);
size_t Hash() const;
SharedCacheEntry*& HashNext() { return fNext; }
bool operator==(const TypeAndSignature& typeAndSignature) const;
private:
SharedCacheEntry* fNext;
BString fFileType;
BString fAppSignature;
friend class SharedIconCache;
};
class SharedIconCache : public SimpleIconCache {
public:
SharedIconCache();
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode,
BSize size, bool async = false);
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
BSize, void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL);
SharedCacheEntry* FindItem(const char* fileType,
const char* appSignature = 0) const;
SharedCacheEntry* AddItem(const char* fileType,
const char* appSignature = 0);
void IconChanged(SharedCacheEntry*);
void SetAliasFor(IconCacheEntry* entry,
const SharedCacheEntry* original) const;
IconCacheEntry* ResolveIfAlias(IconCacheEntry* entry) const;
void RemoveAliasesTo(SharedCacheEntry* alias);
private:
typedef BOpenHashTable<SelfHashing<SharedCacheEntry> > EntryHashTable;
EntryHashTable fHashTable;
BObjectList<BBitmap, true> fRetiredBitmaps;
};
class NodeCacheEntry : public IconCacheEntry {
public:
NodeCacheEntry(bool permanent = false);
NodeCacheEntry(const node_ref*, bool permanent = false);
void Draw(BView*, BPoint, IconDrawMode mode, BSize size,
bool async = false);
void Draw(BView*, BPoint, IconDrawMode, BSize,
void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL);
const node_ref* Node() const;
bool Permanent() const;
public:
typedef const node_ref* HashKeyType;
static size_t Hash(const node_ref* node);
size_t Hash() const;
NodeCacheEntry*& HashNext() { return fNext; }
bool operator==(const node_ref* ref) const;
private:
NodeCacheEntry* fNext;
node_ref fRef;
bool fPermanent;
friend class NodeIconCache;
};
class NodeIconCache : public SimpleIconCache {
public:
NodeIconCache();
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
BSize, bool async = false);
virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode,
BSize, void (*)(BView*, BPoint, BBitmap*, void*), void* = 0);
NodeCacheEntry* FindItem(const node_ref*) const;
NodeCacheEntry* AddItem(const node_ref*, bool permanent = false);
void Deleting(const node_ref*);
void Removing(const node_ref*);
void Deleting(const BView*);
void IconChanged(const Model*);
void RemoveAliasesTo(SharedCacheEntry* alias);
private:
typedef BOpenHashTable<SelfHashing<NodeCacheEntry> > EntryHashTable;
EntryHashTable fHashTable;
};
const int32 kColorTransformTableSize = 256;
class IconCache {
public:
IconCache();
void Draw(Model*, BView*, BPoint where, IconDrawMode mode,
BSize size, bool async = false);
void SyncDraw(Model*, BView*, BPoint, IconDrawMode,
BSize, void (*)(BView*, BPoint, BBitmap*, void*),
void* passThruState = 0);
void Preload(Model*, IconDrawMode mode, BSize size,
bool permanent = false);
status_t Preload(const char* mimeType, IconDrawMode mode, BSize size);
void Deleting(const Model*);
void Removing(const Model* model);
void Deleting(const BView*);
void IconChanged(Model*);
void IconChanged(const char* mimeType, const char* appSignature);
bool IsIconFrom(const Model*, const char* mimeType,
const char* appSignature) const;
bool IconHitTest(BPoint, const Model*, IconDrawMode, BSize);
BBitmap* MakeSelectedIcon(const BBitmap* normal, BSize,
LazyBitmapAllocator*);
static bool NeedsDeletionNotification(IconSource);
static IconCache* sIconCache;
static BSize sMiniIconSize;
private:
IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache,
AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconDrawMode mode, BSize size, bool permanent);
IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature,
const char* preferredApp, IconDrawMode mode, BSize size,
LazyBitmapAllocator*, IconCacheEntry*);
IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*,
IconSource &source, IconDrawMode mode, BSize size,
LazyBitmapAllocator*, IconCacheEntry*);
IconCacheEntry* GetIconFromMetaMime(const char* fileType,
IconDrawMode mode, BSize size, LazyBitmapAllocator*,
IconCacheEntry*);
IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache,
AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*);
IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache,
AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*);
IconCacheEntry* GetPrinterIcon(AutoLock<SimpleIconCache>* nodeCache,
AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*);
IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache,
AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*);
IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *,
AutoLock<SimpleIconCache>* nodeCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*, IconCacheEntry*,
bool permanent);
IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache,
AutoLock<SimpleIconCache>** resultingLockedCache,
Model*, IconSource&, IconDrawMode mode,
BSize size, LazyBitmapAllocator*, IconCacheEntry*);
IconCacheEntry* GetFallbackIcon(
AutoLock<SimpleIconCache>* sharedCacheLocker,
AutoLock<SimpleIconCache>** resultingOpenCache,
Model* model, IconDrawMode mode, BSize size,
LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry);
BBitmap* MakeTransformedIcon(const BBitmap*, BSize,
int32 colorTransformTable [], LazyBitmapAllocator*);
private:
NodeIconCache fNodeCache;
SharedIconCache fSharedCache;
void InitHighlightTable();
int32 fHighlightTable[kColorTransformTableSize];
bool fInitHighlightTable;
friend class BPrivate::GenerateThumbnailJob;
};
class LazyBitmapAllocator {
public:
LazyBitmapAllocator(BSize size,
color_space colorSpace = kDefaultIconDepth,
bool preallocate = false);
~LazyBitmapAllocator();
BBitmap* Get();
BBitmap* Adopt();
private:
BBitmap* fBitmap;
BSize fSize;
color_space fColorSpace;
};
inline const char*
SharedCacheEntry::FileType() const
{
return fFileType.String();
}
inline const char*
SharedCacheEntry::AppSignature() const
{
return fAppSignature.String();
}
inline bool
IconCache::NeedsDeletionNotification(IconSource from)
{
return from == kNode;
}
inline IconCacheEntry*
SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const
{
if (entry->fAliasTo == NULL)
return entry;
return const_cast<IconCacheEntry*>(entry->fAliasTo);
}
}
using namespace BPrivate;
#endif