diff --git a/src/macosx/classes/com/apple/laf/AquaMenuBarBorder.java b/src/macosx/classes/com/apple/laf/AquaMenuBarBorder.java index 389eb4cfeec746e7fd307b412cdd2c848fc0b1ea..bd5ab2b6a8a5e24547aedf55fff6ad0cf76f9969 100644 --- a/src/macosx/classes/com/apple/laf/AquaMenuBarBorder.java +++ b/src/macosx/classes/com/apple/laf/AquaMenuBarBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,46 +25,33 @@ package com.apple.laf; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; import javax.swing.border.Border; +import sun.swing.SwingUtilities2; + +/** + * The class represents the border of a {@code JMenuBar}. + */ public class AquaMenuBarBorder implements Border { - public AquaMenuBarBorder() { - super(); - } - /** - * Paints the border for the specified component with the specified - * position and size. - * @param c the component for which this border is being painted - * @param g the paint graphics - * @param x the x position of the painted border - * @param y the y position of the painted border - * @param width the width of the painted border - * @param height the height of the painted border - */ - public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { - // for now we don't paint a border. We let the button paint it since there - // needs to be a strict ordering for aqua components. - //paintButton(c, g, x, y, width, height); + @Override + public void paintBorder(final Component c, final Graphics g, final int x, + final int y, final int width, final int height) { g.setColor(Color.gray); - g.drawLine(x, y + height - 1, x + width, y + height - 1); + SwingUtilities2.drawHLine(g, x, x + width - 1, y + height - 1); } - /** - * Returns the insets of the border. - * @param c the component for which this border insets value applies - */ + @Override public Insets getBorderInsets(final Component c) { return new Insets(0, 0, 1, 0); } - /** - * Returns whether or not the border is opaque. If the border - * is opaque, it is responsible for filling in it's own - * background when painting. - */ + @Override public boolean isBorderOpaque() { return false; } diff --git a/src/share/classes/javax/swing/plaf/basic/BasicBorders.java b/src/share/classes/javax/swing/plaf/basic/BasicBorders.java index be06927017cb8e7cf822ff0eb9ba08b959001b22..5e58480a2ada160147dfd9dae2e48c64269df922 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicBorders.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicBorders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,6 +37,8 @@ import java.awt.Rectangle; import java.awt.Color; import java.awt.Graphics; +import sun.swing.SwingUtilities2; + /** * Factory object that can vend Borders appropriate for the basic L & F. * @author Georges Saab @@ -337,10 +339,10 @@ public class BasicBorders { Color oldColor = g.getColor(); g.translate(x, y); g.setColor(shadow); - g.drawLine(0, height-2, width, height-2); + SwingUtilities2.drawHLine(g, 0, width - 1, height - 2); g.setColor(highlight); - g.drawLine(0, height-1, width, height-1); - g.translate(-x,-y); + SwingUtilities2.drawHLine(g, 0, width - 1, height - 1); + g.translate(-x, -y); g.setColor(oldColor); } diff --git a/src/share/classes/javax/swing/plaf/metal/MetalBorders.java b/src/share/classes/javax/swing/plaf/metal/MetalBorders.java index 24c3d5a15d1b8b183ad268e4b1c7884109fe6ac3..f2b92450ad0bb1559b6667dd783780664236c2a6 100644 --- a/src/share/classes/javax/swing/plaf/metal/MetalBorders.java +++ b/src/share/classes/javax/swing/plaf/metal/MetalBorders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -40,6 +40,7 @@ import java.awt.Graphics; import java.awt.Window; import sun.swing.StringUIClientPropertyKey; +import sun.swing.SwingUtilities2; /** @@ -528,25 +529,22 @@ public class MetalBorders { protected static Insets borderInsets = new Insets( 1, 0, 1, 0 ); public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { - g.translate( x, y ); + g.translate(x, y); if (MetalLookAndFeel.usingOcean()) { - // Only paint a border if we're not next to a horizontal - // toolbar - if ((c instanceof JMenuBar) && !MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) { + // Only paint a border if we're not next to a horizontal toolbar + if (c instanceof JMenuBar + && !MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) { g.setColor(MetalLookAndFeel.getControl()); - g.drawLine(0, h - 2, w, h - 2); + SwingUtilities2.drawHLine(g, 0, w - 1, h - 2); g.setColor(UIManager.getColor("MenuBar.borderColor")); - g.drawLine(0, h - 1, w, h - 1); + SwingUtilities2.drawHLine(g, 0, w - 1, h - 1); } + } else { + g.setColor(MetalLookAndFeel.getControlShadow()); + SwingUtilities2.drawHLine(g, 0, w - 1, h - 1); } - else { - g.setColor( MetalLookAndFeel.getControlShadow() ); - g.drawLine( 0, h-1, w, h-1 ); - } - - g.translate( -x, -y ); - + g.translate(-x, -y); } public Insets getBorderInsets(Component c, Insets newInsets) { diff --git a/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java b/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java new file mode 100644 index 0000000000000000000000000000000000000000..43a7dc31533b857ed3edc3664ef273137ddce991 --- /dev/null +++ b/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java @@ -0,0 +1,135 @@ +/* + * 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.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/** + * @test + * @bug 8073795 + * @summary JMenuBar has incorrect border when the window is on retina display. + * @author Sergey Bylokhov + * @run main/othervm MisplacedBorder + * @run main/othervm -Dswing.metalTheme=steel MisplacedBorder + */ +public final class MisplacedBorder implements Runnable { + + public static final int W = 400; + public static final int H = 400; + + public static void main(final String[] args) throws Exception { + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + SwingUtilities.invokeAndWait(new MisplacedBorder()); + } + System.out.println("Test passed"); + } + + @Override + public void run() { + final JMenuBar menubar = new JMenuBar(); + menubar.add(new JMenu("")); + menubar.add(new JMenu("")); + final JFrame frame = new JFrame(); + frame.setUndecorated(true); + frame.setJMenuBar(menubar); + frame.setSize(W / 3, H / 3); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + // draw menu bar using standard order. + final BufferedImage bi1 = step1(menubar); + + // draw menu border on top of the menu bar, nothing should be changed. + final BufferedImage bi2 = step2(menubar); + frame.dispose(); + + for (int x = 0; x < W; ++x) { + for (int y = 0; y < H; ++y) { + if (bi1.getRGB(x, y) != bi2.getRGB(x, y)) { + try { + ImageIO.write(bi1, "png", new File("image1.png")); + ImageIO.write(bi2, "png", new File("image2.png")); + } catch (IOException e) { + e.printStackTrace(); + } + throw new RuntimeException("Failed: wrong color"); + } + } + } + } + + /** + * Draws standard JMenuBar. + */ + private BufferedImage step1(final JMenuBar menubar) { + final BufferedImage bi1 = new BufferedImage(W, H, TYPE_INT_ARGB_PRE); + final Graphics2D g2d = bi1.createGraphics(); + g2d.scale(2, 2); + g2d.setColor(Color.RED); + g2d.fillRect(0, 0, W, H); + menubar.paintAll(g2d); + g2d.dispose(); + return bi1; + } + + /** + * Draws standard JMenuBar and border on top of it. + */ + private BufferedImage step2(final JMenuBar menubar) { + final BufferedImage bi2 = new BufferedImage(W, H, TYPE_INT_ARGB_PRE); + final Graphics2D g2d2 = bi2.createGraphics(); + g2d2.scale(2, 2); + g2d2.setColor(Color.RED); + g2d2.fillRect(0, 0, W, H); + menubar.paintAll(g2d2); + menubar.getBorder().paintBorder(menubar, g2d2, menubar.getX(), menubar + .getX(), menubar.getWidth(), menubar.getHeight()); + g2d2.dispose(); + return bi2; + } + + private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + System.out.println("LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + UnsupportedLookAndFeelException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file