diff options
Diffstat (limited to 'libjava/classpath/javax/swing/JComponent.java')
-rw-r--r-- | libjava/classpath/javax/swing/JComponent.java | 803 |
1 files changed, 423 insertions, 380 deletions
diff --git a/libjava/classpath/javax/swing/JComponent.java b/libjava/classpath/javax/swing/JComponent.java index fa83502946d..5ec5079223e 100644 --- a/libjava/classpath/javax/swing/JComponent.java +++ b/libjava/classpath/javax/swing/JComponent.java @@ -69,6 +69,7 @@ import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; import java.io.Serializable; +import java.util.ArrayList; import java.util.EventListener; import java.util.Hashtable; import java.util.Locale; @@ -503,27 +504,6 @@ public abstract class JComponent extends Container implements Serializable } } - /** - * An explicit value for the component's preferred size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getPreferredSize} method on the {@link #ui} property. - */ - Dimension preferredSize; - - /** - * An explicit value for the component's minimum size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getMinimumSize} method on the {@link #ui} property. - */ - Dimension minimumSize; - - /** - * An explicit value for the component's maximum size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getMaximumSize} method on the {@link #ui} property. - */ - Dimension maximumSize; - /** * A value between 0.0 and 1.0 indicating the preferred horizontal * alignment of the component, relative to its siblings. The values @@ -561,14 +541,6 @@ public abstract class JComponent extends Container implements Serializable */ Border border; - /** - * The text to show in the tooltip associated with this component. - * - * @see #setToolTipText - * @see #getToolTipText() - */ - String toolTipText; - /** * The popup menu for the component. * @@ -687,7 +659,7 @@ public abstract class JComponent extends Container implements Serializable * Indicates whether we are calling paintDoubleBuffered() from * paintImmadiately (RepaintManager) or from paint() (AWT refresh). */ - static private boolean isRepainting = false; + static boolean isRepainting = false; /** * Listeners for events other than {@link PropertyChangeEvent} are @@ -783,6 +755,13 @@ public abstract class JComponent extends Container implements Serializable */ public static final int WHEN_IN_FOCUSED_WINDOW = 2; + + /** + * Used to optimize painting. This is set in paintImmediately2() to specify + * the exact component path to be painted by paintChildren. + */ + Component paintChild; + /** * Indicates if the opaque property has been set by a client program or by * the UI. @@ -868,7 +847,12 @@ public abstract class JComponent extends Container implements Serializable t.put(key, value); else t.remove(key); - firePropertyChange(key.toString(), old, value); + + // When both old and new value are null, no event is fired. This is + // different from what firePropertyChange() normally does, so we add this + // check here. + if (old != null || value != null) + firePropertyChange(key.toString(), old, value); } /** @@ -943,12 +927,12 @@ public abstract class JComponent extends Container implements Serializable * * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == PropertyChangeListener.class) - return getPropertyChangeListeners(); + return (T[]) getPropertyChangeListeners(); else if (listenerType == VetoableChangeListener.class) - return getVetoableChangeListeners(); + return (T[]) getVetoableChangeListeners(); else return listenerList.getListeners(listenerType); } @@ -1270,37 +1254,38 @@ public abstract class JComponent extends Container implements Serializable } /** - * Get the component's maximum size. If the {@link #maximumSize} property - * has been explicitly set, it is returned. If the {@link #maximumSize} + * Get the component's maximum size. If the <code>maximumSize</code> property + * has been explicitly set, it is returned. If the <code>maximumSize</code> * property has not been set but the {@link #ui} property has been, the * result of {@link ComponentUI#getMaximumSize} is returned. If neither * property has been set, the result of {@link Container#getMaximumSize} * is returned. * - * @return The maximum size of the component + * @return the maximum size of the component * - * @see #maximumSize - * @see #setMaximumSize + * @see Component#setMaximumSize + * @see Component#getMaximumSize() + * @see Component#isMaximumSizeSet() + * @see ComponentUI#getMaximumSize(JComponent) */ public Dimension getMaximumSize() { - if (maximumSize != null) - return maximumSize; - - if (ui != null) + Dimension size = null; + if (isMaximumSizeSet()) + size = super.getMaximumSize(); + else { - Dimension s = ui.getMaximumSize(this); - if (s != null) - return s; + if (ui != null) + size = ui.getMaximumSize(this); + if (size == null) + size = super.getMaximumSize(); } - - Dimension p = super.getMaximumSize(); - return p; + return size; } /** - * Get the component's minimum size. If the {@link #minimumSize} property - * has been explicitly set, it is returned. If the {@link #minimumSize} + * Get the component's minimum size. If the <code>minimumSize</code> property + * has been explicitly set, it is returned. If the <code>minimumSize</code> * property has not been set but the {@link #ui} property has been, the * result of {@link ComponentUI#getMinimumSize} is returned. If neither * property has been set, the result of {@link Container#getMinimumSize} @@ -1308,97 +1293,57 @@ public abstract class JComponent extends Container implements Serializable * * @return The minimum size of the component * - * @see #minimumSize - * @see #setMinimumSize + * @see Component#setMinimumSize + * @see Component#getMinimumSize() + * @see Component#isMinimumSizeSet() + * @see ComponentUI#getMinimumSize(JComponent) */ public Dimension getMinimumSize() { - if (minimumSize != null) - return minimumSize; - - if (ui != null) + Dimension size = null; + if (isMinimumSizeSet()) + size = super.getMinimumSize(); + else { - Dimension s = ui.getMinimumSize(this); - if (s != null) - return s; + if (ui != null) + size = ui.getMinimumSize(this); + if (size == null) + size = super.getMinimumSize(); } - - Dimension p = super.getMinimumSize(); - return p; + return size; } /** - * Get the component's preferred size. If the {@link #preferredSize} - * property has been explicitly set, it is returned. If the {@link - * #preferredSize} property has not been set but the {@link #ui} property - * has been, the result of {@link ComponentUI#getPreferredSize} is + * Get the component's preferred size. If the <code>preferredSize</code> + * property has been explicitly set, it is returned. If the + * <code>preferredSize</code> property has not been set but the {@link #ui} + * property has been, the result of {@link ComponentUI#getPreferredSize} is * returned. If neither property has been set, the result of {@link * Container#getPreferredSize} is returned. * * @return The preferred size of the component * - * @see #preferredSize - * @see #setPreferredSize + * @see Component#setPreferredSize + * @see Component#getPreferredSize() + * @see Component#isPreferredSizeSet() + * @see ComponentUI#getPreferredSize(JComponent) */ public Dimension getPreferredSize() { - Dimension prefSize = null; - if (preferredSize != null) - prefSize = new Dimension(preferredSize); - - else if (ui != null) + Dimension size = null; + if (isPreferredSizeSet()) + size = super.getPreferredSize(); + else { - Dimension s = ui.getPreferredSize(this); - if (s != null) - prefSize = s; + if (ui != null) + size = ui.getPreferredSize(this); + if (size == null) + size = super.getPreferredSize(); } - - if (prefSize == null) - prefSize = super.getPreferredSize(); - - return prefSize; + return size; } /** - * Checks if a maximum size was explicitely set on the component. - * - * @return <code>true</code> if a maximum size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isMaximumSizeSet() - { - return maximumSize != null; - } - - /** - * Checks if a minimum size was explicitely set on the component. - * - * @return <code>true</code> if a minimum size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isMinimumSizeSet() - { - return minimumSize != null; - } - - /** - * Checks if a preferred size was explicitely set on the component. - * - * @return <code>true</code> if a preferred size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isPreferredSizeSet() - { - return preferredSize != null; - } - - /** * Return the value of the <code>nextFocusableComponent</code> property. * * @return The current value of the property, or <code>null</code> @@ -1491,14 +1436,12 @@ public abstract class JComponent extends Container implements Serializable { JToolTip toolTip = new JToolTip(); toolTip.setComponent(this); - toolTip.setTipText(toolTipText); - return toolTip; } /** - * Return the location at which the {@link #toolTipText} property should be - * displayed, when triggered by a particular mouse event. + * Return the location at which the <code>toolTipText</code> property should + * be displayed, when triggered by a particular mouse event. * * @param event The event the tooltip is being presented in response to * @@ -1511,53 +1454,56 @@ public abstract class JComponent extends Container implements Serializable } /** - * Set the value of the {@link #toolTipText} property. + * Set the tooltip text for this component. If a non-<code>null</code> + * value is set, this component is registered in the + * <code>ToolTipManager</code> in order to turn on tooltips for this + * component. If a <code>null</code> value is set, tooltips are turne off + * for this component. * - * @param text The new property value + * @param text the tooltip text for this component * * @see #getToolTipText() + * @see #getToolTipText(MouseEvent) */ public void setToolTipText(String text) { + String old = getToolTipText(); + putClientProperty(TOOL_TIP_TEXT_KEY, text); + ToolTipManager ttm = ToolTipManager.sharedInstance(); if (text == null) - { - ToolTipManager.sharedInstance().unregisterComponent(this); - toolTipText = null; - return; - } - - // XXX: The tip text doesn't get updated unless you set it to null - // and then to something not-null. This is consistent with the behaviour - // of Sun's ToolTipManager. - - String oldText = toolTipText; - toolTipText = text; - - if (oldText == null) - ToolTipManager.sharedInstance().registerComponent(this); + ttm.unregisterComponent(this); + else if (old == null) + ttm.registerComponent(this); } /** - * Get the value of the {@link #toolTipText} property. + * Returns the current tooltip text for this component, or <code>null</code> + * if none has been set. * - * @return The current property value + * @return the current tooltip text for this component, or <code>null</code> + * if none has been set * * @see #setToolTipText + * @see #getToolTipText(MouseEvent) */ public String getToolTipText() { - return toolTipText; + return (String) getClientProperty(TOOL_TIP_TEXT_KEY); } /** - * Get the value of the {@link #toolTipText} property, in response to a - * particular mouse event. + * Returns the tooltip text for this component for a particular mouse + * event. This can be used to support context sensitive tooltips that can + * change with the mouse location. By default this returns the static + * tooltip text returned by {@link #getToolTipText()}. * - * @param event The mouse event which triggered the tooltip + * @param event the mouse event which triggered the tooltip * - * @return The current property value + * @return the tooltip text for this component for a particular mouse + * event * * @see #setToolTipText + * @see #getToolTipText() */ public String getToolTipText(MouseEvent event) { @@ -1850,7 +1796,7 @@ public abstract class JComponent extends Container implements Serializable && rm.isDoubleBufferingEnabled()) { Rectangle clip = g.getClipBounds(); - paintDoubleBuffered(clip); + paintDoubleBuffered(clip.x, clip.y, clip.width, clip.height); } else { @@ -1865,8 +1811,22 @@ public abstract class JComponent extends Container implements Serializable dragBuffer = null; } - if (g.getClip() == null) - g.setClip(0, 0, getWidth(), getHeight()); + Rectangle clip = g.getClipBounds(); + int clipX, clipY, clipW, clipH; + if (clip == null) + { + clipX = 0; + clipY = 0; + clipW = getWidth(); + clipH = getHeight(); + } + else + { + clipX = clip.x; + clipY = clip.y; + clipW = clip.width; + clipH = clip.height; + } if (dragBuffer != null && dragBufferInitialized) { g.drawImage(dragBuffer, 0, 0, this); @@ -1874,14 +1834,51 @@ public abstract class JComponent extends Container implements Serializable else { Graphics g2 = getComponentGraphics(g); - paintComponent(g2); - paintBorder(g2); + if (! isOccupiedByChild(clipX, clipY, clipW, clipH)) + { + paintComponent(g2); + paintBorder(g2); + } paintChildren(g2); } } } /** + * Determines if a region of this component is completely occupied by + * an opaque child component, in which case we don't need to bother + * painting this component at all. + * + * @param x the area, x coordinate + * @param y the area, y coordinate + * @param w the area, width + * @param h the area, height + * + * @return <code>true</code> if the specified area is completely covered + * by a child component, <code>false</code> otherwise + */ + private boolean isOccupiedByChild(int x, int y, int w, int h) + { + boolean occupied = false; + int count = getComponentCount(); + for (int i = 0; i < count; i++) + { + Component child = getComponent(i); + int cx = child.getX(); + int cy = child.getY(); + int cw = child.getWidth(); + int ch = child.getHeight(); + if (child.isVisible() && x >= cx && x + w <= cx + cw && y >= cy + && y + h <= cy + ch) + { + occupied = child.isOpaque(); + break; + } + } + return occupied; + } + + /** * Initializes the drag buffer by creating a new image and painting this * component into it. */ @@ -1940,7 +1937,14 @@ public abstract class JComponent extends Container implements Serializable // Need to lock the tree to avoid problems with AWT and concurrency. synchronized (getTreeLock()) { - for (int i = getComponentCount() - 1; i >= 0; i--) + // Fast forward to the child to paint, if set by + // paintImmediately2() + int i = getComponentCount() - 1; + if (paintChild != null && paintChild.isOpaque()) + { + for (; i >= 0 && getComponent(i) != paintChild; i--); + } + for (; i >= 0; i--) { Component child = getComponent(i); if (child != null && child.isLightweight() @@ -1958,7 +1962,8 @@ public abstract class JComponent extends Container implements Serializable Rectangle clip = g.getClipBounds(); // A copy. SwingUtilities.computeIntersection(cx, cy, cw, ch, clip); - if (isCompletelyObscured(i, clip)) + if (isCompletelyObscured(i, clip.x, clip.y, + clip.width, clip.height)) continue; // Continues the for-loop. } Graphics cg = g.create(cx, cy, cw, ch); @@ -1984,12 +1989,15 @@ public abstract class JComponent extends Container implements Serializable * of its siblings. * * @param index the index of the child component - * @param rect the region to check + * @param x the region to check, x coordinate + * @param y the region to check, y coordinate + * @param w the region to check, width + * @param h the region to check, height * * @return <code>true</code> if the region is completely obscured by a * sibling, <code>false</code> otherwise */ - private boolean isCompletelyObscured(int index, Rectangle rect) + private boolean isCompletelyObscured(int index, int x, int y, int w, int h) { boolean obscured = false; for (int i = index - 1; i >= 0 && obscured == false; i--) @@ -1998,10 +2006,10 @@ public abstract class JComponent extends Container implements Serializable if (sib.isVisible()) { Rectangle sibRect = sib.getBounds(rectCache); - if (sib.isOpaque() && rect.x >= sibRect.x - && (rect.x + rect.width) <= (sibRect.x + sibRect.width) - && rect.y >= sibRect.y - && (rect.y + rect.height) <= (sibRect.y + sibRect.height)) + if (sib.isOpaque() && x >= sibRect.x + && (x + w) <= (sibRect.x + sibRect.width) + && y >= sibRect.y + && (y + h) <= (sibRect.y + sibRect.height)) { obscured = true; } @@ -2011,6 +2019,39 @@ public abstract class JComponent extends Container implements Serializable } /** + * Checks if a component/rectangle is partially obscured by one of its + * siblings. + * Note that this doesn't check for completely obscured, this is + * done by isCompletelyObscured() and should probably also be checked. + * + * @param i the component index from which to start searching + * @param x the x coordinate of the rectangle to check + * @param y the y coordinate of the rectangle to check + * @param w the width of the rectangle to check + * @param h the height of the rectangle to check + * + * @return <code>true</code> if the rectangle is partially obscured + */ + private boolean isPartiallyObscured(int i, int x, int y, int w, int h) + { + boolean obscured = false; + for (int j = i - 1; j >= 0 && ! obscured; j--) + { + Component sibl = getComponent(j); + if (sibl.isVisible()) + { + Rectangle rect = sibl.getBounds(rectCache); + if (!(x + w <= rect.x) + || (y + h <= rect.y) + || (x >= rect.x + rect.width) + || (y >= rect.y + rect.height)) + obscured = true; + } + } + return obscured; + } + + /** * Paint the component's body. This usually means calling {@link * ComponentUI#update} on the {@link #ui} property of the component, if * it is non-<code>null</code>. You may override this if you wish to @@ -2050,7 +2091,26 @@ public abstract class JComponent extends Container implements Serializable */ public void paintImmediately(int x, int y, int w, int h) { - paintImmediately(new Rectangle(x, y, w, h)); + // Find opaque parent and call paintImmediately2() on it. + if (isShowing()) + { + Component c = this; + Component p; + while (c != null && ! c.isOpaque()) + { + p = c.getParent(); + if (p != null) + { + x += c.getX(); + y += c.getY(); + c = p; + } + } + if (c instanceof JComponent) + ((JComponent) c).paintImmediately2(x, y, w, h); + else + c.repaint(x, y, w, h); + } } /** @@ -2073,60 +2133,202 @@ public abstract class JComponent extends Container implements Serializable */ public void paintImmediately(Rectangle r) { - // Try to find a root pane for this component. - //Component root = findPaintRoot(r); - Component root = findPaintRoot(r); - // If no paint root is found, then this component is completely overlapped - // by another component and we don't need repainting. - if (root == null|| !root.isShowing()) - return; - SwingUtilities.convertRectangleToAncestor(this, r, root); - if (root instanceof JComponent) - ((JComponent) root).paintImmediately2(r); - else - root.repaint(r.x, r.y, r.width, r.height); + paintImmediately(r.x, r.y, r.width, r.height); } /** * Performs the actual work of paintImmediatly on the repaint root. * - * @param r the area to be repainted + * @param x the area to be repainted, X coordinate + * @param y the area to be repainted, Y coordinate */ - void paintImmediately2(Rectangle r) + void paintImmediately2(int x, int y, int w, int h) { - isRepainting = true; + // Optimization for components that are always painted on top. + boolean onTop = onTop() && isOpaque(); + + // Fetch the RepaintManager. RepaintManager rm = RepaintManager.currentManager(this); - if (rm.isDoubleBufferingEnabled() && isPaintingDoubleBuffered()) - paintDoubleBuffered(r); - else - paintSimple(r); - isRepainting = false; + + // The painting clip; + int paintX = x; + int paintY = y; + int paintW = w; + int paintH = h; + + // If we should paint buffered or not. + boolean haveBuffer = false; + + // The component that is finally triggered for painting. + JComponent paintRoot = this; + + // Stores the component and all its parents. This will be used to limit + // the actually painted components in paintChildren by setting + // the field paintChild. + int pIndex = -1; + int pCount = 0; + ArrayList components = new ArrayList(); + + // Offset to subtract from the paintRoot rectangle when painting. + int offsX = 0; + int offsY = 0; + + // The current component and its child. + Component child; + Container c; + + // Find appropriate paint root. + for (c = this, child = null; + c != null && ! (c instanceof Window) && ! (c instanceof Applet); + child = c, c = c.getParent()) + { + JComponent jc = c instanceof JComponent ? (JComponent) c : null; + components.add(c); + if (! onTop && jc != null && ! jc.isOptimizedDrawingEnabled()) + { + // Indicates whether we reset the paint root to be the current + // component. + boolean updatePaintRoot = false; + + // Check obscured state of the child. + // Generally, we have 3 cases here: + // 1. Not obscured. No need to paint from the parent. + // 2. Partially obscured. Paint from the parent. + // 3. Completely obscured. No need to paint anything. + if (c != this) + { + if (jc.isPaintRoot()) + updatePaintRoot = true; + else + { + int count = c.getComponentCount(); + int i = 0; + for (; i < count && c.getComponent(i) != child; i++); + + if (jc.isCompletelyObscured(i, paintX, paintY, paintW, + paintH)) + return; // No need to paint anything. + else if (jc.isPartiallyObscured(i, paintX, paintY, paintW, + paintH)) + updatePaintRoot = true; + + } + } + if (updatePaintRoot) + { + // Paint from parent. + paintRoot = jc; + pIndex = pCount; + offsX = 0; + offsY = 0; + haveBuffer = false; + } + } + pCount++; + // Check if component is double buffered. + if (rm.isDoubleBufferingEnabled() && jc != null + && jc.isDoubleBuffered()) + { + haveBuffer = true; + } + + // Clip the paint region with the parent. + if (! onTop) + { + paintX = Math.max(0, paintX); + paintY = Math.max(0, paintY); + paintW = Math.min(c.getWidth(), paintW + paintX) - paintX; + paintH = Math.min(c.getHeight(), paintH + paintY) - paintY; + int dx = c.getX(); + int dy = c.getY(); + paintX += dx; + paintY += dy; + offsX += dx; + offsY += dy; + } + } + if (c != null && c.getPeer() != null && paintW > 0 && paintH > 0) + { + isRepainting = true; + paintX -= offsX; + paintY -= offsY; + + // Set the painting path so that paintChildren paints only what we + // want. + if (paintRoot != this) + { + for (int i = pIndex; i > 0; i--) + { + Component paintParent = (Component) components.get(i); + if (paintParent instanceof JComponent) + ((JComponent) paintParent).paintChild = + (Component) components.get(i - 1); + } + } + + // Actually trigger painting. + if (haveBuffer) + paintRoot.paintDoubleBuffered(paintX, paintY, paintW, paintH); + else + { + Graphics g = paintRoot.getGraphics(); + try + { + g.setClip(paintX, paintY, paintW, paintH); + paintRoot.paint(g); + } + finally + { + g.dispose(); + } + } + + // Reset the painting path. + if (paintRoot != this) + { + for (int i = pIndex; i > 0; i--) + { + Component paintParent = (Component) components.get(i); + if (paintParent instanceof JComponent) + ((JComponent) paintParent).paintChild = null; + } + } + + isRepainting = false; + } } /** - * Returns true if we must paint double buffered, that is, when this - * component or any of it's ancestors are double buffered. + * Returns <code>true</code> if the component is guaranteed to be painted + * on top of others. This returns false by default and is overridden by + * components like JMenuItem, JPopupMenu and JToolTip to return true for + * added efficiency. * - * @return true if we must paint double buffered, that is, when this - * component or any of it's ancestors are double buffered + * @return <code>true</code> if the component is guaranteed to be painted + * on top of others */ - private boolean isPaintingDoubleBuffered() + boolean onTop() { - boolean doubleBuffered = isDoubleBuffered(); - Component parent = getParent(); - while (! doubleBuffered && parent != null) - { - doubleBuffered = parent instanceof JComponent - && ((JComponent) parent).isDoubleBuffered(); - parent = parent.getParent(); - } - return doubleBuffered; + return false; + } + + /** + * This returns true when a component needs to force itself as a paint + * origin. This is used for example in JViewport to make sure that it + * gets to update its backbuffer. + * + * @return true when a component needs to force itself as a paint + * origin + */ + boolean isPaintRoot() + { + return false; } /** * Performs double buffered repainting. */ - private void paintDoubleBuffered(Rectangle r) + private void paintDoubleBuffered(int x, int y, int w, int h) { RepaintManager rm = RepaintManager.currentManager(this); @@ -2143,7 +2345,7 @@ public abstract class JComponent extends Container implements Serializable //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root); Graphics g2 = buffer.getGraphics(); clipAndTranslateGraphics(root, this, g2); - g2.clipRect(r.x, r.y, r.width, r.height); + g2.clipRect(x, y, w, h); g2 = getComponentGraphics(g2); paintingDoubleBuffered = true; try @@ -2164,7 +2366,7 @@ public abstract class JComponent extends Container implements Serializable } // Paint the buffer contents on screen. - rm.commitBuffer(this, r); + rm.commitBuffer(this, x, y, w, h); } /** @@ -2577,7 +2779,7 @@ public abstract class JComponent extends Container implements Serializable KeyEvent e, int condition, boolean pressed) - { + { if (isEnabled()) { Action act = null; @@ -2591,7 +2793,7 @@ public abstract class JComponent extends Container implements Serializable if (cmd instanceof ActionListenerProxy) act = (Action) cmd; else - act = (Action) getActionMap().get(cmd); + act = getActionMap().get(cmd); } } if (act != null && act.isEnabled()) @@ -2741,9 +2943,25 @@ public abstract class JComponent extends Container implements Serializable */ public void scrollRectToVisible(Rectangle r) { - Component p = getParent(); - if (p instanceof JComponent) - ((JComponent) p).scrollRectToVisible(r); + // Search nearest JComponent. + int xOffs = getX(); + int yOffs = getY(); + Component p; + for (p = getParent(); p != null && ! (p instanceof JComponent); + p = p.getParent()) + { + xOffs += p.getX(); + yOffs += p.getY(); + } + if (p != null) + { + r.x += xOffs; + r.y += yOffs; + JComponent jParent = (JComponent) p; + jParent.scrollRectToVisible(r); + r.x -= xOffs; + r.y -= yOffs; + } } /** @@ -2862,57 +3080,6 @@ public abstract class JComponent extends Container implements Serializable } /** - * Set the value of the {@link #maximumSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param max The new value of the property - */ - public void setMaximumSize(Dimension max) - { - Dimension oldMaximumSize = maximumSize; - if (max != null) - maximumSize = new Dimension(max); - else - maximumSize = null; - firePropertyChange("maximumSize", oldMaximumSize, maximumSize); - } - - /** - * Set the value of the {@link #minimumSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param min The new value of the property - */ - public void setMinimumSize(Dimension min) - { - Dimension oldMinimumSize = minimumSize; - if (min != null) - minimumSize = new Dimension(min); - else - minimumSize = null; - firePropertyChange("minimumSize", oldMinimumSize, minimumSize); - } - - /** - * Set the value of the {@link #preferredSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param pref The new value of the property - */ - public void setPreferredSize(Dimension pref) - { - Dimension oldPreferredSize = preferredSize; - if (pref != null) - preferredSize = new Dimension(pref); - else - preferredSize = null; - firePropertyChange("preferredSize", oldPreferredSize, preferredSize); - } - - /** * Set the specified component to be the next component in the * focus cycle, overriding the {@link FocusTraversalPolicy} for * this component. @@ -3571,130 +3738,6 @@ public abstract class JComponent extends Container implements Serializable jc.fireAncestorEvent(ancestor, id); } } - - /** - * Finds a suitable paint root for painting this component. This method first - * checks if this component is overlapped using - * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then - * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque - * component for this paint root. If no paint is necessary, then we return - * <code>null</code>. - * - * @param c the clip of this component - * - * @return the paint root or <code>null</code> if no painting is necessary - */ - private Component findPaintRoot(Rectangle c) - { - Component p = findOverlapFreeParent(c); - if (p == null) - return null; - Component root = findOpaqueParent(p); - return root; - } - - /** - * Scans the containment hierarchy upwards for components that overlap the - * this component in the specified clip. This method returns - * <code>this</code>, if no component overlaps this component. It returns - * <code>null</code> if another component completely covers this component - * in the specified clip (no repaint necessary). If another component partly - * overlaps this component in the specified clip, then the parent of this - * component is returned (this is the component that must be used as repaint - * root). For efficient lookup, the method - * {@link #isOptimizedDrawingEnabled()} is used. - * - * @param clip the clip of this component - * - * @return the paint root, or <code>null</code> if no paint is necessary - */ - private Component findOverlapFreeParent(Rectangle clip) - { - Rectangle currentClip = clip; - Component found = this; - Container parent = this; - - while (parent != null && !(parent instanceof Window)) - { - Container newParent = parent.getParent(); - if (newParent == null || newParent instanceof Window) - break; - // If the parent is optimizedDrawingEnabled, then its children are - // tiled and cannot have an overlapping child. Go directly to next - // parent. - if ((newParent instanceof JComponent - && ((JComponent) newParent).isOptimizedDrawingEnabled())) - - { - parent = newParent; - continue; - } - - // If the parent is not optimizedDrawingEnabled, we must check if the - // parent or some neighbor overlaps the current clip. - - // This is the current clip converted to the parent's coordinate - // system. TODO: We can do this more efficiently by succesively - // cumulating the parent-child translations. - Rectangle target = SwingUtilities.convertRectangle(found, - currentClip, - newParent); - - // We have an overlap if either: - // - The new parent itself doesn't completely cover the clip - // (this can be the case with viewports). - // - If some higher-level (than the current) children of the new parent - // intersect the target rectangle. - Rectangle parentRect = SwingUtilities.getLocalBounds(newParent); - boolean haveOverlap = - ! SwingUtilities.isRectangleContainingRectangle(parentRect, target); - if (! haveOverlap) - { - Component child; - for (int i = 0; (child = newParent.getComponent(i)) != parent && !haveOverlap; i++) - { - Rectangle childRect = child.getBounds(); - haveOverlap = target.intersects(childRect); - } - } - if (haveOverlap) - { - found = newParent; - currentClip = target; - } - parent = newParent; - } - //System.err.println("overlapfree parent: " + found); - return found; - } - - /** - * Finds the nearest component to <code>c</code> (upwards in the containment - * hierarchy), that is opaque. If <code>c</code> itself is opaque, - * this returns <code>c</code> itself. - * - * @param c the start component for the search - * @return the nearest component to <code>c</code> (upwards in the containment - * hierarchy), that is opaque; If <code>c</code> itself is opaque, - * this returns <code>c</code> itself - */ - private Component findOpaqueParent(Component c) - { - Component found = c; - while (true) - { - if ((found instanceof JComponent) && ((JComponent) found).isOpaque()) - break; - else if (!(found instanceof JComponent) && !found.isLightweight()) - break; - Container p = found.getParent(); - if (p == null) - break; - else - found = p; - } - return found; - } /** * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map |