6989617: Enable JComponent to control repaintings of its children
authoralexp
Wed, 20 Oct 2010 19:37:48 +0400
changeset 7005 5e6d24f4303b
parent 7004 3f92ea1ffcac
child 7006 05505fff1342
6989617: Enable JComponent to control repaintings of its children Reviewed-by: rupashka
jdk/src/share/classes/javax/swing/JComponent.java
jdk/src/share/classes/javax/swing/JLayer.java
jdk/src/share/classes/javax/swing/JViewport.java
jdk/src/share/classes/javax/swing/RepaintManager.java
jdk/test/javax/swing/JComponent/6989617/bug6989617.java
--- 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();
+    }
+}