From 9d7121c18080d088db9c2cadb7955508f0d22df8 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 25 Nov 2020 20:28:10 +0000 Subject: [PATCH] 8256713: SwingSet2 : Slider leaves tracks in uiScale=2 Reviewed-by: jdv, psadhukhan --- .../javax/swing/plaf/basic/BasicSliderUI.java | 52 ++++++-- .../swing/plaf/metal/MetalIconFactory.java | 35 +++++- .../swing/JSlider/Thumb/PaintThumbSize.java | 118 ++++++++++++++++++ 3 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 test/jdk/javax/swing/JSlider/Thumb/PaintThumbSize.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index df4f058427255..83192db4f3cbd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, 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,20 +25,52 @@ package javax.swing.plaf.basic; -import java.awt.event.*; -import java.awt.*; -import java.beans.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.IllegalComponentStateException; +import java.awt.Insets; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Dictionary; import java.util.Enumeration; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.plaf.*; +import javax.swing.AbstractAction; +import javax.swing.BoundedRangeModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MouseInputAdapter; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.plaf.SliderUI; + import sun.swing.DefaultLookup; import sun.swing.SwingUtilities2; import sun.swing.UIAction; - /** * A Basic L&F implementation of SliderUI. * @@ -1486,6 +1518,8 @@ public void paintThumb(Graphics g) { int h = knobBounds.height; g.translate(knobBounds.x, knobBounds.y); + Rectangle clip = g.getClipBounds(); + g.clipRect(0, 0, w, h); if ( slider.isEnabled() ) { g.setColor(slider.getBackground()); @@ -1581,7 +1615,7 @@ else if ( slider.getOrientation() == JSlider.HORIZONTAL ) { g.drawLine(w-1, 1, w-1, h-2 ); // right } } - + g.setClip(clip); g.translate(-knobBounds.x, -knobBounds.y); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalIconFactory.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalIconFactory.java index 96e295c24cbda..9df2b625e1862 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalIconFactory.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalIconFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, 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,16 +25,33 @@ package javax.swing.plaf.metal; -import javax.swing.*; -import javax.swing.plaf.UIResource; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.Serializable; -import java.util.Enumeration; import java.util.Vector; + +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JRadioButton; +import javax.swing.plaf.UIResource; + import sun.swing.CachedPainter; -import static sun.swing.SwingUtilities2.setAntialiasingHintForScaledGraphics; + import static sun.swing.SwingUtilities2.getAndSetAntialisingHintForScaledGraphics; +import static sun.swing.SwingUtilities2.setAntialiasingHintForScaledGraphics; /** * Factory object that vends Icons for @@ -2401,6 +2418,8 @@ public void paintIcon( Component c, Graphics g, int x, int y ) { boolean leftToRight = MetalUtils.isLeftToRight(c); g.translate( x, y ); + Rectangle clip = g.getClipBounds(); + g.clipRect(0, 0, getIconWidth(), getIconHeight()); // Draw the frame if ( c.hasFocus() ) { @@ -2479,6 +2498,7 @@ public void paintIcon( Component c, Graphics g, int x, int y ) { } } + g.setClip(clip); g.translate( -x, -y ); } @@ -2508,6 +2528,8 @@ public HorizontalSliderThumbIcon() { public void paintIcon( Component c, Graphics g, int x, int y ) { g.translate( x, y ); + Rectangle clip = g.getClipBounds(); + g.clipRect(0, 0, getIconWidth(), getIconHeight()); // Draw the frame if ( c.hasFocus() ) { @@ -2558,6 +2580,7 @@ public void paintIcon( Component c, Graphics g, int x, int y ) { g.drawLine( 1, 1, 1, 8 ); } + g.setClip(clip); g.translate( -x, -y ); } diff --git a/test/jdk/javax/swing/JSlider/Thumb/PaintThumbSize.java b/test/jdk/javax/swing/JSlider/Thumb/PaintThumbSize.java new file mode 100644 index 0000000000000..9bd0916823f54 --- /dev/null +++ b/test/jdk/javax/swing/JSlider/Thumb/PaintThumbSize.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020, 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.EventQueue; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.JSlider; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.SliderUI; +import javax.swing.plaf.basic.BasicSliderUI; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/** + * @test + * @bug 8256713 + * @key headful + * @summary The thumb should not touch pixels outside its location. + */ +public final class PaintThumbSize { + + private static final int SCALE = 2; + private static final int SHIFT = 100; + + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + EventQueue.invokeAndWait(() -> setLookAndFeel(laf)); + EventQueue.invokeAndWait(PaintThumbSize::test); + if (laf.getClassName().contains("Metal")) { + EventQueue.invokeAndWait(() -> { + System.err.println("\tAdditional theme: DefaultMetalTheme"); + MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme()); + test(); + }); + } + } + } + + private static void test() { + BufferedImage bi = new BufferedImage(500, 500, TYPE_INT_ARGB); + Graphics2D g = bi.createGraphics(); + g.setColor(Color.CYAN); + g.fillRect(0, 0, bi.getWidth(), bi.getHeight()); + g.setColor(Color.BLACK); + + g.scale(SCALE, SCALE); + g.translate(SHIFT, SHIFT); + + JSlider slider = new JSlider(); + SliderUI ui = slider.getUI(); + if (ui instanceof BasicSliderUI) { + BasicSliderUI bui = (BasicSliderUI) ui; + bui.setThumbLocation(0, 0); + bui.paintThumb(g); + + for (int y = 0; y < bi.getHeight(); ++y) { + for (int x = 0; x < bi.getWidth(); ++x) { + if (x >= SHIFT * SCALE && y >= SHIFT * SCALE) { + continue; + } + if (bi.getRGB(x, y) != Color.CYAN.getRGB()) { + System.err.println("x = " + x); + System.err.println("y = " + y); + try { + ImageIO.write(bi,"png", new File("image.png")); + } catch (IOException e) { + e.printStackTrace(); + } + throw new RuntimeException("Wrong color"); + } + } + } + } + g.dispose(); + } + + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + System.err.println("LookAndFeel: " + laf.getClassName()); + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.err.println("Unsupported LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } +}