#include "main.h" #include "navigationIcons.h" #include typedef struct IconCacheRecord { size_t ref; int index; DeviceImage *image; } IconCacheRecord; typedef std::vector IconCache; static IconCache iconCache; static BOOL NavigationIcons_GetSize(unsigned int *width, unsigned int *height) { HWND libraryWindow; MLIMAGELISTIMAGESIZE imageSize; libraryWindow = Plugin_GetLibraryWindow(); imageSize.hmlil = MLNavCtrl_GetImageList(libraryWindow); if (NULL == imageSize.hmlil) return FALSE; if (FALSE == MLImageList_GetImageSize(libraryWindow, &imageSize)) return FALSE; *width = imageSize.cx; *height = imageSize.cy; return TRUE; } static DeviceImage* NavigationIcons_GetDeviceImage(ifc_device *device, unsigned int width, unsigned int height) { wchar_t path[MAX_PATH * 2] = {0}; if (NULL == device) return NULL; if (FAILED(device->GetIcon(path, ARRAYSIZE(path), width, height))) return NULL; return DeviceImageCache_GetImage(Plugin_GetImageCache(), path, width, height, NULL, NULL); } static DeviceImage* NavigationIcons_GetDeviceTypeImage(ifc_device *device, unsigned int width, unsigned int height) { ifc_devicetype *type; DeviceImage *image; wchar_t path[MAX_PATH * 2] = {0}; if (NULL == device || NULL == WASABI_API_DEVICES || S_OK != WASABI_API_DEVICES->TypeFind(device->GetName(), &type)) { return NULL; } if (SUCCEEDED(type->GetIcon(path, ARRAYSIZE(path), width, height))) { image = DeviceImageCache_GetImage(Plugin_GetImageCache(), path, width, height, NULL, NULL); } else image = NULL; type->Release(); return image; } static DeviceImage* NavigationIcons_GetDefaultImage(ifc_device *device, unsigned int width, unsigned int height) { const wchar_t *path; path = Plugin_GetDefaultDeviceImage(width, height); if (NULL == path) return NULL; return DeviceImageCache_GetImage(Plugin_GetImageCache(), path, width, height, NULL, NULL); } static int NavigationIcons_RegisterDeviceIcon(DeviceImage *image, int iconIndex) { MLIMAGESOURCE imageSource; MLIMAGELISTITEM listItem; HWND libraryWindow; HBITMAP bitmap; if (NULL == image) return -1; libraryWindow = Plugin_GetLibraryWindow(); if (NULL == libraryWindow) return -1; bitmap = DeviceImage_GetBitmap(image, DeviceImage_ExactSize | DeviceImage_AlignHCenter | DeviceImage_AlignVCenter); if (NULL == bitmap) return -1; imageSource.cbSize = sizeof(imageSource); imageSource.lpszName = (LPCWSTR)bitmap; imageSource.type = SRC_TYPE_HBITMAP; imageSource.bpp = 32; imageSource.flags = 0; imageSource.hInst = NULL; listItem.cbSize = sizeof(listItem); listItem.hmlil = MLNavCtrl_GetImageList(libraryWindow); listItem.filterUID = MLIF_FILTER3_UID; listItem.pmlImgSource = &imageSource; listItem.mlilIndex = iconIndex; if (NULL == listItem.hmlil) return -1; if (listItem.mlilIndex >= 0) { if (FALSE == MLImageList_Replace(libraryWindow, &listItem)) return -1; return listItem.mlilIndex; } return MLImageList_Add(libraryWindow, &listItem); } static IconCacheRecord * NavigationIcons_FindCacheRecord(DeviceImage *image) { size_t index; IconCacheRecord *record; if (NULL == image) return NULL; index = iconCache.size(); while(index--) { record = &iconCache[index]; if (record->image == image) return record; } return NULL; } static IconCacheRecord * NavigationIcons_FindAvailableCacheRecord() { size_t index; IconCacheRecord *record; index = iconCache.size(); while(index--) { record = &iconCache[index]; if (0 == record->ref) return record; } return NULL; } static IconCacheRecord * NavigationIcons_FindCacheRecordByIndex(int iconIndex) { size_t index; IconCacheRecord *record; if (iconIndex < 0) return NULL; index = iconCache.size(); while(index--) { record = &iconCache[index]; if (record->index == iconIndex) return record; } return NULL; } static IconCacheRecord * NavigationIcons_CreateCacheRecord(DeviceImage *image, int iconIndex) { IconCacheRecord record; if (NULL == image || -1 == iconIndex) return NULL; record.ref = 1; record.index = iconIndex; record.image = image; DeviceImage_AddRef(image); iconCache.push_back(record); return &iconCache.back(); } static HBITMAP NavigationIcons_GetDeviceImageBitmap(DeviceImage *image) { return DeviceImage_GetBitmap(image, DeviceImage_ExactSize | DeviceImage_AlignHCenter | DeviceImage_AlignVCenter); } int NavigationIcons_GetDeviceIconIndex(ifc_device *device) { DeviceImage *image; unsigned int width, height; IconCacheRecord *record; int iconIndex; size_t attempt; if (FALSE == NavigationIcons_GetSize(&width, &height)) return -1; for(attempt = 0; attempt < 3; attempt++) { switch(attempt) { case 0: image = NavigationIcons_GetDeviceImage(device, width, height); break; case 1: image = NavigationIcons_GetDeviceTypeImage(device, width, height); break; case 2: image = NavigationIcons_GetDefaultImage(device, width, height); break; } record = (NULL != image) ? NavigationIcons_FindCacheRecord(image) : NULL; if (NULL == record && NULL == NavigationIcons_GetDeviceImageBitmap(image)) { continue; } break; } if (NULL != record) { record->ref++; iconIndex = record->index; } else { record = NavigationIcons_FindAvailableCacheRecord(); if (NULL != record) { iconIndex = NavigationIcons_RegisterDeviceIcon(image, record->index); if (-1 != iconIndex) { record->ref++; record->image = image; } } else { iconIndex = NavigationIcons_RegisterDeviceIcon(image, -1); if (-1 != iconIndex) { IconCacheRecord newRecord; newRecord.ref = 1; newRecord.image = image; newRecord.index = iconIndex; iconCache.push_back(newRecord); } } } if (-1 == iconIndex) DeviceImage_Release(image); return iconIndex; } BOOL NavigationIcons_ReleaseIconIndex(int iconIndex) { IconCacheRecord *record; record = NavigationIcons_FindCacheRecordByIndex(iconIndex); if (NULL == record) return FALSE; if (0 == record->ref) return FALSE; record->ref--; DeviceImage_Release(record->image); if (0 == record->ref) record->image = NULL; return TRUE; } void NavigationIcons_ClearCache() { size_t index; IconCacheRecord *record; index = iconCache.size(); while(index--) { record = &iconCache[index]; if (NULL != record->image) { while(record->ref--) DeviceImage_Release(record->image); record->image = NULL; } record->ref = 0; } }