@NotNull public static Icon colorize(@NotNull final Icon source, @NotNull Color color, boolean keepGray) { float[] base = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); final BufferedImage image = UIUtil.createImage(source.getIconWidth(), source.getIconHeight(), Transparency.TRANSLUCENT); final Graphics2D g = image.createGraphics(); source.paintIcon(null, g, 0, 0); g.dispose(); final BufferedImage img = UIUtil.createImage(source.getIconWidth(), source.getIconHeight(), Transparency.TRANSLUCENT); int[] rgba = new int[4]; float[] hsb = new float[3]; for (int y = 0; y < image.getRaster().getHeight(); y++) { for (int x = 0; x < image.getRaster().getWidth(); x++) { image.getRaster().getPixel(x, y, rgba); if (rgba[3] != 0) { Color.RGBtoHSB(rgba[0], rgba[1], rgba[2], hsb); int rgb = Color.HSBtoRGB(base[0], base[1] * (keepGray ? hsb[1] : 1f), base[2] * hsb[2]); img.getRaster() .setPixel(x, y, new int[] {rgb >> 16 & 0xff, rgb >> 8 & 0xff, rgb & 0xff, rgba[3]}); } } } return createImageIcon(img); }
private static ImageIcon makeColorIconForColor(final Color color) { final int size = UIUtil.isRetina() ? 8 : 16; final int halfSize = size / 2; final Image img = UIUtil.createImage(size, size, BufferedImage.TYPE_INT_RGB); final Graphics gfx = img.getGraphics(); try { if (color == null) { gfx.setColor(IdeaUtils.isDarkTheme() ? Color.darkGray : Color.white); gfx.fillRect(0, 0, size, size); gfx.setColor(IdeaUtils.isDarkTheme() ? Color.yellow : Color.black); gfx.drawRect(0, 0, size - 1, size - 1); gfx.drawLine(0, 0, size - 1, size - 1); } else if (color == DIFF_COLORS) { gfx.setColor(Color.red); gfx.fillRect(0, 0, halfSize, halfSize); gfx.setColor(Color.green); gfx.fillRect(halfSize, 0, halfSize, halfSize); gfx.setColor(Color.blue); gfx.fillRect(0, halfSize, halfSize, halfSize); gfx.setColor(Color.yellow); gfx.fillRect(halfSize, halfSize, halfSize, halfSize); } else { gfx.setColor(color); gfx.fillRect(0, 0, size, size); gfx.setColor(Color.black); gfx.drawRect(0, 0, size - 1, size - 1); } } finally { gfx.dispose(); } return new ImageIcon(img); }
@NotNull public static Icon cropIcon(@NotNull Icon icon, int maxWidth, int maxHeight) { if (icon.getIconHeight() <= maxHeight && icon.getIconWidth() <= maxWidth) { return icon; } final int w = Math.min(icon.getIconWidth(), maxWidth); final int h = Math.min(icon.getIconHeight(), maxHeight); final BufferedImage image = GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice() .getDefaultConfiguration() .createCompatibleImage( icon.getIconWidth(), icon.getIconHeight(), Transparency.TRANSLUCENT); final Graphics2D g = image.createGraphics(); icon.paintIcon(new JPanel(), g, 0, 0); g.dispose(); final BufferedImage img = UIUtil.createImage(w, h, Transparency.TRANSLUCENT); final int offX = icon.getIconWidth() > maxWidth ? (icon.getIconWidth() - maxWidth) / 2 : 0; final int offY = icon.getIconHeight() > maxHeight ? (icon.getIconHeight() - maxHeight) / 2 : 0; for (int col = 0; col < w; col++) { for (int row = 0; row < h; row++) { img.setRGB(col, row, image.getRGB(col + offX, row + offY)); } } return new ImageIcon(img); }
private BufferedImage getAppImage() { assertIsDispatchThread(); try { if (myAppImage != null) return myAppImage; Object app = getApp(); Image appImage = (Image) getAppMethod("getDockIconImage").invoke(app); if (appImage == null) return null; int width = appImage.getWidth(null); int height = appImage.getHeight(null); BufferedImage img = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = img.createGraphics(); g2d.drawImage(appImage, null, null); myAppImage = img; } catch (NoSuchMethodException e) { return null; } catch (Exception e) { LOG.error(e); } return myAppImage; }
private AppImage createAppImage() { BufferedImage current = UIUtil.createImage( getAppImage().getWidth(), getAppImage().getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g = current.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.drawImage(getAppImage(), null, null); return new AppImage(current, g); }
public static Image createImage(final JTable table, int column) { final int height = Math.max(20, Math.min(100, table.getSelectedRowCount() * table.getRowHeight())); final int width = table.getColumnModel().getColumn(column).getWidth(); final BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); drawSelection(table, column, g2, width); return image; }
public static Image createImage(final JTree tree) { final TreeSelectionModel model = tree.getSelectionModel(); final TreePath[] paths = model.getSelectionPaths(); int count = 0; final List<ChangesBrowserNode> nodes = new ArrayList<ChangesBrowserNode>(); for (final TreePath path : paths) { final ChangesBrowserNode node = (ChangesBrowserNode) path.getLastPathComponent(); if (!node.isLeaf()) { nodes.add(node); count += node.getCount(); } } for (TreePath path : paths) { final ChangesBrowserNode element = (ChangesBrowserNode) path.getLastPathComponent(); boolean child = false; for (final ChangesBrowserNode node : nodes) { if (node.isNodeChild(element)) { child = true; break; } } if (!child) { if (element.isLeaf()) count++; } else if (!element.isLeaf()) { count -= element.getCount(); } } final JLabel label = new JLabel(VcsBundle.message("changes.view.dnd.label", count)); label.setOpaque(true); label.setForeground(tree.getForeground()); label.setBackground(tree.getBackground()); label.setFont(tree.getFont()); label.setSize(label.getPreferredSize()); final BufferedImage image = UIUtil.createImage(label.getWidth(), label.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); label.paint(g2); g2.dispose(); return image; }
@Override public void _setTextBadge(IdeFrame frame, String text) { if (!isValid(frame)) { return; } Object icon = null; if (text != null) { try { int size = 55; BufferedImage image = UIUtil.createImage(size, size, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); int roundSize = 40; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setPaint(ERROR_COLOR); g.fillRoundRect( size / 2 - roundSize / 2, size / 2 - roundSize / 2, roundSize, roundSize, size, size); g.setColor(Color.white); Font font = g.getFont(); g.setFont(new Font(font.getName(), font.getStyle(), 22)); FontMetrics fontMetrics = g.getFontMetrics(); int width = fontMetrics.stringWidth(text); g.drawString( text, size / 2 - width / 2, size / 2 - fontMetrics.getHeight() / 2 + fontMetrics.getAscent()); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); Sanselan.writeImage(image, bytes, ImageFormat.IMAGE_FORMAT_ICO, new HashMap()); icon = Win7TaskBar.createIcon(bytes.toByteArray()); } catch (Throwable e) { LOG.error(e); } } try { Win7TaskBar.setOverlayIcon(frame, icon, icon != null); } catch (Throwable e) { LOG.error(e); } }
private void parseProblemGlyphs() { myCheckedForProblemGlyphs = true; BufferedImage buffer = UIUtil.createImage(20, 20, BufferedImage.TYPE_INT_RGB); final Graphics graphics = buffer.getGraphics(); if (!(graphics instanceof Graphics2D)) { return; } final FontRenderContext context = ((Graphics2D) graphics).getFontRenderContext(); char[] charBuffer = new char[1]; for (char c = 0; c < 128; c++) { if (!myFont.canDisplay(c)) { continue; } charBuffer[0] = c; final GlyphVector vector = myFont.createGlyphVector(context, charBuffer); final float y = vector.getGlyphMetrics(0).getAdvanceY(); if (Math.round(y) != 0) { mySymbolsToBreakDrawingIteration.add(c); } } myHasGlyphsToBreakDrawingIteration = !mySymbolsToBreakDrawingIteration.isEmpty(); }
@Override public Pair<Image, Point> createDraggedImage(DnDAction action, Point dragOrigin) { final TreePath[] paths = getSelectionPaths(); if (paths == null) return null; final int count = paths.length; final JLabel label = new JLabel(String.format("%s item%s", count, count == 1 ? "" : "s")); label.setOpaque(true); label.setForeground(myTree.getForeground()); label.setBackground(myTree.getBackground()); label.setFont(myTree.getFont()); label.setSize(label.getPreferredSize()); final BufferedImage image = UIUtil.createImage(label.getWidth(), label.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); label.paint(g2); g2.dispose(); return new Pair<Image, Point>( image, new Point(-image.getWidth(null), -image.getHeight(null))); }
public static Graphics2D createReferenceGraphics() { Graphics2D graphics = (Graphics2D) UIUtil.createImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics(); EditorUIUtil.setupAntialiasing(graphics); return graphics; }
@Nullable private Point createToolTipImage(@NotNull KeyType key) { UIUtil.putClientProperty(myComponent, EXPANDED_RENDERER, true); Pair<Component, Rectangle> rendererAndBounds = getCellRendererAndBounds(key); UIUtil.putClientProperty(myComponent, EXPANDED_RENDERER, null); if (rendererAndBounds == null) return null; JComponent renderer = ObjectUtils.tryCast(rendererAndBounds.first, JComponent.class); if (renderer == null) return null; if (renderer.getClientProperty(DISABLE_EXPANDABLE_HANDLER) != null) return null; if (UIUtil.getClientProperty((JComponent) rendererAndBounds.getFirst(), USE_RENDERER_BOUNDS) == Boolean.TRUE) { rendererAndBounds.getSecond().translate(renderer.getX(), renderer.getY()); rendererAndBounds.getSecond().setSize(renderer.getSize()); } myKeyItemBounds = rendererAndBounds.second; Rectangle cellBounds = myKeyItemBounds; Rectangle visibleRect = getVisibleRect(key); if (cellBounds.y < visibleRect.y) return null; int cellMaxY = cellBounds.y + cellBounds.height; int visMaxY = visibleRect.y + visibleRect.height; if (cellMaxY > visMaxY) return null; int cellMaxX = cellBounds.x + cellBounds.width; int visMaxX = visibleRect.x + visibleRect.width; Point location = new Point(visMaxX, cellBounds.y); SwingUtilities.convertPointToScreen(location, myComponent); Rectangle screen = !Registry.is("ide.expansion.hints.on.all.screens") ? ScreenUtil.getScreenRectangle(location) : ScreenUtil.getAllScreensRectangle(); int borderWidth = isPaintBorder() ? 1 : 0; int width = Math.min(screen.width + screen.x - location.x - borderWidth, cellMaxX - visMaxX); int height = cellBounds.height; if (width <= 0 || height <= 0) return null; Dimension size = getImageSize(width, height); myImage = UIUtil.createImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); Graphics2D g = myImage.createGraphics(); g.setClip(null); doFillBackground(height, width, g); g.translate(cellBounds.x - visMaxX, 0); doPaintTooltipImage(renderer, cellBounds, g, key); CustomLineBorder border = null; if (borderWidth > 0) { border = new CustomLineBorder(getBorderColor(), borderWidth, 0, borderWidth, borderWidth); location.y -= borderWidth; size.width += borderWidth; size.height += borderWidth + borderWidth; } g.dispose(); myRendererPane.remove(renderer); myTipComponent.setBorder(border); myTipComponent.setPreferredSize(size); return location; }
@NotNull @SuppressWarnings("UseJBColor") protected Dialog getOrCreatePickerDialog() { Dialog pickerDialog = getPickerDialog(); if (pickerDialog == null) { pickerDialog = super.getOrCreatePickerDialog(); pickerDialog.addMouseListener( new MouseAdapter() { @Override public void mouseExited(MouseEvent event) { updatePipette(); } }); pickerDialog.addMouseMotionListener( new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { updatePipette(); } }); pickerDialog.addFocusListener( new FocusAdapter() { @Override public void focusLost(FocusEvent e) { if (e.isTemporary()) { pickAndClose(); } else { cancelPipette(); } } }); pickerDialog.setSize(DIALOG_SIZE, DIALOG_SIZE); myMaskImage = UIUtil.createImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB); Graphics2D maskG = myMaskImage.createGraphics(); maskG.setColor(Color.BLUE); maskG.fillRect(0, 0, SIZE, SIZE); maskG.setColor(Color.RED); maskG.setComposite(AlphaComposite.SrcOut); maskG.fillRect(0, 0, SIZE, SIZE); maskG.dispose(); myPipetteImage = UIUtil.createImage( AllIcons.Ide.Pipette.getIconWidth(), AllIcons.Ide.Pipette.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D graphics = myPipetteImage.createGraphics(); //noinspection ConstantConditions AllIcons.Ide.Pipette.paintIcon(null, graphics, 0, 0); graphics.dispose(); myImage = myParent .getGraphicsConfiguration() .createCompatibleImage(SIZE, SIZE, Transparency.TRANSLUCENT); myGraphics = (Graphics2D) myImage.getGraphics(); myGraphics.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); } return pickerDialog; }
public final class IconLoader { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.IconLoader"); public static boolean STRICT = false; private static boolean USE_DARK_ICONS = UIUtil.isUnderDarcula(); private static float SCALE = JBUI.scale(1f); private static ImageFilter IMAGE_FILTER; @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private static final ConcurrentMap<URL, CachedImageIcon> ourIconsCache = ContainerUtil.newConcurrentMap(100, 0.9f, 2); /** This cache contains mapping between icons and disabled icons. */ private static final Map<Icon, Icon> ourIcon2DisabledIcon = new WeakHashMap<Icon, Icon>(200); @NonNls private static final Map<String, String> ourDeprecatedIconsReplacements = new HashMap<String, String>(); static { ourDeprecatedIconsReplacements.put( "/general/toolWindowDebugger.png", "AllIcons.Toolwindows.ToolWindowDebugger"); ourDeprecatedIconsReplacements.put( "/general/toolWindowChanges.png", "AllIcons.Toolwindows.ToolWindowChanges"); ourDeprecatedIconsReplacements.put( "/actions/showSettings.png", "AllIcons.General.ProjectSettings"); ourDeprecatedIconsReplacements.put("/general/ideOptions.png", "AllIcons.General.Settings"); ourDeprecatedIconsReplacements.put( "/general/applicationSettings.png", "AllIcons.General.Settings"); ourDeprecatedIconsReplacements.put("/toolbarDecorator/add.png", "AllIcons.General.Add"); ourDeprecatedIconsReplacements.put("/vcs/customizeView.png", "AllIcons.General.Settings"); ourDeprecatedIconsReplacements.put("/vcs/refresh.png", "AllIcons.Actions.Refresh"); ourDeprecatedIconsReplacements.put("/actions/sync.png", "AllIcons.Actions.Refresh"); ourDeprecatedIconsReplacements.put("/actions/refreshUsages.png", "AllIcons.Actions.Rerun"); ourDeprecatedIconsReplacements.put("/compiler/error.png", "AllIcons.General.Error"); ourDeprecatedIconsReplacements.put( "/compiler/hideWarnings.png", "AllIcons.General.HideWarnings"); ourDeprecatedIconsReplacements.put("/compiler/information.png", "AllIcons.General.Information"); ourDeprecatedIconsReplacements.put("/compiler/warning.png", "AllIcons.General.Warning"); ourDeprecatedIconsReplacements.put("/ide/errorSign.png", "AllIcons.General.Error"); ourDeprecatedIconsReplacements.put("/ant/filter.png", "AllIcons.General.Filter"); ourDeprecatedIconsReplacements.put("/inspector/useFilter.png", "AllIcons.General.Filter"); ourDeprecatedIconsReplacements.put("/actions/showSource.png", "AllIcons.Actions.Preview"); ourDeprecatedIconsReplacements.put( "/actions/consoleHistory.png", "AllIcons.General.MessageHistory"); ourDeprecatedIconsReplacements.put( "/vcs/messageHistory.png", "AllIcons.General.MessageHistory"); } private static final ImageIcon EMPTY_ICON = new ImageIcon(UIUtil.createImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)) { @NonNls public String toString() { return "Empty icon " + super.toString(); } }; private static boolean ourIsActivated = false; private IconLoader() {} @Deprecated public static Icon getIcon(@NotNull final Image image) { return new JBImageIcon(image); } public static void setUseDarkIcons(boolean useDarkIcons) { USE_DARK_ICONS = useDarkIcons; clearCache(); } public static void setScale(float scale) { if (scale != SCALE) { SCALE = scale; clearCache(); } } public static void setFilter(ImageFilter filter) { if (!Registry.is("color.blindness.icon.filter")) { filter = null; } if (IMAGE_FILTER != filter) { IMAGE_FILTER = filter; clearCache(); } } private static void clearCache() { ourIconsCache.clear(); ourIcon2DisabledIcon.clear(); } // TODO[kb] support iconsets // public static Icon getIcon(@NotNull final String path, @NotNull final String darkVariantPath) { // return new InvariantIcon(getIcon(path), getIcon(darkVariantPath)); // } @NotNull public static Icon getIcon(@NonNls @NotNull final String path) { Class callerClass = ReflectionUtil.getGrandCallerClass(); assert callerClass != null : path; return getIcon(path, callerClass); } @Nullable private static Icon getReflectiveIcon(@NotNull String path, ClassLoader classLoader) { try { @NonNls String pckg = path.startsWith("AllIcons.") ? "com.intellij.icons." : "icons."; Class cur = Class.forName( pckg + path.substring(0, path.lastIndexOf('.')).replace('.', '$'), true, classLoader); Field field = cur.getField(path.substring(path.lastIndexOf('.') + 1)); return (Icon) field.get(null); } catch (Exception e) { return null; } } @Nullable /** * Might return null if icon was not found. Use only if you expected null return value, otherwise * see {@link IconLoader#getIcon(java.lang.String)} */ public static Icon findIcon(@NonNls @NotNull String path) { Class callerClass = ReflectionUtil.getGrandCallerClass(); if (callerClass == null) return null; return findIcon(path, callerClass); } @NotNull public static Icon getIcon(@NotNull String path, @NotNull final Class aClass) { final Icon icon = findIcon(path, aClass); if (icon == null) { LOG.error("Icon cannot be found in '" + path + "', aClass='" + aClass + "'"); } return icon; } public static void activate() { ourIsActivated = true; } private static boolean isLoaderDisabled() { return !ourIsActivated; } /** * Might return null if icon was not found. Use only if you expected null return value, otherwise * see {@link IconLoader#getIcon(java.lang.String, java.lang.Class)} */ @Nullable public static Icon findIcon(@NotNull final String path, @NotNull final Class aClass) { return findIcon(path, aClass, false); } @Nullable public static Icon findIcon( @NotNull String path, @NotNull final Class aClass, boolean computeNow) { path = undeprecate(path); if (isReflectivePath(path)) return getReflectiveIcon(path, aClass.getClassLoader()); URL myURL = aClass.getResource(path); if (myURL == null) { if (STRICT) throw new RuntimeException("Can't find icon in '" + path + "' near " + aClass); return null; } return findIcon(myURL); } @NotNull private static String undeprecate(@NotNull String path) { String replacement = ourDeprecatedIconsReplacements.get(path); return replacement == null ? path : replacement; } private static boolean isReflectivePath(@NotNull String path) { List<String> paths = StringUtil.split(path, "."); return paths.size() > 1 && paths.get(0).endsWith("Icons"); } @Nullable public static Icon findIcon(URL url) { return findIcon(url, true); } @Nullable public static Icon findIcon(URL url, boolean useCache) { if (url == null) { return null; } CachedImageIcon icon = ourIconsCache.get(url); if (icon == null) { icon = new CachedImageIcon(url); if (useCache) { icon = ConcurrencyUtil.cacheOrGet(ourIconsCache, url, icon); } } return icon; } @Nullable public static Icon findIcon(@NotNull String path, @NotNull ClassLoader classLoader) { path = undeprecate(path); if (isReflectivePath(path)) return getReflectiveIcon(path, classLoader); if (!StringUtil.startsWithChar(path, '/')) return null; final URL url = classLoader.getResource(path.substring(1)); return findIcon(url); } @Nullable private static Icon checkIcon(final Image image, @NotNull URL url) { if (image == null || image.getHeight(LabelHolder.ourFakeComponent) < 1) { // image wasn't loaded or broken return null; } final Icon icon = getIcon(image); if (icon != null && !isGoodSize(icon)) { LOG.error("Invalid icon: " + url); // # 22481 return EMPTY_ICON; } return icon; } public static boolean isGoodSize(@NotNull final Icon icon) { return icon.getIconWidth() > 0 && icon.getIconHeight() > 0; } /** * Gets (creates if necessary) disabled icon based on the passed one. * * @return <code>ImageIcon</code> constructed from disabled image of passed icon. */ @Nullable public static Icon getDisabledIcon(Icon icon) { if (icon instanceof LazyIcon) icon = ((LazyIcon) icon).getOrComputeIcon(); if (icon == null) return null; Icon disabledIcon = ourIcon2DisabledIcon.get(icon); if (disabledIcon == null) { if (!isGoodSize(icon)) { LOG.error(icon); // # 22481 return EMPTY_ICON; } final int scale = UIUtil.isRetina() ? 2 : 1; @SuppressWarnings("UndesirableClassUsage") BufferedImage image = new BufferedImage( scale * icon.getIconWidth(), scale * icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D graphics = image.createGraphics(); graphics.setColor(UIUtil.TRANSPARENT_COLOR); graphics.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight()); graphics.scale(scale, scale); icon.paintIcon(LabelHolder.ourFakeComponent, graphics, 0, 0); graphics.dispose(); Image img = ImageUtil.filter(image, UIUtil.getGrayFilter()); if (UIUtil.isRetina()) img = RetinaImage.createFrom(img, 2, ImageLoader.ourComponent); disabledIcon = new JBImageIcon(img); ourIcon2DisabledIcon.put(icon, disabledIcon); } return disabledIcon; } public static Icon getTransparentIcon(@NotNull final Icon icon) { return getTransparentIcon(icon, 0.5f); } public static Icon getTransparentIcon(@NotNull final Icon icon, final float alpha) { return new Icon() { @Override public int getIconHeight() { return icon.getIconHeight(); } @Override public int getIconWidth() { return icon.getIconWidth(); } @Override public void paintIcon(final Component c, final Graphics g, final int x, final int y) { final Graphics2D g2 = (Graphics2D) g; final Composite saveComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); icon.paintIcon(c, g2, x, y); g2.setComposite(saveComposite); } }; } private static final class CachedImageIcon implements ScalableIcon { private Object myRealIcon; @NotNull private final URL myUrl; private boolean dark; private float scale; private ImageFilter filter; private HashMap<Float, Icon> scaledIcons; public CachedImageIcon(@NotNull URL url) { myUrl = url; dark = USE_DARK_ICONS; scale = SCALE; filter = IMAGE_FILTER; } @NotNull private synchronized Icon getRealIcon() { if (isLoaderDisabled() && (myRealIcon == null || dark != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER)) return EMPTY_ICON; if (dark != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER) { myRealIcon = null; dark = USE_DARK_ICONS; scale = SCALE; filter = IMAGE_FILTER; } Object realIcon = myRealIcon; if (realIcon instanceof Icon) return (Icon) realIcon; Icon icon; if (realIcon instanceof Reference) { icon = ((Reference<Icon>) realIcon).get(); if (icon != null) return icon; } Image image = ImageLoader.loadFromUrl(myUrl, true, filter); icon = checkIcon(image, myUrl); if (icon != null) { if (icon.getIconWidth() < 50 && icon.getIconHeight() < 50) { realIcon = icon; } else { realIcon = new SoftReference<Icon>(icon); } myRealIcon = realIcon; } return icon == null ? EMPTY_ICON : icon; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { getRealIcon().paintIcon(c, g, x, y); } @Override public int getIconWidth() { return getRealIcon().getIconWidth(); } @Override public int getIconHeight() { return getRealIcon().getIconHeight(); } @Override public String toString() { return myUrl.toString(); } @Override public Icon scale(float scaleFactor) { if (scaleFactor == 1f) { return this; } if (scaledIcons == null) { scaledIcons = new HashMap<Float, Icon>(1); } Icon result = scaledIcons.get(scaleFactor); if (result != null) { return result; } final Image image = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), scaleFactor >= 1.5f, filter); if (image != null) { int width = (int) (getIconWidth() * scaleFactor); int height = (int) (getIconHeight() * scaleFactor); final BufferedImage resizedImage = Scalr.resize( ImageUtil.toBufferedImage(image), Scalr.Method.ULTRA_QUALITY, width, height); result = getIcon(resizedImage); scaledIcons.put(scaleFactor, result); return result; } return this; } } public abstract static class LazyIcon implements Icon { private boolean myWasComputed; private Icon myIcon; private boolean isDarkVariant = USE_DARK_ICONS; private float scale = SCALE; private ImageFilter filter = IMAGE_FILTER; @Override public void paintIcon(Component c, Graphics g, int x, int y) { final Icon icon = getOrComputeIcon(); if (icon != null) { icon.paintIcon(c, g, x, y); } } @Override public int getIconWidth() { final Icon icon = getOrComputeIcon(); return icon != null ? icon.getIconWidth() : 0; } @Override public int getIconHeight() { final Icon icon = getOrComputeIcon(); return icon != null ? icon.getIconHeight() : 0; } protected final synchronized Icon getOrComputeIcon() { if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER) { isDarkVariant = USE_DARK_ICONS; scale = SCALE; filter = IMAGE_FILTER; myWasComputed = true; myIcon = compute(); } return myIcon; } public final void load() { getIconWidth(); } protected abstract Icon compute(); } private static class LabelHolder { /** * To get disabled icon with paint it into the image. Some icons require not null component to * paint. */ private static final JComponent ourFakeComponent = new JLabel(); } }