8081411: Add an API for painting an icon with a SynthContext
Reviewed-by: serb, azvegint
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java Wed Nov 18 19:13:42 2015 +0400
@@ -24,6 +24,7 @@
*/
package com.sun.java.swing.plaf.gtk;
+import javax.swing.plaf.synth.SynthIcon;
import java.util.*;
import javax.swing.plaf.synth.*;
import java.awt.*;
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java Wed Nov 18 19:13:42 2015 +0400
@@ -36,7 +36,7 @@
import sun.awt.AppContext;
import sun.awt.UNIXToolkit;
import sun.swing.SwingUtilities2;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
import com.sun.java.swing.plaf.gtk.GTKEngine.WidgetType;
import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java Wed Nov 18 19:13:42 2015 +0400
@@ -25,7 +25,7 @@
package javax.swing.plaf.nimbus;
import javax.swing.Painter;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.*;
@@ -37,7 +37,7 @@
* An icon that delegates to a painter.
* @author rbair
*/
-class NimbusIcon extends SynthIcon {
+class NimbusIcon implements SynthIcon {
private int width;
private int height;
private String prefix;
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Wed Nov 18 19:13:42 2015 +0400
@@ -50,7 +50,7 @@
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import sun.swing.ImageIconUIResource;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
import sun.swing.plaf.GTKKeybindings;
import sun.swing.plaf.WindowsKeybindings;
import sun.security.action.GetPropertyAction;
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java Wed Nov 18 19:13:42 2015 +0400
@@ -31,7 +31,6 @@
import javax.swing.*;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.*;
-import sun.swing.plaf.synth.*;
/**
* Wrapper for primitive graphics calls.
@@ -287,8 +286,8 @@
return new Dimension(dx, dy);
}
else if ((text == null) || ((icon != null) && (font == null))) {
- return new Dimension(SynthIcon.getIconWidth(icon, ss) + dx,
- SynthIcon.getIconHeight(icon, ss) + dy);
+ return new Dimension(getIconWidth(icon, ss) + dx,
+ getIconHeight(icon, ss) + dy);
}
else {
FontMetrics fm = c.getFontMetrics(font);
@@ -404,7 +403,7 @@
paintIconR.x += textOffset;
}
paintIconR.y += textOffset;
- SynthIcon.paintIcon(icon, ss, g, paintIconR.x, paintIconR.y,
+ paintIcon(icon, ss, g, paintIconR.x, paintIconR.y,
paintIconR.width, paintIconR.height);
g.setColor(color);
}
@@ -423,6 +422,62 @@
}
}
+ /**
+ * Returns the icon's width.
+ * The {@code getIconWidth(context)} method is called for {@code SynthIcon}.
+ *
+ * @param icon the icon
+ * @param context {@code SynthContext} requesting the icon, may be null.
+ * @return an int specifying the width of the icon.
+ */
+ public static int getIconWidth(Icon icon, SynthContext context) {
+ if (icon == null) {
+ return 0;
+ }
+ if (icon instanceof SynthIcon) {
+ return ((SynthIcon) icon).getIconWidth(context);
+ }
+ return icon.getIconWidth();
+ }
+
+ /**
+ * Returns the icon's height.
+ * The {@code getIconHeight(context)} method is called for {@code SynthIcon}.
+ *
+ * @param icon the icon
+ * @param context {@code SynthContext} requesting the icon, may be null.
+ * @return an int specifying the height of the icon.
+ */
+ public static int getIconHeight(Icon icon, SynthContext context) {
+ if (icon == null) {
+ return 0;
+ }
+ if (icon instanceof SynthIcon) {
+ return ((SynthIcon) icon).getIconHeight(context);
+ }
+ return icon.getIconHeight();
+ }
+
+ /**
+ * Paints the icon. The {@code paintIcon(context, g, x, y, width, height)}
+ * method is called for {@code SynthIcon}.
+ *
+ * @param icon the icon
+ * @param context identifies hosting region, may be null.
+ * @param g the graphics context
+ * @param x the x location to paint to
+ * @param y the y location to paint to
+ * @param width the width of the region to paint to, may be 0
+ * @param height the height of the region to paint to, may be 0
+ */
+ public static void paintIcon(Icon icon, SynthContext context, Graphics g,
+ int x, int y, int width, int height) {
+ if (icon instanceof SynthIcon) {
+ ((SynthIcon) icon).paintIcon(context, g, x, y, width, height);
+ } else if (icon != null) {
+ icon.paintIcon(context.getComponent(), g, x, y);
+ }
+ }
/**
* A quick note about how preferred sizes are calculated... Generally
@@ -561,7 +616,7 @@
if (icon != null) {
Rectangle iconRect = lr.getIconRect();
- SynthIcon.paintIcon(icon, lh.getContext(), g, iconRect.x,
+ paintIcon(icon, lh.getContext(), g, iconRect.x,
iconRect.y, iconRect.width, iconRect.height);
}
}
@@ -571,7 +626,7 @@
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getCheckIcon() != null) {
Rectangle checkRect = lr.getCheckRect();
- SynthIcon.paintIcon(lh.getCheckIcon(), lh.getContext(), g,
+ paintIcon(lh.getCheckIcon(), lh.getContext(), g,
checkRect.x, checkRect.y, checkRect.width, checkRect.height);
}
}
@@ -610,7 +665,7 @@
MenuItemLayoutHelper.LayoutResult lr) {
if (lh.getArrowIcon() != null) {
Rectangle arrowRect = lr.getArrowRect();
- SynthIcon.paintIcon(lh.getArrowIcon(), lh.getContext(), g,
+ paintIcon(lh.getArrowIcon(), lh.getContext(), g,
arrowRect.x, arrowRect.y, arrowRect.width, arrowRect.height);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthIcon.java Wed Nov 18 19:13:42 2015 +0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.swing.plaf.synth;
+
+import java.awt.*;
+import javax.swing.*;
+
+/**
+ * An icon that is passed a {@code SynthContext}. Subclasses need only implement
+ * the variants that take a {@code SynthContext}, but must be prepared for the
+ * {@code SynthContext} to be null.
+ *
+ * @author Scott Violet
+ */
+public interface SynthIcon extends Icon {
+
+ /**
+ * Paints the icon at the specified location for the given synth context.
+ *
+ * @param context identifies hosting region, may be null.
+ * @param g the graphics context
+ * @param x the x location to paint to
+ * @param y the y location to paint to
+ * @param width the width of the region to paint to, may be 0
+ * @param height the height of the region to paint to, may be 0
+ */
+ void paintIcon(SynthContext context, Graphics g, int x, int y,
+ int width, int height);
+
+ /**
+ * Returns the icon's width for the given synth context.
+ *
+ * @param context {@code SynthContext} requesting the Icon, may be null.
+ * @return an int specifying the width of the icon.
+ */
+ int getIconWidth(SynthContext context);
+
+ /**
+ * Returns the icon's height for the given synth context.
+ *
+ * @param context {@code SynthContext} requesting the Icon, may be null.
+ * @return an int specifying the height of the icon.
+ */
+ int getIconHeight(SynthContext context);
+
+ @Override
+ default void paintIcon(Component c, Graphics g, int x, int y) {
+ paintIcon(null, g, x, y, getIconWidth(), getIconHeight());
+ }
+
+ @Override
+ default int getIconWidth() {
+ return getIconWidth(null);
+ }
+
+ @Override
+ default int getIconHeight() {
+ return getIconHeight(null);
+ }
+}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java Wed Nov 18 19:13:42 2015 +0400
@@ -53,6 +53,10 @@
* an example of providing your own <code>SynthStyleFactory</code> to
* <code>setStyleFactory</code>.
* <p>
+ * {@link SynthIcon} interface provides
+ * {@code paintIcon(synthContext, graphics, x, y, width, height)} method that
+ * allows to draw the icon with the given {@code SynthContext}.
+ * <p>
* <strong>Warning:</strong>
* This class implements {@link Serializable} as a side effect of it
* extending {@link BasicLookAndFeel}. It is not intended to be serialized.
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java Wed Nov 18 19:13:42 2015 +0400
@@ -27,7 +27,6 @@
import sun.swing.StringUIClientPropertyKey;
import sun.swing.MenuItemLayoutHelper;
-import sun.swing.plaf.synth.SynthIcon;
import javax.swing.*;
import javax.swing.text.View;
@@ -130,8 +129,8 @@
protected void calcWidthsAndHeights() {
// iconRect
if (getIcon() != null) {
- getIconSize().setWidth(SynthIcon.getIconWidth(getIcon(), context));
- getIconSize().setHeight(SynthIcon.getIconHeight(getIcon(), context));
+ getIconSize().setWidth(SynthGraphicsUtils.getIconWidth(getIcon(), context));
+ getIconSize().setHeight(SynthGraphicsUtils.getIconHeight(getIcon(), context));
}
// accRect
@@ -165,16 +164,16 @@
// checkIcon
if (getCheckIcon() != null) {
getCheckSize().setWidth(
- SynthIcon.getIconWidth(getCheckIcon(), context));
+ SynthGraphicsUtils.getIconWidth(getCheckIcon(), context));
getCheckSize().setHeight(
- SynthIcon.getIconHeight(getCheckIcon(), context));
+ SynthGraphicsUtils.getIconHeight(getCheckIcon(), context));
}
// arrowRect
if (getArrowIcon() != null) {
getArrowSize().setWidth(
- SynthIcon.getIconWidth(getArrowIcon(), context));
+ SynthGraphicsUtils.getIconWidth(getArrowIcon(), context));
getArrowSize().setHeight(
- SynthIcon.getIconHeight(getArrowIcon(), context));
+ SynthGraphicsUtils.getIconHeight(getArrowIcon(), context));
}
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java Wed Nov 18 19:13:42 2015 +0400
@@ -41,7 +41,6 @@
import javax.swing.JToolBar;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicToolBarUI;
-import sun.swing.plaf.synth.SynthIcon;
/**
* Provides the Synth L&F UI delegate for
@@ -281,10 +280,10 @@
if (handleIcon != null && toolBar.isFloatable()) {
int startX = toolBar.getComponentOrientation().isLeftToRight() ?
0 : toolBar.getWidth() -
- SynthIcon.getIconWidth(handleIcon, context);
- SynthIcon.paintIcon(handleIcon, context, g, startX, 0,
- SynthIcon.getIconWidth(handleIcon, context),
- SynthIcon.getIconHeight(handleIcon, context));
+ SynthGraphicsUtils.getIconWidth(handleIcon, context);
+ SynthGraphicsUtils.paintIcon(handleIcon, context, g, startX, 0,
+ SynthGraphicsUtils.getIconWidth(handleIcon, context),
+ SynthGraphicsUtils.getIconHeight(handleIcon, context));
}
SynthContext subcontext = getContext(
@@ -358,7 +357,7 @@
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
dim.width = tb.isFloatable() ?
- SynthIcon.getIconWidth(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
@@ -370,7 +369,7 @@
}
} else {
dim.height = tb.isFloatable() ?
- SynthIcon.getIconHeight(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
@@ -396,7 +395,7 @@
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
dim.width = tb.isFloatable() ?
- SynthIcon.getIconWidth(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
@@ -408,7 +407,7 @@
}
} else {
dim.height = tb.isFloatable() ?
- SynthIcon.getIconHeight(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
Dimension compDim;
for (int i = 0; i < tb.getComponentCount(); i++) {
Component component = tb.getComponent(i);
@@ -449,7 +448,7 @@
if (tb.getOrientation() == JToolBar.HORIZONTAL) {
int handleWidth = tb.isFloatable() ?
- SynthIcon.getIconWidth(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
// Note: contentRect does not take insets into account
// since it is used for determining the bounds that are
@@ -500,7 +499,7 @@
}
} else {
int handleHeight = tb.isFloatable() ?
- SynthIcon.getIconHeight(handleIcon, context) : 0;
+ SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
// See notes above regarding the use of insets
contentRect.x = 0;
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java Tue Nov 17 13:24:06 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java Wed Nov 18 19:13:42 2015 +0400
@@ -47,7 +47,6 @@
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
-import sun.swing.plaf.synth.SynthIcon;
/**
* Provides the Synth L&F UI delegate for
@@ -610,10 +609,10 @@
@Override
protected void drawCentered(Component c, Graphics graphics, Icon icon,
int x, int y) {
- int w = SynthIcon.getIconWidth(icon, paintContext);
- int h = SynthIcon.getIconHeight(icon, paintContext);
+ int w = SynthGraphicsUtils.getIconWidth(icon, paintContext);
+ int h = SynthGraphicsUtils.getIconHeight(icon, paintContext);
- SynthIcon.paintIcon(icon, paintContext, graphics,
+ SynthGraphicsUtils.paintIcon(icon, paintContext, graphics,
findCenteredX(x, w),
y - h/2, w, h);
}
@@ -780,16 +779,16 @@
// To get the correct context we return an instance of this that fetches
// the SynthContext as needed.
//
- private class ExpandedIconWrapper extends SynthIcon {
+ private class ExpandedIconWrapper implements SynthIcon {
public void paintIcon(SynthContext context, Graphics g, int x,
int y, int w, int h) {
if (context == null) {
context = getContext(tree);
- SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
+ SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
context.dispose();
}
else {
- SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
+ SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
}
}
@@ -797,11 +796,11 @@
int width;
if (context == null) {
context = getContext(tree);
- width = SynthIcon.getIconWidth(expandedIcon, context);
+ width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
context.dispose();
}
else {
- width = SynthIcon.getIconWidth(expandedIcon, context);
+ width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
}
return width;
}
@@ -810,11 +809,11 @@
int height;
if (context == null) {
context = getContext(tree);
- height = SynthIcon.getIconHeight(expandedIcon, context);
+ height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
context.dispose();
}
else {
- height = SynthIcon.getIconHeight(expandedIcon, context);
+ height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
}
return height;
}
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthIcon.java Tue Nov 17 13:24:06 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.swing.plaf.synth;
-
-import javax.swing.plaf.synth.*;
-import java.awt.*;
-import javax.swing.*;
-import javax.swing.border.Border;
-import javax.swing.plaf.UIResource;
-
-/**
- * An icon that is passed a SynthContext. Subclasses need only implement
- * the variants that take a SynthContext, but must be prepared for the
- * SynthContext to be null.
- *
- * @author Scott Violet
- */
-public abstract class SynthIcon implements Icon {
- public static int getIconWidth(Icon icon, SynthContext context) {
- if (icon == null) {
- return 0;
- }
- if (icon instanceof SynthIcon) {
- return ((SynthIcon)icon).getIconWidth(context);
- }
- return icon.getIconWidth();
- }
-
- public static int getIconHeight(Icon icon, SynthContext context) {
- if (icon == null) {
- return 0;
- }
- if (icon instanceof SynthIcon) {
- return ((SynthIcon)icon).getIconHeight(context);
- }
- return icon.getIconHeight();
- }
-
- public static void paintIcon(Icon icon, SynthContext context, Graphics g,
- int x, int y, int w, int h) {
- if (icon instanceof SynthIcon) {
- ((SynthIcon)icon).paintIcon(context, g, x, y, w, h);
- }
- else if (icon != null) {
- icon.paintIcon(context.getComponent(), g, x, y);
- }
- }
-
- /**
- * Paints the icon at the specified location.
- *
- * @param context Identifies hosting region, may be null.
- * @param x x location to paint to
- * @param y y location to paint to
- * @param w Width of the region to paint to, may be 0
- * @param h Height of the region to paint to, may be 0
- */
- public abstract void paintIcon(SynthContext context, Graphics g, int x,
- int y, int w, int h);
-
- /**
- * Returns the desired width of the Icon.
- *
- * @param context SynthContext requesting the Icon, may be null.
- * @return Desired width of the icon.
- */
- public abstract int getIconWidth(SynthContext context);
-
- /**
- * Returns the desired height of the Icon.
- *
- * @param context SynthContext requesting the Icon, may be null.
- * @return Desired height of the icon.
- */
- public abstract int getIconHeight(SynthContext context);
-
- /**
- * Paints the icon. This is a cover method for
- * <code>paintIcon(null, g, x, y, 0, 0)</code>
- */
- public void paintIcon(Component c, Graphics g, int x, int y) {
- paintIcon(null, g, x, y, 0, 0);
- }
-
- /**
- * Returns the icon's width. This is a cover methods for
- * <code>getIconWidth(null)</code>.
- *
- * @return an int specifying the fixed width of the icon.
- */
- public int getIconWidth() {
- return getIconWidth(null);
- }
-
- /**
- * Returns the icon's height. This is a cover method for
- * <code>getIconHeight(null)</code>.
- *
- * @return an int specifying the fixed height of the icon.
- */
- public int getIconHeight() {
- return getIconHeight(null);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/synth/8081411/bug8081411.java Wed Nov 18 19:13:42 2015 +0400
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import javax.swing.Icon;
+import javax.swing.JMenuItem;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.plaf.synth.Region;
+import javax.swing.plaf.synth.SynthConstants;
+import javax.swing.plaf.synth.SynthContext;
+import javax.swing.plaf.synth.SynthGraphicsUtils;
+import javax.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthLookAndFeel;
+import javax.swing.plaf.synth.SynthStyle;
+
+/*
+ * @test
+ * @bug 8081411
+ * @summary Add an API for painting an icon with a SynthContext
+ * @author Alexander Scherbatiy
+ */
+public class bug8081411 {
+
+ private static final Color TEST_COLOR = new Color(71, 71, 72);
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(bug8081411::testSynthIcon);
+ }
+
+ private static void testSynthIcon() {
+
+ if (!checkAndSetNimbusLookAndFeel()) {
+ return;
+ }
+
+ JMenuItem menu = new JMenuItem();
+ Icon subMenuIcon = UIManager.getIcon("Menu.arrowIcon");
+
+ if (!(subMenuIcon instanceof SynthIcon)) {
+ throw new RuntimeException("Icon is not a SynthIcon!");
+ }
+
+ Region region = SynthLookAndFeel.getRegion(menu);
+ SynthStyle style = SynthLookAndFeel.getStyle(menu, region);
+ SynthContext synthContext = new SynthContext(menu, region, style, SynthConstants.ENABLED);
+
+ int width = SynthGraphicsUtils.getIconWidth(subMenuIcon, synthContext);
+ int height = SynthGraphicsUtils.getIconHeight(subMenuIcon, synthContext);
+ paintAndCheckIcon(subMenuIcon, synthContext, width, height);
+
+ int newWidth = width * 17;
+ int newHeight = height * 37;
+ Icon centeredIcon = new CenteredSynthIcon((SynthIcon) subMenuIcon,
+ newWidth, newHeight);
+ paintAndCheckIcon(centeredIcon, synthContext, newWidth, newHeight);
+ }
+
+ private static void paintAndCheckIcon(Icon icon, SynthContext synthContext,
+ int width, int height) {
+
+ BufferedImage buffImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ Graphics g = buffImage.createGraphics();
+ g.setColor(Color.RED);
+ g.fillRect(0, 0, width, height);
+ SynthGraphicsUtils.paintIcon(icon, synthContext, g, 0, 0, width, height);
+ g.dispose();
+
+ Color iconCenterColor = new Color(buffImage.getRGB(width / 2, height / 2));
+
+ if (!TEST_COLOR.equals(iconCenterColor)) {
+ throw new RuntimeException("Icon is painted incorrectly!");
+ }
+ }
+
+ private static boolean checkAndSetNimbusLookAndFeel() {
+ try {
+ for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ UIManager.setLookAndFeel(info.getClassName());
+ return true;
+ }
+ }
+ return false;
+ } catch (Exception ignore) {
+ return false;
+ }
+ }
+
+ private static class CenteredSynthIcon implements SynthIcon {
+
+ private final SynthIcon icon;
+ private final int width;
+ private final int height;
+
+ public CenteredSynthIcon(SynthIcon icon, int width, int height) {
+ this.icon = icon;
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public void paintIcon(SynthContext syntContext, Graphics g, int x, int y,
+ int w, int h) {
+ int dw = icon.getIconWidth(syntContext);
+ int dh = icon.getIconHeight(syntContext);
+ int dx = width - dw;
+ int dy = height - dh;
+ icon.paintIcon(syntContext, g, x + dx / 2, y + dy / 2,
+ dw + 2, dh + 2);
+ }
+
+ @Override
+ public int getIconWidth(SynthContext sc) {
+ return width;
+ }
+
+ @Override
+ public int getIconHeight(SynthContext sc) {
+ return height;
+ }
+ }
+}