[cp-patches] FYI: JLayeredPane fixes

2006-06-23 Thread Roman Kennke
A couple of fixes for the JLayeredPane. This fixes the behaviour of
toFront(), toBack(), setPosition() and setLayer() which was slightly
broken before.

2006-06-23  Roman Kennke  <[EMAIL PROTECTED]>

* javax/swing/JLayeredPane.java
(getPosition): Moved code around to avoid unnecessary method
calls.
(setPosition): Delegate to setLayer().
(insertIndexForLayer(int,int)): Delegate to new private helper
method.
(insertIndexForLayer(Component,int,int)): New helper method
to support the use of setComponentZOrder() which doesn't remove
the component and thus the insertIndexForLayer must ignore
the component to be moved to get the index right.
(setLayer): Added check to prevent unnecessary execution of
method body. Changed to update the component order here.
Added repaint() to make sure that the update becomes visible.
(addImpl): Call setLayer() only when a constraint has been
specified.
Validate and repaint the JLayeredPane.

/Roman

-- 
“Improvement makes straight roads, but the crooked roads, without
Improvement, are roads of Genius.” - William Blake
Index: javax/swing/JLayeredPane.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JLayeredPane.java,v
retrieving revision 1.46
diff -u -2 -0 -r1.46 JLayeredPane.java
--- javax/swing/JLayeredPane.java	1 Jun 2006 04:38:49 -	1.46
+++ javax/swing/JLayeredPane.java	23 Jun 2006 11:07:55 -
@@ -26,40 +26,41 @@
 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing;
 
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Container;
 import java.awt.Graphics;
 import java.awt.Rectangle;
+import java.util.ArrayList;
 import java.util.Hashtable;
 
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
 import javax.accessibility.AccessibleRole;
 
 /**
  * A container that adds depth to the usual Container semantics.
  * Each child component of a Layered Pane is placed within one
  * of several layers. JLayeredPane defines a set of standard
  * layers. The pre-defined sets are (in the order from button to top):
  *
  *  
  *[EMAIL PROTECTED] #DEFAULT_LAYER}
  *The layer where most of the normal components are placed. This
  *  is the bottommost layer.
  *
  *[EMAIL PROTECTED] #PALETTE_LAYER}
  *Palette windows are placed in this layer.
  *
@@ -309,70 +310,68 @@
   {
 setPosition (c, -1);
   }
 
   /**
* Return the position of a component within its layer. Positions are assigned
* from the "front" (position 0) to the "back" (position N-1), and drawn from 
* the back towards the front.
*
* @param c the component to get the position of
*
* @return the position of c within its layer or -1 if
* c is not a child of this layered pane
*
* @see #setPosition
*/
   public int getPosition(Component c)
   {
 int pos = -1;
 int index = getIndexOf(c);
-Component[] components = getComponents();
-int layer = getLayer(c);
 if (index >= 0)
   {
-for (int i = index; i >= 0; --i)
+pos = 0;
+int layer = getLayer(c);
+for (int i = index - 1; i >= 0; --i)
   {
-if (layer == getLayer(components[i]))
+if (layer == getLayer(getComponent(i)))
   pos++;
 else
   break;
   }
   }
 return pos;
   }
 
   /**
* Change the position of a component within its layer. Positions are assigned
* from the "front" (position 0) to the "back" (position N-1), and drawn from 
* the back towards the front.
*
* @param c the component to change the position of
* @param position the position to assign the component to
*
* @see #getPosition
*/
   public void setPosition(Component c, int position)
   {
-int layer = getLayer(c);
-int index = insertIndexForLayer(layer, position);
-setComponentZOrder(c, index);
+setLayer(c, getLayer(c), position);
   }
 
   /**
* Return an array of all components within a layer of this
* container. Components are ordered front-to-back, with the "front"
* element (which draws last) at position 0 of the returned 

[cp-patches] FYI: JLayeredPane fixes

2006-01-27 Thread Roman Kennke
I have essentially rewritten most of JLayeredPane. I noticed some
troubles with this class and read a little in the OReilly Swing book 1st
edition. I learned that we did a couple of things wrong in this class:

- we stored all components and their layers in the Hashtable. This is
wrong. JComponents should have their layer stored as client property
with LAYER_PROPERTY as key.
- a lot of the methods used to throw IllegalArgumentExceptions for
unusual arguments like components that are not children of the layered
pane. These methods should ignore this instead and return -1 or 0. (This
error actually caused several problems in some applications)

Also, our implementation used a second datastructure called 'layers' to
manage the layers. This is really not needed and makes maintainence of
the code less straightforward. I removed this and rewrote most stuff in
a more straightforward manner.

2006-01-27  Roman Kennke  <[EMAIL PROTECTED]>

* javax/swing/JLayeredPane.java
(FRAME_CONTENT_LAYER): Made field final.
(componentToLayer): Made field private.
(rectCache): Removed field.
(layers): Removed field.
(JLayeredPane()): Removed initialization of removed fields.
(getLayer): Rewritten to make use of client properties in
JComponents and to be more straighforward.
(static getLayer): Rewritten to make use of client properties in
JComponents.
(layerToRange): Removed method.
(incrLayer): Removed method.
(decrLayer): Removed method.
(highestLayer): Rewritten to be more straightforward.
(lowestLayer): Rewritten to be more straightforward.
(getPosition): Rewritten to be more straightforward.
(getComponentsInLayer): Rewritten to be more straightforward.
(getComponentCountInLayer): Rewritten to be more straightforward.
(getIndexOf): Rewritten to be more straightforward.
(inserIndexForLayer): Rewritten to be more straightforward.
(remove): Rewritten to be more straightforward.
(setLayer): Rewritten to be more straightforward.
(addImpl): Rewritten to be more straightforward.
(putLayer): Rewritten to be more straightforward.

/Roman
Index: javax/swing/JLayeredPane.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JLayeredPane.java,v
retrieving revision 1.37
diff -u -r1.37 JLayeredPane.java
--- javax/swing/JLayeredPane.java	27 Jan 2006 15:51:21 -	1.37
+++ javax/swing/JLayeredPane.java	27 Jan 2006 19:56:19 -
@@ -43,11 +43,7 @@
 import java.awt.Container;
 import java.awt.Graphics;
 import java.awt.Rectangle;
-import java.awt.Shape;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
 
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
@@ -119,6 +115,7 @@
  * component indexing and position order
  *
  * @author Graydon Hoare ([EMAIL PROTECTED])
+ * @author Roman Kennke ([EMAIL PROTECTED])
  */
 public class JLayeredPane extends JComponent implements Accessible
 {
@@ -150,7 +147,7 @@
   
   public static final String LAYER_PROPERTY = "layeredContainerLayer";
 
-  public static Integer FRAME_CONTENT_LAYER = new Integer (-3);
+  public static final Integer FRAME_CONTENT_LAYER = new Integer (-3);
 
   public static final Integer DEFAULT_LAYER = new Integer (0);
   public static final Integer PALETTE_LAYER = new Integer (100);
@@ -158,14 +155,10 @@
   public static final Integer POPUP_LAYER   = new Integer (300);
   public static final Integer DRAG_LAYER= new Integer (400);
 
-  TreeMap layers;   // Layer Number (Integer) -> Layer Size (Integer)
-  Hashtable componentToLayer;   // Component -> Layer Number (Integer)
+  private Hashtable componentToLayer;   // Component -> Layer Number (Integer)
 
-  private transient Rectangle rectCache;
-  
   public JLayeredPane()
   {
-layers = new TreeMap ();
 componentToLayer = new Hashtable ();
 setLayout(null);
   }
@@ -173,47 +166,50 @@
   /** 
* Looks up the layer a child component is currently assigned to.
*
+   * If c is an instance of [EMAIL PROTECTED] JComponent}, then the layer
+   * is fetched from the client property with the key [EMAIL PROTECTED] #LAYER_PROPERTY}.
+   * Otherwise it is looked up in an internal hashtable that maps
+   * non-JComponent components to layers. If the components cannot be found
+   * in either way, the [EMAIL PROTECTED] #DEFAULT_LAYER} is returned.
+   *
* @param c the component to look up.
-   * @return the layer the component is currently assigned to, in this container.
-   * @throws IllegalArgumentException if the component is not a child of this container.
+   *
+   * @return the layer the component is currently assigned to; if the component
+   * is not in this layered pane, then 0 (DEFAULT_LAYER) is returned
*/
   public int getLayer(Co

[cp-patches] FYI: JLayeredPane fixes

2006-02-14 Thread Roman Kennke
The attached patch fixes two issues with JLayeredPane. It avoids a
potential memory leak that comes from not overriding removeAll in
JLayeredPane. Calling removeAll() would cause components to be removed
but their layer information to be kept forever in JLayeredPane's
Hashtable.

Also, I improved the isOptimizedDrawingEnabled method so that it
accurately calculates if child components overlap or not. Before, I had
a heuristic there that returns false for #components>2. Now I go through
all the components and compare their rectangles. This is surprisingly
efficient, I had a JLayeredPane here with 9 children and this method
still took 1ms or less. As a reward the painting is done more efficient,
which is well worth the effort.

2006-02-13  Roman Kennke  <[EMAIL PROTECTED]>

* javax/swing/JLayeredPane.java
(removeAll): New method. Avoid potential memory leak.
(isOptimizedDrawingEnabled): Replaced heuristic with accurate
calculation.

/Roman
Index: javax/swing/JLayeredPane.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JLayeredPane.java,v
retrieving revision 1.43
diff -u -r1.43 JLayeredPane.java
--- javax/swing/JLayeredPane.java	4 Feb 2006 11:08:43 -	1.43
+++ javax/swing/JLayeredPane.java	14 Feb 2006 11:12:57 -
@@ -523,6 +523,17 @@
   }
 
   /**
+   * Removes all components from this container.
+   *
+   * @since 1.5
+   */
+  public void removeAll()
+  {
+	componentToLayer.clear();
+	super.removeAll();
+  }
+
+  /**
* Set the layer property for a component, within this container. The
* component will be implicitly mapped to the bottom-most position in the
* layer, but only if added after calling this method.
@@ -646,30 +657,33 @@
   public boolean isOptimizedDrawingEnabled()
   {
 int numChildren = getComponentCount();
-boolean result = false;
-// We implement a heuristic here in order to return a quick result:
-// - For 0 or 1 children it is clear that they do not overlap, return true.
-// - For 2 children we check their bounding rectangles and if they don't
-//   interect, return true.
-// - For more than 2 children we return false. Comparing all the bounding
-//   rectangles costs too much time and in most cases this will return
-//   false anyway, since JLayeredPane are mostly used in JRootPane and then
-//   have at least one child (the contentPane) that takes up the whole
-//   area of the JLayeredPane.
-switch (numChildren)
-{
-  case 0:
-  case 1:
-result = true;
-break;
-  case 2:
-Rectangle r1 = getComponent(0).getBounds();
-Rectangle r2 = getComponent(1).getBounds();
-result = !r1.intersects(r2);
-break;
-  default:
-result = false;
-}
+boolean result = true;
+for (int i = 0; i < numChildren; ++i)
+  {
+	Component c1 = getComponent(i);
+	if (! c1.isVisible())
+  continue;
+	Rectangle r1 = c1.getBounds();
+	if (r1.isEmpty())
+  continue;
+
+	for (int j = i + 1; j < numChildren; ++j)
+  {
+Component c2 = getComponent(j);
+if (! c2.isVisible())
+  continue;
+Rectangle r2 = c2.getBounds();
+if (r2.isEmpty())
+  continue;
+if (r1.intersects(r2))
+  {
+result = false;
+break;
+  }
+if (result == false)
+  break;
+  }
+  }
 return result;
   }
 }


[cp-patches] FYI: JLayeredPane fixes / new Container methods

2006-02-04 Thread Roman Kennke
This fixes a mauve test for JLayeredPane. In order to fix this, I
implemented the set/getComponentZOrder() methods in Container and made
JLayeredPane use these methods. This is not only much more efficient
than adding/removing components when changing the order, it also fixes a
nasty problem when there is a layout manager installed on the
JLayeredPane (which is discouraged but not forbidden).

2006-02-04  Roman Kennke  <[EMAIL PROTECTED]>

* java/awt/Container.java
(getComponentZOrder): New method.
(setComponentZOrder): New method.
* javax/swing/JLayeredPane.java
(setPosition): Reimplemented to use setComponentZOrder().
(getIndexOf): Reimplemented to use getComponentZOrder().
(addImpl): Pass layerContraint to super call. Important for
possibly
installed layout managers.
(swapComponents): Remove unneeded method.

/Roman
Index: java/awt/Container.java
===
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.77
diff -u -r1.77 Container.java
--- java/awt/Container.java	27 Jan 2006 15:51:21 -	1.77
+++ java/awt/Container.java	4 Feb 2006 11:04:18 -
@@ -1565,6 +1565,93 @@
 changeSupport.addPropertyChangeListener (name, listener);
   }
 
+
+  /**
+   * Sets the Z ordering for the component comp to
+   * index. Components with lower Z order paint above components
+   * with higher Z order.
+   *
+   * @param comp the component for which to change the Z ordering
+   * @param index the index to set
+   *
+   * @throws NullPointerException if comp == null
+   * @throws IllegalArgumentException if comp is an ancestor of this container
+   * @throws IllegalArgumentException if index is not in
+   * [0, getComponentCount()] for moving between
+   * containers or [0, getComponentCount() - 1] for moving
+   * inside this container
+   * @throws IllegalArgumentException if comp == this
+   * @throws IllegalArgumentException if comp is a
+   * Window
+   *
+   * @see #getComponentZOrder(Component)
+   *
+   * @since 1.5
+   */
+  public final void setComponentZOrder(Component comp, int index)
+  {
+if (comp == null)
+  throw new NullPointerException("comp must not be null");
+if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
+  throw new IllegalArgumentException("comp must not be an ancestor of "
+ + "this");
+if (comp instanceof Window)
+  throw new IllegalArgumentException("comp must not be a Window");
+
+if (comp == this)
+  throw new IllegalArgumentException("cannot add component to itself");
+
+// FIXME: Implement reparenting.
+if ( comp.getParent() != this)
+  throw new AssertionError("Reparenting is not implemented yet");
+else
+  {
+// Find current component index.
+int currentIndex = getComponentZOrder(comp);
+if (currentIndex < index)
+  {
+System.arraycopy(component, currentIndex + 1, component,
+ currentIndex, index - currentIndex);
+  }
+else
+  {
+System.arraycopy(component, index, component, index + 1,
+ currentIndex - index);
+  }
+component[index] = comp;
+  }
+  }
+
+  /**
+   * Returns the Z ordering index of comp. If comp
+   * is not a child component of this Container, this returns -1.
+   *
+   * @param comp the component for which to query the Z ordering
+   *
+   * @return the Z ordering index of comp or -1 if
+   * comp is not a child of this Container
+   *
+   * @see #setComponentZOrder(Component, int)
+   *
+   * @since 1.5
+   */
+  public final int getComponentZOrder(Component comp)
+  {
+int index = -1;
+if (component != null)
+  {
+for (int i = 0; i < component.length; i++)
+  {
+if (component[i] == comp)
+  {
+index = i;
+break;
+  }
+  }
+  }
+return index;
+  }
+
   // Hidden helper methods.
 
   /**
Index: javax/swing/JLayeredPane.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JLayeredPane.java,v
retrieving revision 1.42
diff -u -r1.42 JLayeredPane.java
--- javax/swing/JLayeredPane.java	1 Feb 2006 12:17:13 -	1.42
+++ javax/swing/JLayeredPane.java	4 Feb 2006 11:04:18 -
@@ -353,16 +353,9 @@
*/
   public void setPosition(Component c, int position)
   {
-int currentPos = getPosition(c);
-if (currentPos == position)
-  return;
-
 int layer = getLayer(c);
-int i1 = position;
-int i2 = getPosition(c);
-int incr = (i1 - i2) / Math.abs(i1 - i2);
-for (int p = i2; p != i1; p += incr)
-  swapComponents(p, p + incr, layer);
+int index = insertIndexForLayer(layer, position);
+set