PageRenderTime 28ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/core/dylib/src/main/java/ch/cyberduck/core/resources/NSImageIconCache.java

https://gitlab.com/vincent.hsu/cyberduck
Java | 316 lines | 237 code | 22 blank | 57 comment | 53 complexity | 7442555b174ea23d75644419e18ec455 MD5 | raw file
  1. package ch.cyberduck.core.resources;
  2. /*
  3. * Copyright (c) 2002-2013 David Kocher. All rights reserved.
  4. * http://cyberduck.ch/
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * Bug fixes, suggestions and comments should be sent to feedback@cyberduck.ch
  17. */
  18. import ch.cyberduck.binding.application.NSGraphics;
  19. import ch.cyberduck.binding.application.NSImage;
  20. import ch.cyberduck.binding.application.NSWorkspace;
  21. import ch.cyberduck.core.Local;
  22. import ch.cyberduck.core.Path;
  23. import ch.cyberduck.core.Permission;
  24. import ch.cyberduck.core.local.Application;
  25. import ch.cyberduck.core.preferences.PreferencesFactory;
  26. import org.apache.commons.collections4.map.LRUMap;
  27. import org.apache.commons.lang3.StringUtils;
  28. import org.apache.log4j.Logger;
  29. import org.rococoa.cocoa.foundation.NSPoint;
  30. import org.rococoa.cocoa.foundation.NSRect;
  31. import org.rococoa.cocoa.foundation.NSSize;
  32. import java.util.HashMap;
  33. import java.util.Map;
  34. public class NSImageIconCache extends AbstractIconCache<NSImage> {
  35. private static final Logger log = Logger.getLogger(NSImageIconCache.class);
  36. private final static NSRect NSZeroRect = new NSRect(0, 0);
  37. /**
  38. * Cache limited to n entries
  39. */
  40. private final Map<String, NSImage> cache;
  41. public NSImageIconCache() {
  42. if(0 == PreferencesFactory.get().getInteger("icon.cache.size")) {
  43. cache = new HashMap<String, NSImage>() {
  44. @Override
  45. public NSImage put(String key, NSImage value) {
  46. return value;
  47. }
  48. };
  49. }
  50. else {
  51. cache = new LRUMap<String, NSImage>(PreferencesFactory.get().getInteger("icon.cache.size")) {
  52. @Override
  53. protected boolean removeLRU(LinkEntry entry) {
  54. if(log.isDebugEnabled()) {
  55. log.debug("Removing from cache:" + entry);
  56. }
  57. return true;
  58. }
  59. };
  60. }
  61. }
  62. private NSImage put(final String name, final NSImage image, final Integer size) {
  63. cache.put(String.format("%d-%s", size, name), image);
  64. return image;
  65. }
  66. private NSImage load(final String name, final Integer size) {
  67. if(!cache.containsKey(String.format("%d-%s", size, name))) {
  68. if(log.isDebugEnabled()) {
  69. log.debug(String.format("No cached image for %s", name));
  70. }
  71. return null;
  72. }
  73. return cache.get(String.format("%d-%s", size, name));
  74. }
  75. /**
  76. * @param extension File type
  77. * @param size Requested size
  78. * @return Cached icon
  79. */
  80. @Override
  81. public NSImage documentIcon(final String extension, final Integer size) {
  82. NSImage image = this.load(extension, size);
  83. if(null == image) {
  84. image = NSWorkspace.sharedWorkspace().iconForFileType(extension);
  85. image = this.convert(extension, image, size);
  86. this.put(extension, image, size);
  87. }
  88. return image;
  89. }
  90. @Override
  91. public NSImage documentIcon(final String extension, final Integer size, final NSImage badge) {
  92. final String name = extension + badge.name();
  93. NSImage icon = this.iconNamed(name, size);
  94. if(null == icon) {
  95. icon = this.badge(badge, this.documentIcon(extension, size));
  96. this.put(name, icon, size);
  97. }
  98. return icon;
  99. }
  100. @Override
  101. public NSImage folderIcon(final Integer size) {
  102. NSImage folder = this.iconNamed("NSFolder", size);
  103. if(null == folder) {
  104. return this.iconNamed("NSFolder", size);
  105. }
  106. return folder;
  107. }
  108. @Override
  109. public NSImage folderIcon(final Integer size, final NSImage badge) {
  110. final String name = String.format("NSFolder-%s", badge.name());
  111. NSImage folder = this.load(name, size);
  112. if(null == folder) {
  113. folder = this.convert(name, this.iconNamed("NSFolder", size), size);
  114. folder = this.badge(badge, folder);
  115. this.put(name, folder, size);
  116. }
  117. return folder;
  118. }
  119. /**
  120. * Overlay badge image.
  121. *
  122. * @param badge Overlay
  123. * @param icon Icon
  124. * @return Cached icon
  125. */
  126. @Override
  127. protected NSImage badge(final NSImage badge, final NSImage icon) {
  128. NSImage f = NSImage.imageWithSize(icon.size());
  129. f.lockFocus();
  130. icon.drawInRect(new NSRect(new NSPoint(0, 0), icon.size()),
  131. NSZeroRect, NSGraphics.NSCompositeSourceOver, 1.0f);
  132. badge.drawInRect(new NSRect(new NSPoint(0, 0), badge.size()),
  133. NSZeroRect, NSGraphics.NSCompositeSourceOver, 1.0f);
  134. f.unlockFocus();
  135. return f;
  136. }
  137. public NSImage iconNamed(final String image, final Integer size, final NSImage badge) {
  138. final String name = String.format("%s-%s", image, badge.name());
  139. NSImage icon = this.load(name, size);
  140. if(null == icon) {
  141. icon = this.convert(name, this.iconNamed(image, size), size);
  142. icon = this.badge(badge, icon);
  143. this.put(name, icon, size);
  144. }
  145. return icon;
  146. }
  147. /**
  148. * @param name When looking for files in the application bundle, it is better (but not required)
  149. * to include the filename extension in the name parameter
  150. * @param width Requested size
  151. * @param height Requested size
  152. * @return Cached icon
  153. * @see NSImage#imageNamed(String)
  154. * @see #convert(String, ch.cyberduck.binding.application.NSImage, Integer, Integer)
  155. */
  156. @Override
  157. public NSImage iconNamed(final String name, final Integer width, final Integer height) {
  158. NSImage image = this.load(name, width);
  159. if(null == image) {
  160. if(name.startsWith("/")) {
  161. image = NSImage.imageWithContentsOfFile(name);
  162. }
  163. else {
  164. image = NSImage.imageNamed(String.format("%d-%s", width, name));
  165. if(null == image) {
  166. image = NSImage.imageNamed(name);
  167. }
  168. else {
  169. return image;
  170. }
  171. }
  172. if(null == image) {
  173. log.warn(String.format("No icon named %s", name));
  174. this.put(name, null, width);
  175. }
  176. else {
  177. image = this.convert(name, image, width, height);
  178. this.put(name, image, width);
  179. }
  180. }
  181. return image;
  182. }
  183. /**
  184. * @param path File
  185. * @param size Requested size
  186. * @return Cached icon
  187. */
  188. @Override
  189. public NSImage fileIcon(final Local path, final Integer size) {
  190. NSImage icon = null;
  191. if(path.exists()) {
  192. icon = this.load(path.getAbsolute(), size);
  193. if(null == icon) {
  194. icon = NSWorkspace.sharedWorkspace().iconForFile(path.getAbsolute());
  195. icon = this.convert(path.getName(), icon, size);
  196. this.put(path.getAbsolute(), icon, size);
  197. }
  198. }
  199. if(null == icon) {
  200. return this.iconNamed("notfound.tiff", size);
  201. }
  202. return icon;
  203. }
  204. /**
  205. * @param app Application
  206. * @param size Requested size
  207. * @return Cached icon
  208. */
  209. @Override
  210. public NSImage applicationIcon(final Application app, final Integer size) {
  211. NSImage icon = this.load(app.getIdentifier(), size);
  212. if(null == icon) {
  213. final String path = NSWorkspace.sharedWorkspace().absolutePathForAppBundleWithIdentifier(app.getIdentifier());
  214. // Null if the bundle cannot be found
  215. if(StringUtils.isNotBlank(path)) {
  216. icon = NSWorkspace.sharedWorkspace().iconForFile(path);
  217. icon = this.convert(app.getIdentifier(), icon, size);
  218. this.put(app.getIdentifier(), icon, size);
  219. }
  220. }
  221. if(null == icon) {
  222. return this.iconNamed("notfound.tiff", size);
  223. }
  224. return icon;
  225. }
  226. /**
  227. * @param path File
  228. * @param size Requested size
  229. * @return Cached icon
  230. */
  231. @Override
  232. public NSImage fileIcon(final Path path, final Integer size) {
  233. if(path.getType().contains(Path.Type.decrypted)) {
  234. final NSImage badge = this.iconNamed("unlockedbadge.tiff", size);
  235. badge.setName("unlockedbadge");
  236. if(path.isDirectory()) {
  237. return this.folderIcon(size, badge);
  238. }
  239. return this.documentIcon(StringUtils.lowerCase(path.getExtension()), size, badge);
  240. }
  241. if(path.isSymbolicLink()) {
  242. final NSImage badge = this.iconNamed("aliasbadge.tiff", size);
  243. badge.setName("aliasbadge");
  244. if(path.isDirectory()) {
  245. return this.folderIcon(size, badge);
  246. }
  247. return this.documentIcon(StringUtils.lowerCase(path.getExtension()), size, badge);
  248. }
  249. if(path.isFile()) {
  250. if(StringUtils.isEmpty(path.getExtension())) {
  251. if(path.attributes().getPermission().isExecutable()) {
  252. return this.iconNamed("executable.tiff", size);
  253. }
  254. }
  255. return this.documentIcon(StringUtils.lowerCase(path.getExtension()), size);
  256. }
  257. if(path.isDirectory()) {
  258. if(!Permission.EMPTY.equals(path.attributes().getPermission())) {
  259. if(!path.attributes().getPermission().isExecutable()) {
  260. final NSImage badge = this.iconNamed("privatefolderbadge.tiff", size);
  261. badge.setName("privatefolderbadge");
  262. return this.folderIcon(size, badge);
  263. }
  264. if(!path.attributes().getPermission().isReadable()) {
  265. if(path.attributes().getPermission().isWritable()) {
  266. final NSImage badge = this.iconNamed("dropfolderbadge.tiff", size);
  267. badge.setName("dropfolderbadge");
  268. return this.folderIcon(size, badge);
  269. }
  270. }
  271. if(!path.attributes().getPermission().isWritable()) {
  272. final NSImage badge = this.iconNamed("readonlyfolderbadge.tiff", size);
  273. badge.setName("readonlyfolderbadge");
  274. return this.folderIcon(size, badge);
  275. }
  276. }
  277. return this.folderIcon(size);
  278. }
  279. return this.iconNamed("notfound.tiff", size);
  280. }
  281. private NSImage convert(final String name, final NSImage icon, final Integer size) {
  282. return this.convert(name, icon, size, size);
  283. }
  284. private NSImage convert(final String name, final NSImage icon, final Integer width, final Integer height) {
  285. if(null == width || null == height) {
  286. log.debug(String.format("Return default size for %s", icon.name()));
  287. return icon;
  288. }
  289. // Cache sized image
  290. icon.setName(String.format("%d-%s", width, name));
  291. icon.setSize(new NSSize(width, height));
  292. return icon;
  293. }
  294. }