navigationIcons.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include "main.h"
  2. #include "navigationIcons.h"
  3. #include <vector>
  4. typedef struct IconCacheRecord
  5. {
  6. size_t ref;
  7. int index;
  8. DeviceImage *image;
  9. } IconCacheRecord;
  10. typedef std::vector<IconCacheRecord> IconCache;
  11. static IconCache iconCache;
  12. static BOOL
  13. NavigationIcons_GetSize(unsigned int *width, unsigned int *height)
  14. {
  15. HWND libraryWindow;
  16. MLIMAGELISTIMAGESIZE imageSize;
  17. libraryWindow = Plugin_GetLibraryWindow();
  18. imageSize.hmlil = MLNavCtrl_GetImageList(libraryWindow);
  19. if (NULL == imageSize.hmlil)
  20. return FALSE;
  21. if (FALSE == MLImageList_GetImageSize(libraryWindow, &imageSize))
  22. return FALSE;
  23. *width = imageSize.cx;
  24. *height = imageSize.cy;
  25. return TRUE;
  26. }
  27. static DeviceImage*
  28. NavigationIcons_GetDeviceImage(ifc_device *device, unsigned int width, unsigned int height)
  29. {
  30. wchar_t path[MAX_PATH * 2] = {0};
  31. if (NULL == device)
  32. return NULL;
  33. if (FAILED(device->GetIcon(path, ARRAYSIZE(path), width, height)))
  34. return NULL;
  35. return DeviceImageCache_GetImage(Plugin_GetImageCache(),
  36. path, width, height, NULL, NULL);
  37. }
  38. static DeviceImage*
  39. NavigationIcons_GetDeviceTypeImage(ifc_device *device, unsigned int width, unsigned int height)
  40. {
  41. ifc_devicetype *type;
  42. DeviceImage *image;
  43. wchar_t path[MAX_PATH * 2] = {0};
  44. if (NULL == device ||
  45. NULL == WASABI_API_DEVICES ||
  46. S_OK != WASABI_API_DEVICES->TypeFind(device->GetName(), &type))
  47. {
  48. return NULL;
  49. }
  50. if (SUCCEEDED(type->GetIcon(path, ARRAYSIZE(path), width, height)))
  51. {
  52. image = DeviceImageCache_GetImage(Plugin_GetImageCache(),
  53. path, width, height, NULL, NULL);
  54. }
  55. else
  56. image = NULL;
  57. type->Release();
  58. return image;
  59. }
  60. static DeviceImage*
  61. NavigationIcons_GetDefaultImage(ifc_device *device, unsigned int width, unsigned int height)
  62. {
  63. const wchar_t *path;
  64. path = Plugin_GetDefaultDeviceImage(width, height);
  65. if (NULL == path)
  66. return NULL;
  67. return DeviceImageCache_GetImage(Plugin_GetImageCache(), path, width, height, NULL, NULL);
  68. }
  69. static int
  70. NavigationIcons_RegisterDeviceIcon(DeviceImage *image, int iconIndex)
  71. {
  72. MLIMAGESOURCE imageSource;
  73. MLIMAGELISTITEM listItem;
  74. HWND libraryWindow;
  75. HBITMAP bitmap;
  76. if (NULL == image)
  77. return -1;
  78. libraryWindow = Plugin_GetLibraryWindow();
  79. if (NULL == libraryWindow)
  80. return -1;
  81. bitmap = DeviceImage_GetBitmap(image,
  82. DeviceImage_ExactSize | DeviceImage_AlignHCenter | DeviceImage_AlignVCenter);
  83. if (NULL == bitmap)
  84. return -1;
  85. imageSource.cbSize = sizeof(imageSource);
  86. imageSource.lpszName = (LPCWSTR)bitmap;
  87. imageSource.type = SRC_TYPE_HBITMAP;
  88. imageSource.bpp = 32;
  89. imageSource.flags = 0;
  90. imageSource.hInst = NULL;
  91. listItem.cbSize = sizeof(listItem);
  92. listItem.hmlil = MLNavCtrl_GetImageList(libraryWindow);
  93. listItem.filterUID = MLIF_FILTER3_UID;
  94. listItem.pmlImgSource = &imageSource;
  95. listItem.mlilIndex = iconIndex;
  96. if (NULL == listItem.hmlil)
  97. return -1;
  98. if (listItem.mlilIndex >= 0)
  99. {
  100. if (FALSE == MLImageList_Replace(libraryWindow, &listItem))
  101. return -1;
  102. return listItem.mlilIndex;
  103. }
  104. return MLImageList_Add(libraryWindow, &listItem);
  105. }
  106. static IconCacheRecord *
  107. NavigationIcons_FindCacheRecord(DeviceImage *image)
  108. {
  109. size_t index;
  110. IconCacheRecord *record;
  111. if (NULL == image)
  112. return NULL;
  113. index = iconCache.size();
  114. while(index--)
  115. {
  116. record = &iconCache[index];
  117. if (record->image == image)
  118. return record;
  119. }
  120. return NULL;
  121. }
  122. static IconCacheRecord *
  123. NavigationIcons_FindAvailableCacheRecord()
  124. {
  125. size_t index;
  126. IconCacheRecord *record;
  127. index = iconCache.size();
  128. while(index--)
  129. {
  130. record = &iconCache[index];
  131. if (0 == record->ref)
  132. return record;
  133. }
  134. return NULL;
  135. }
  136. static IconCacheRecord *
  137. NavigationIcons_FindCacheRecordByIndex(int iconIndex)
  138. {
  139. size_t index;
  140. IconCacheRecord *record;
  141. if (iconIndex < 0)
  142. return NULL;
  143. index = iconCache.size();
  144. while(index--)
  145. {
  146. record = &iconCache[index];
  147. if (record->index == iconIndex)
  148. return record;
  149. }
  150. return NULL;
  151. }
  152. static IconCacheRecord *
  153. NavigationIcons_CreateCacheRecord(DeviceImage *image, int iconIndex)
  154. {
  155. IconCacheRecord record;
  156. if (NULL == image || -1 == iconIndex)
  157. return NULL;
  158. record.ref = 1;
  159. record.index = iconIndex;
  160. record.image = image;
  161. DeviceImage_AddRef(image);
  162. iconCache.push_back(record);
  163. return &iconCache.back();
  164. }
  165. static HBITMAP
  166. NavigationIcons_GetDeviceImageBitmap(DeviceImage *image)
  167. {
  168. return DeviceImage_GetBitmap(image,
  169. DeviceImage_ExactSize |
  170. DeviceImage_AlignHCenter |
  171. DeviceImage_AlignVCenter);
  172. }
  173. int
  174. NavigationIcons_GetDeviceIconIndex(ifc_device *device)
  175. {
  176. DeviceImage *image;
  177. unsigned int width, height;
  178. IconCacheRecord *record;
  179. int iconIndex;
  180. size_t attempt;
  181. if (FALSE == NavigationIcons_GetSize(&width, &height))
  182. return -1;
  183. for(attempt = 0; attempt < 3; attempt++)
  184. {
  185. switch(attempt)
  186. {
  187. case 0:
  188. image = NavigationIcons_GetDeviceImage(device, width, height);
  189. break;
  190. case 1:
  191. image = NavigationIcons_GetDeviceTypeImage(device, width, height);
  192. break;
  193. case 2:
  194. image = NavigationIcons_GetDefaultImage(device, width, height);
  195. break;
  196. }
  197. record = (NULL != image) ?
  198. NavigationIcons_FindCacheRecord(image) :
  199. NULL;
  200. if (NULL == record &&
  201. NULL == NavigationIcons_GetDeviceImageBitmap(image))
  202. {
  203. continue;
  204. }
  205. break;
  206. }
  207. if (NULL != record)
  208. {
  209. record->ref++;
  210. iconIndex = record->index;
  211. }
  212. else
  213. {
  214. record = NavigationIcons_FindAvailableCacheRecord();
  215. if (NULL != record)
  216. {
  217. iconIndex = NavigationIcons_RegisterDeviceIcon(image, record->index);
  218. if (-1 != iconIndex)
  219. {
  220. record->ref++;
  221. record->image = image;
  222. }
  223. }
  224. else
  225. {
  226. iconIndex = NavigationIcons_RegisterDeviceIcon(image, -1);
  227. if (-1 != iconIndex)
  228. {
  229. IconCacheRecord newRecord;
  230. newRecord.ref = 1;
  231. newRecord.image = image;
  232. newRecord.index = iconIndex;
  233. iconCache.push_back(newRecord);
  234. }
  235. }
  236. }
  237. if (-1 == iconIndex)
  238. DeviceImage_Release(image);
  239. return iconIndex;
  240. }
  241. BOOL
  242. NavigationIcons_ReleaseIconIndex(int iconIndex)
  243. {
  244. IconCacheRecord *record;
  245. record = NavigationIcons_FindCacheRecordByIndex(iconIndex);
  246. if (NULL == record)
  247. return FALSE;
  248. if (0 == record->ref)
  249. return FALSE;
  250. record->ref--;
  251. DeviceImage_Release(record->image);
  252. if (0 == record->ref)
  253. record->image = NULL;
  254. return TRUE;
  255. }
  256. void
  257. NavigationIcons_ClearCache()
  258. {
  259. size_t index;
  260. IconCacheRecord *record;
  261. index = iconCache.size();
  262. while(index--)
  263. {
  264. record = &iconCache[index];
  265. if (NULL != record->image)
  266. {
  267. while(record->ref--)
  268. DeviceImage_Release(record->image);
  269. record->image = NULL;
  270. }
  271. record->ref = 0;
  272. }
  273. }