6989617: Enable JComponent to control repaintings of its children
Reviewed-by: rupashka
--- a/jdk/src/share/classes/javax/swing/JComponent.java Wed Oct 20 15:08:39 2010 +0400
+++ b/jdk/src/share/classes/javax/swing/JComponent.java Wed Oct 20 19:37:48 2010 +0400
@@ -4783,21 +4783,11 @@
* @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 @@
* currently pending events have been dispatched.
*
* @param r a <code>Rectangle</code> containing the dirty region
+ * @see #isPaintingOrigin()
* @see java.awt.Component#isShowing
* @see RepaintManager#addDirtyRegion
*/
@@ -4912,13 +4903,19 @@
}
/**
- * 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.
+ * <p/>
+ * Calling {@link JComponent#repaint} on a Swing component will be delegated to
+ * the first ancestor which {@code isPaintingOrigin()} returns {@true},
+ * if there are any.
+ * <p/>
+ * {@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.
- */
- boolean isPaintingOrigin() {
+ * @return always returns {@code false}
+ */
+ protected boolean isPaintingOrigin() {
return false;
}
--- a/jdk/src/share/classes/javax/swing/JLayer.java Wed Oct 20 15:08:39 2010 +0400
+++ b/jdk/src/share/classes/javax/swing/JLayer.java Wed Oct 20 19:37:48 2010 +0400
@@ -384,7 +384,7 @@
* @return true
* @see JComponent#isPaintingOrigin()
*/
- boolean isPaintingOrigin() {
+ protected boolean isPaintingOrigin() {
return true;
}
--- a/jdk/src/share/classes/javax/swing/JViewport.java Wed Oct 20 15:08:39 2010 +0400
+++ b/jdk/src/share/classes/javax/swing/JViewport.java Wed Oct 20 19:37:48 2010 +0400
@@ -637,14 +637,14 @@
}
/**
- * Returns true if scroll mode is a BACKINGSTORE_SCROLL_MODE to cause
- * painting to originate from <code>JViewport</code>, 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;
}
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java Wed Oct 20 15:08:39 2010 +0400
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java Wed Oct 20 19:37:48 2010 +0400
@@ -438,6 +438,7 @@
* @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 @@
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);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/6989617/bug6989617.java Wed Oct 20 19:37:48 2010 +0400
@@ -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();
+ }
+}