diff --git a/src/share/classes/javax/swing/JComponent.java b/src/share/classes/javax/swing/JComponent.java index f94a797ae6c695113bf43e54a8a88d2fb1bf2d7b..6f017402ec7e01e9d8f6b1bc480a35ae7c38e0e8 100644 --- a/src/share/classes/javax/swing/JComponent.java +++ b/src/share/classes/javax/swing/JComponent.java @@ -4783,21 +4783,11 @@ public abstract class JComponent extends Container implements Serializable, * @param y the y value of the dirty region * @param width the width of the dirty region * @param height the height of the dirty region + * @see #isPaintingOrigin() * @see java.awt.Component#isShowing * @see RepaintManager#addDirtyRegion */ public void repaint(long tm, int x, int y, int width, int height) { - Container p = this; - while ((p = p.getParent()) instanceof JComponent) { - JComponent jp = (JComponent) p; - if (jp.isPaintingOrigin()) { - Rectangle rectangle = SwingUtilities.convertRectangle( - this, new Rectangle(x, y, width, height), jp); - jp.repaint(tm, - rectangle.x, rectangle.y, rectangle.width, rectangle.height); - return; - } - } RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height); } @@ -4808,6 +4798,7 @@ public abstract class JComponent extends Container implements Serializable, * currently pending events have been dispatched. * * @param r a Rectangle containing the dirty region + * @see #isPaintingOrigin() * @see java.awt.Component#isShowing * @see RepaintManager#addDirtyRegion */ @@ -4912,13 +4903,19 @@ public abstract class JComponent extends Container implements Serializable, } /** - * Returns true if a paint triggered on a child component should cause + * Returns {@code true} if a paint triggered on a child component should cause * painting to originate from this Component, or one of its ancestors. + *

+ * Calling {@link JComponent#repaint} on a Swing component will be delegated to + * the first ancestor which {@code isPaintingOrigin()} returns {@true}, + * if there are any. + *

+ * {@code JComponent} subclasses that need to be repainted when any of their + * children are repainted should override this method to return {@code true}. * - * @return true if painting should originate from this Component or - * one of its ancestors. + * @return always returns {@code false} */ - boolean isPaintingOrigin() { + protected boolean isPaintingOrigin() { return false; } diff --git a/src/share/classes/javax/swing/JLayer.java b/src/share/classes/javax/swing/JLayer.java index c01c4450767fc78cdcfadc23e61ac0bf32f5be14..8da354103f96ade5a46e8b7549346b7462dc227f 100644 --- a/src/share/classes/javax/swing/JLayer.java +++ b/src/share/classes/javax/swing/JLayer.java @@ -384,7 +384,7 @@ public final class JLayer * @return true * @see JComponent#isPaintingOrigin() */ - boolean isPaintingOrigin() { + protected boolean isPaintingOrigin() { return true; } diff --git a/src/share/classes/javax/swing/JViewport.java b/src/share/classes/javax/swing/JViewport.java index 97dacb30b4bf23c0e3b671b148037b11dd7f1b27..f171cd6a8a831a4e796199e3b5a15b8d1a27d36f 100644 --- a/src/share/classes/javax/swing/JViewport.java +++ b/src/share/classes/javax/swing/JViewport.java @@ -637,14 +637,14 @@ public class JViewport extends JComponent implements Accessible } /** - * Returns true if scroll mode is a BACKINGSTORE_SCROLL_MODE to cause - * painting to originate from JViewport, or one of its - * ancestors. Otherwise returns false. + * Returns true if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE} to cause + * painting to originate from {@code JViewport}, or one of its + * ancestors. Otherwise returns {@code false}. * - * @return true if if scroll mode is a BACKINGSTORE_SCROLL_MODE. + * @return true if if scroll mode is a {@code BACKINGSTORE_SCROLL_MODE}. * @see JComponent#isPaintingOrigin() */ - boolean isPaintingOrigin() { + protected boolean isPaintingOrigin() { return scrollMode == BACKINGSTORE_SCROLL_MODE; } diff --git a/src/share/classes/javax/swing/RepaintManager.java b/src/share/classes/javax/swing/RepaintManager.java index d1166f90633fcaa37a8771e4c55d58a0de909434..63444b422be246d3b189da54ba55228134688673 100644 --- a/src/share/classes/javax/swing/RepaintManager.java +++ b/src/share/classes/javax/swing/RepaintManager.java @@ -438,6 +438,7 @@ public class RepaintManager * @param y Y coordinate of the region to repaint * @param w Width of the region to repaint * @param h Height of the region to repaint + * @see JComponent#isPaintingOrigin() * @see JComponent#repaint */ public void addDirtyRegion(JComponent c, int x, int y, int w, int h) @@ -447,6 +448,16 @@ public class RepaintManager delegate.addDirtyRegion(c, x, y, w, h); return; } + Container p = c; + while ((p = p.getParent()) instanceof JComponent) { + JComponent jp = (JComponent) p; + if (jp.isPaintingOrigin()) { + Rectangle rectangle = SwingUtilities.convertRectangle( + c, new Rectangle(x, y, w, h), jp); + jp.repaint(0, rectangle.x, rectangle.y, rectangle.width, rectangle.height); + return; + } + } addDirtyRegion0(c, x, y, w, h); } diff --git a/test/javax/swing/JComponent/6989617/bug6989617.java b/test/javax/swing/JComponent/6989617/bug6989617.java new file mode 100644 index 0000000000000000000000000000000000000000..7f7aa958bf6d567eaaffaf63726b1eebdb5c2e92 --- /dev/null +++ b/test/javax/swing/JComponent/6989617/bug6989617.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010, 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. + */ + +/* @test + @bug 6989617 + @summary Enable JComponent to control repaintings of its children + @author Alexander Potochkin + @run main bug6989617 +*/ + +import javax.swing.*; +import java.awt.*; + +public class bug6989617 { + + private boolean isPaintingOrigin; + private boolean innerPanelRepainted, outerPanelRepainted; + + public bug6989617() { + + final JButton button = new JButton("button"); + + JPanel innerPanel = new JPanel() { + protected boolean isPaintingOrigin() { + return isPaintingOrigin; + } + + public void repaint(long tm, int x, int y, int width, int height) { + if (button.getParent() != null) { + innerPanelRepainted = true; + if (!button.getSize().equals(new Dimension(width, height))) { + throw new RuntimeException("Wrong size of the dirty area"); + } + if (!button.getLocation().equals(new Point(x, y))) { + throw new RuntimeException("Wrong location of the dirty area"); + } + } + super.repaint(tm, x, y, width, height); + } + }; + + JPanel outerPanel = new JPanel() { + protected boolean isPaintingOrigin() { + return isPaintingOrigin; + } + + public void repaint(long tm, int x, int y, int width, int height) { + if (button.getParent() != null) { + outerPanelRepainted = true; + if (!button.getSize().equals(new Dimension(width, height))) { + throw new RuntimeException("Wrong size of the dirty area"); + } + } + super.repaint(tm, x, y, width, height); + } + }; + + + outerPanel.add(innerPanel); + innerPanel.add(button); + + outerPanel.setSize(100, 100); + innerPanel.setBounds(10, 10, 50, 50); + button.setBounds(10, 10, 20, 20); + + if (innerPanelRepainted || outerPanelRepainted) { + throw new RuntimeException("Repainted flag is unexpectedly on"); + } + button.repaint(); + if (innerPanelRepainted || outerPanelRepainted) { + throw new RuntimeException("Repainted flag is unexpectedly on"); + } + isPaintingOrigin = true; + button.repaint(); + if (!innerPanelRepainted || !outerPanelRepainted) { + throw new RuntimeException("Repainted flag is unexpectedly off"); + } + } + + public static void main(String... args) throws Exception { + new bug6989617(); + } +}