diff options
Diffstat (limited to 'javax')
-rw-r--r-- | javax/swing/JComponent.java | 57 | ||||
-rw-r--r-- | javax/swing/RepaintManager.java | 136 | ||||
-rw-r--r-- | javax/swing/SwingUtilities.java | 23 |
3 files changed, 113 insertions, 103 deletions
diff --git a/javax/swing/JComponent.java b/javax/swing/JComponent.java index 66c562d11..bb2326d69 100644 --- a/javax/swing/JComponent.java +++ b/javax/swing/JComponent.java @@ -671,6 +671,12 @@ public abstract class JComponent extends Container implements Serializable static boolean isPaintingDoubleBuffered = false; /** + * Indicates whether we are calling paintDoubleBuffered() from + * paintImmadiately (RepaintManager) or from paint() (AWT refresh). + */ + static private boolean isRepainting = false; + + /** * Listeners for events other than {@link PropertyChangeEvent} are * handled by this listener list. PropertyChangeEvents are handled in * {@link #changeSupport}. @@ -1855,7 +1861,7 @@ public abstract class JComponent extends Container implements Serializable index < children.length; index++) { Component comp = children[index]; - if (! comp.isVisible()) + if (! comp.isVisible() || ! comp.isLightweight()) continue; Rectangle compBounds = comp.getBounds(); @@ -2027,7 +2033,7 @@ public abstract class JComponent extends Container implements Serializable if (i == children.length - 1) paintingTile = false; - if (!children[i].isVisible()) + if (!children[i].isVisible() || ! children[i].isLightweight()) continue; Rectangle bounds = children[i].getBounds(rectCache); @@ -2131,41 +2137,16 @@ public abstract class JComponent extends Container implements Serializable */ void paintImmediately2(Rectangle r) { + isRepainting = true; RepaintManager rm = RepaintManager.currentManager(this); if (rm.isDoubleBufferingEnabled() && isDoubleBuffered()) paintDoubleBuffered(r); else paintSimple(r); + isRepainting = false; } /** - * Gets the root of the component given. If a parent of the - * component is an instance of Applet, then the applet is - * returned. The applet is considered the root for painting - * and adding/removing components. Otherwise, the root Window - * is returned if it exists. - * - * @param comp - The component to get the root for. - * @return the parent root. An applet if it is a parent, - * or the root window. If neither exist, null is returned. - */ - private Component getRoot(Component comp) - { - Applet app = null; - - while (comp != null) - { - if (app == null && comp instanceof Window) - return comp; - else if (comp instanceof Applet) - app = (Applet) comp; - comp = comp.getParent(); - } - - return app; - } - - /** * Performs double buffered repainting. */ private void paintDoubleBuffered(Rectangle r) @@ -2173,7 +2154,7 @@ public abstract class JComponent extends Container implements Serializable RepaintManager rm = RepaintManager.currentManager(this); // Paint on the offscreen buffer. - Component root = getRoot(this); + Component root = SwingUtilities.getRoot(this); Image buffer = rm.getVolatileOffscreenBuffer(this, root.getWidth(), root.getHeight()); @@ -2183,7 +2164,6 @@ public abstract class JComponent extends Container implements Serializable buffer = rm.getOffscreenBuffer(this, root.getWidth(), root.getHeight()); //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root); - Point translation = SwingUtilities.convertPoint(this, 0, 0, root); Graphics g2 = buffer.getGraphics(); clipAndTranslateGraphics(root, this, g2); g2.clipRect(r.x, r.y, r.width, r.height); @@ -2191,7 +2171,14 @@ public abstract class JComponent extends Container implements Serializable isPaintingDoubleBuffered = true; try { - paint(g2); + if (isRepainting) // Called from paintImmediately, go through paint(). + paint(g2); + else // Called from paint() (AWT refresh), don't call it again. + { + paintComponent(g2); + paintBorder(g2); + paintChildren(g2); + } } finally { @@ -2200,9 +2187,7 @@ public abstract class JComponent extends Container implements Serializable } // Paint the buffer contents on screen. - rm.commitBuffer(root, new Rectangle(translation.x + r.x, - translation.y + r.y, r.width, - r.height)); + rm.commitBuffer(this, r); } /** @@ -3654,7 +3639,7 @@ public abstract class JComponent extends Container implements Serializable { if ((found instanceof JComponent) && ((JComponent) found).isOpaque()) break; - else if (!(found instanceof JComponent)) + else if (!(found instanceof JComponent) && !found.isLightweight()) break; Container p = found.getParent(); if (p == null) diff --git a/javax/swing/RepaintManager.java b/javax/swing/RepaintManager.java index f95934123..a82b3163a 100644 --- a/javax/swing/RepaintManager.java +++ b/javax/swing/RepaintManager.java @@ -618,7 +618,7 @@ public class RepaintManager public Image getOffscreenBuffer(Component component, int proposedWidth, int proposedHeight) { - Component root = getRoot(component); + Component root = SwingUtilities.getWindowAncestor(component); Image buffer = (Image) offscreenBuffers.get(root); if (buffer == null || buffer.getWidth(null) < proposedWidth @@ -635,43 +635,26 @@ public class RepaintManager } /** - * Gets the root of the component given. If a parent of the - * component is an instance of Applet, then the applet is - * returned. The applet is considered the root for painting. - * Otherwise, the root Window is returned if it exists. - * - * @param comp - The component to get the root for. - * @return the parent root. An applet if it is a parent, - * or the root window. If neither exist, null is returned. - */ - private Component getRoot(Component comp) - { - Applet app = null; - - while (comp != null) - { - if (app == null && comp instanceof Window) - return comp; - else if (comp instanceof Applet) - app = (Applet) comp; - comp = comp.getParent(); - } - - return app; - } - - /** * Blits the back buffer of the specified root component to the screen. If * the RepaintManager is currently working on a paint request, the commit * requests are queued up and committed at once when the paint request is * done (by {@link #commitRemainingBuffers}). This is package private because * it must get called by JComponent. * - * @param root the component, either a Window or an Applet instance - * @param area the area to paint on screen + * @param comp the component to be painted + * @param area the area to paint on screen, in comp coordinates */ - void commitBuffer(Component root, Rectangle area) + void commitBuffer(Component comp, Rectangle area) { + // Determine the component that we finally paint the buffer upon. + // We need to paint on the nearest heavyweight component, so that Swing + // hierarchies inside (non-window) heavyweights get painted correctly. + // Otherwise we would end up blitting the backbuffer behind the heavyweight + // which is wrong. + Component root = getHeavyweightParent(comp); + // FIXME: Optimize this. + Rectangle rootRect = SwingUtilities.convertRectangle(comp, area, root); + // We synchronize on dirtyComponents here because that is what // paintDirtyRegions also synchronizes on while painting. synchronized (dirtyComponents) @@ -680,54 +663,73 @@ public class RepaintManager // blit the requested buffer on the screen. if (! repaintUnderway) { - Graphics g = root.getGraphics(); - Image buffer = (Image) offscreenBuffers.get(root); - Rectangle clip = g.getClipBounds(); - if (clip != null) - area = SwingUtilities.computeIntersection(clip.x, clip.y, - clip.width, clip.height, - area); - int dx1 = area.x; - int dy1 = area.y; - int dx2 = area.x + area.width; - int dy2 = area.y + area.height; - // Make sure we have a sane clip at this point. - g.clipRect(area.x, area.y, area.width, area.height); - - // Make sure the coordinates are inside the buffer, everything else - // might lead to problems. - // TODO: This code should not really be necessary, however, in fact - // we have two issues here: - // 1. We shouldn't get repaint requests in areas outside the buffer - // region in the first place. This still happens for example - // when a component is inside a JViewport, and the component has - // a size that would reach beyond the window size. - // 2. Graphics.drawImage() should not behave strange when trying - // to draw regions outside the image. - int bufferWidth = buffer.getWidth(root); - int bufferHeight = buffer.getHeight(root); - dx1 = Math.min(bufferWidth, dx1); - dy1 = Math.min(bufferHeight, dy1); - dx2 = Math.min(bufferWidth, dx2); - dy2 = Math.min(bufferHeight, dy2); - g.drawImage(buffer, 0, 0, root); - g.dispose(); + blitBuffer(root, rootRect); } + // Otherwise queue this request up, until all the RepaintManager work // is done. else { if (commitRequests.containsKey(root)) - SwingUtilities.computeUnion(area.x, area.y, area.width, - area.height, + SwingUtilities.computeUnion(rootRect.x, rootRect.y, + rootRect.width, rootRect.height, (Rectangle) commitRequests.get(root)); else - commitRequests.put(root, area); + commitRequests.put(root, rootRect); } } } /** + * Copies the buffer to the screen. Note that the root component here is + * not necessarily the component with which the offscreen buffer is + * associated. The offscreen buffers are always allocated for the toplevel + * windows. However, painted is performed on lower-level heavyweight + * components too, if they contain Swing components. + * + * @param root the heavyweight component to blit upon + * @param rootRect the rectangle in the root component's coordinate space + */ + private void blitBuffer(Component root, Rectangle rootRect) + { + // Find the Window from which we use the backbuffer. + Component bufferRoot = root; + Rectangle bufferRect = rootRect.getBounds(); + if (!(bufferRoot instanceof Window)) + { + bufferRoot = SwingUtilities.getWindowAncestor(bufferRoot); + SwingUtilities.convertRectangleToAncestor(root, rootRect, bufferRoot); + } + + Graphics g = root.getGraphics(); + Image buffer = (Image) offscreenBuffers.get(bufferRoot); + + // Make sure we have a sane clip at this point. + g.clipRect(rootRect.x, rootRect.y, rootRect.width, rootRect.height); + g.drawImage(buffer, rootRect.x - bufferRect.x, rootRect.y - bufferRect.y, + root); + g.dispose(); + + } + + /** + * Finds and returns the nearest heavyweight parent for the specified + * component. If the component isn't contained inside a heavyweight parent, + * this returns null. + * + * @param comp the component + * + * @return the nearest heavyweight parent for the specified component or + * null if the component has no heavyweight ancestor + */ + private Component getHeavyweightParent(Component comp) + { + while (comp != null && comp.isLightweight()) + comp = comp.getParent(); + return comp; + } + + /** * Commits the queued up back buffers to screen all at once. */ private void commitRemainingBuffers() @@ -743,7 +745,7 @@ public class RepaintManager Map.Entry entry = (Map.Entry) i.next(); Component root = (Component) entry.getKey(); Rectangle area = (Rectangle) entry.getValue(); - commitBuffer(root, area); + blitBuffer(root, area); i.remove(); } } @@ -767,7 +769,7 @@ public class RepaintManager public Image getVolatileOffscreenBuffer(Component comp, int proposedWidth, int proposedHeight) { - Component root = getRoot(comp); + Component root = SwingUtilities.getWindowAncestor(comp); Image buffer = (Image) offscreenBuffers.get(root); if (buffer == null || buffer.getWidth(null) < proposedWidth diff --git a/javax/swing/SwingUtilities.java b/javax/swing/SwingUtilities.java index 5d02d9bb3..d7808ba60 100644 --- a/javax/swing/SwingUtilities.java +++ b/javax/swing/SwingUtilities.java @@ -1599,4 +1599,27 @@ public class SwingUtilities throw new IllegalArgumentException("Unrecognised code: " + code); } } + + /** + * Converts a rectangle in the coordinate system of a child component into + * a rectangle of one of it's Ancestors. The result is stored in the input + * rectangle. + * + * @param comp the child component + * @param r the rectangle to convert + * @param ancestor the ancestor component + */ + static void convertRectangleToAncestor(Component comp, Rectangle r, + Component ancestor) + { + if (comp == ancestor) + return; + + r.x += comp.getX(); + r.y += comp.getY(); + + Component parent = comp.getParent(); + if (parent != null && parent != ancestor) + convertRectangleToAncestor(parent, r, ancestor); + } } |