I checked in a neat little optimization for painting overlapping
children. Up to now we always painted the whole stack of components for
a given clip, from the bottom up to the top. This is really not
necessary if one of the components spans the whole clip. In this case we
don't need to paint the underlying components. I added this checking in
JComponent.paintChildren as well as the implementation of the
isPaintingTile() method.
This should significantly improve performance for all overlapping
components like menus, JLayeredPanes, Popups, JTabbedPanes, etc.
2005-10-10 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/JComponent.java
(paintingTile): New field.
(isPaintingTile): Implemented.
(paintChildren): Optimized painting of overlapping children.
/Roman
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.81
diff -u -r1.81 JComponent.java
--- javax/swing/JComponent.java 9 Nov 2005 23:14:39 -0000 1.81
+++ javax/swing/JComponent.java 10 Nov 2005 12:35:13 -0000
@@ -555,6 +555,11 @@
private TransferHandler transferHandler;
/**
+ * Indicates if this component is currently painting a tile or not.
+ */
+ private boolean paintingTile;
+
+ /**
* A cached Rectangle object to be reused. Be careful when you use that,
* so that it doesn't get modified in another context within the same
* method call chain.
@@ -1614,13 +1619,16 @@
}
/**
- * Return <code>true</code> if this component is currently painting a tile.
+ * Return <code>true</code> if this component is currently painting a tile,
+ * this means that paint() is called again on another child component. This
+ * method returns <code>false</code> if this component does not paint a tile
+ * or if the last tile is currently painted.
*
- * @return Whether the component is painting a tile
+ * @return whether the component is painting a tile
*/
public boolean isPaintingTile()
{
- return false;
+ return paintingTile;
}
/**
@@ -1735,8 +1743,38 @@
Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
g.clipRect(inner.x, inner.y, inner.width, inner.height);
Component[] children = getComponents();
- for (int i = children.length - 1; i >= 0; --i)
+
+ // Find the bottommost component that needs to be painted. This is a
+ // component that completely covers the current clip and is opaque. In
+ // this case we don't need to paint the components below it.
+ int startIndex = children.length - 1;
+ // No need to check for overlapping components when this component is
+ // optimizedDrawingEnabled (== it tiles its children).
+ if (! isOptimizedDrawingEnabled())
{
+ Rectangle clip = g.getClipBounds();
+ for (int i = 0; i < children.length; i++)
+ {
+ Rectangle childBounds = children[i].getBounds();
+ if (children[i].isOpaque()
+ && SwingUtilities.isRectangleContainingRectangle(childBounds,
+ g.getClipBounds()))
+ {
+ startIndex = i;
+ break;
+ }
+ }
+ }
+ // paintingTile becomes true just before we start painting the component's
+ // children.
+ paintingTile = true;
+ for (int i = startIndex; i >= 0; --i)
+ {
+ // paintingTile must be set to false before we begin to start painting
+ // the last tile.
+ if (i == 0)
+ paintingTile = false;
+
if (!children[i].isVisible())
continue;
@@ -3287,7 +3325,9 @@
/**
* This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
* is changed.
- * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW map
+ *
+ * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
+ * map
*/
void updateComponentInputMap(ComponentInputMap changed)
{
_______________________________________________
Classpath-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/classpath-patches