Hi,

the JAPI pages pointed me to JScrollPane and the BasicScrollPaneUI.
Obviously the implementation has been a little wrong here. There was a lot
of logic implemented in JScrollPane that should have been implemented in
BasicScrollPaneUI. I move the bits over and added some stuff so now the
BasicScrollPaneUI is pretty much complete except for the keyboard and
mouse wheel handling. (Unfortunatly the scrollpane is still not working
100% ok).

2005-09-23  Roman Kennke  <[EMAIL PROTECTED]>
        * javax/swing/JScrollPane.java
        (setHorizontalScrollBar): Removed handling of listeners on the model.
        This is now done in the BasicScrollPaneUI.
        (setHorizontalScrollBarPolicy): Added revalidate call.
        (setVerticalScrollBar): Removed handling of listeners on the model.
        This is now done in the BasicScrollPaneUI.
        (setVerticalScrollBarPolicy): Added revalidate call.
        (setViewport): Removed handling of listeners on the viewport.
        This is now done in the BasicScrollPaneUI.
        (createScrollListener): Removed unnecessary and undocumented method.
        The functionality of this method is moved to BasicScrollPaneUI
        as specified.
        (JScrollPane): Removed initialization of removed listener.
        * javax/swing/plaf/basic/BasicScrollPaneUI.java
        (HSBChangeListener): New inner class.
        (VSBChangeListener): New inner class.
        (ViewportChangeHandler): New inner class.
        (PropertyChangeHandler): New inner class.
        (MouseWheelHandler): New inner class.
        (installUI): Also call installListeners.
        (installListeners): New method. Initializes the listeners on the
        scrollpane.
        (createHSBChangeListener): New method.
        (createVSBChangeListener): New method.
        (createViewport): New method.
        (createPropertyChangeListener): New method.
        (uninstallUI): Also call uninstallListeners.
        (uninstallListeners): New method.
        (syncScrollPaneWithViewport): New method.
        (updateColumnHeader): New method.
        (updateRowHeader): New method.
        (updateScrollBarDisplayPolicy): New method.
        (updateViewport): New method.
/Roman
Index: javax/swing/JScrollPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JScrollPane.java,v
retrieving revision 1.27
diff -u -r1.27 JScrollPane.java
--- javax/swing/JScrollPane.java	12 Sep 2005 20:59:15 -0000	1.27
+++ javax/swing/JScrollPane.java	23 Sep 2005 20:23:59 -0000
@@ -40,16 +40,12 @@
 
 import java.awt.Component;
 import java.awt.ComponentOrientation;
-import java.awt.Dimension;
 import java.awt.Insets;
 import java.awt.LayoutManager;
-import java.awt.Point;
 import java.awt.Rectangle;
 
 import javax.accessibility.Accessible;
 import javax.swing.border.Border;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 import javax.swing.plaf.ScrollPaneUI;
 import javax.swing.plaf.UIResource;
 
@@ -100,7 +96,6 @@
   
   Border viewportBorder;
   boolean wheelScrollingEnabled;
-  ChangeListener scrollListener;  
 
   public JViewport getColumnHeader()
   {
@@ -331,18 +326,6 @@
     firePropertyChange("horizontalScrollBar", old, h);
     sync();
 
-    if (old != null)
-      {
-        BoundedRangeModel model = old.getModel();
-        if (model != null)
-          model.removeChangeListener(scrollListener);
-      }
-    if (h != null)
-      {
-        BoundedRangeModel model = h.getModel();
-        if (model != null)
-          model.addChangeListener(scrollListener);
-      }
   }
 
   public void setHorizontalScrollBarPolicy(int h)
@@ -359,6 +342,7 @@
     horizontalScrollBarPolicy = h;
     firePropertyChange("horizontalScrollBarPolicy", old, h);
     sync();
+    revalidate();
   }
 
   public void setLayout(LayoutManager l)
@@ -403,19 +387,6 @@
     addNonNull(v, JScrollPane.VERTICAL_SCROLLBAR);
     firePropertyChange("verticalScrollBar", old, v);
     sync();
-
-    if (old != null)
-      {
-        BoundedRangeModel model = old.getModel();
-        if (model != null)
-          model.removeChangeListener(scrollListener);
-      }
-    if (v != null)
-      {
-        BoundedRangeModel model = v.getModel();
-        if (model != null)
-          model.addChangeListener(scrollListener);
-      }
   }
 
   public void setVerticalScrollBarPolicy(int v)
@@ -432,6 +403,7 @@
     verticalScrollBarPolicy = v;
     firePropertyChange("verticalScrollBarPolicy", old, v);
     sync();
+    revalidate();
   }
 
   public void setWheelScrollingEnabled(boolean b)
@@ -452,11 +424,7 @@
     
     JViewport old = viewport;
     removeNonNull(old);
-    if (old != null)
-      old.removeChangeListener(scrollListener);
     viewport = v;
-    if (v != null)
-      v.addChangeListener(scrollListener);
     addNonNull(v, JScrollPane.VIEWPORT);
     revalidate();
     repaint();
@@ -494,79 +462,6 @@
     return true;
   }
 
-  ChangeListener createScrollListener()
-  {
-    return new ChangeListener() 
-      {
-        
-        public void stateChanged(ChangeEvent event)
-        {
-          JScrollBar vsb = JScrollPane.this.getVerticalScrollBar();
-          JScrollBar hsb = JScrollPane.this.getHorizontalScrollBar();
-          JViewport vp = JScrollPane.this.getViewport();
-
-          if (vp != null && event.getSource() == vp)
-            {
-              // if the viewport changed, we should update the VSB / HSB
-              // models according to the new vertical and horizontal sizes
-
-              Rectangle vr = vp.getViewRect();
-              Dimension vs = vp.getViewSize();
-              if (vsb != null
-                  && (vsb.getMinimum() != 0
-                      || vsb.getMaximum() != vs.height
-                      || vsb.getValue() != vr.y
-                      || vsb.getVisibleAmount() != vr.height))
-                vsb.setValues(vr.y, vr.height, 0, vs.height);
-
-              if (hsb != null
-                  && (hsb.getMinimum() != 0
-                      || hsb.getMaximum() != vs.width
-                      || hsb.getValue() != vr.width
-                      || hsb.getVisibleAmount() != vr.height))
-                hsb.setValues(vr.x, vr.width, 0, vs.width);
-            }
-          else
-            {
-              // otherwise we got a change update from either the VSB or
-              // HSB model, and we need to update the viewport positions of
-              // both the main viewport and any row or column headers to
-              // match.
-
-              int xpos = 0;
-              int ypos = 0;
-              
-              if (vsb != null)
-                ypos = vsb.getValue();
-              
-              if (hsb != null)
-                xpos = hsb.getValue();
-
-              Point pt = new Point(xpos, ypos);
-
-              if (vp != null
-                  && vp.getViewPosition() != pt)
-                vp.setViewPosition(pt);
-
-              pt.x = 0;
-
-              if (rowHeader != null 
-                  && rowHeader.getViewPosition() != pt)
-                rowHeader.setViewPosition(pt);
-              
-              pt.x = xpos;
-              pt.y = 0;
-
-              if (columnHeader != null 
-                  && columnHeader.getViewPosition() != pt)
-                columnHeader.setViewPosition(pt);
-
-            }
-        }
-      };
-  }
-
-
   /**
    * Creates a new <code>JScrollPane</code> without a view. The scrollbar
    * policy is set to [EMAIL PROTECTED] #VERTICAL_SCROLLBAR_AS_NEEDED} and
@@ -627,7 +522,6 @@
    */
   public JScrollPane(Component view, int vsbPolicy, int hsbPolicy) 
   {
-    scrollListener = createScrollListener();
     setVerticalScrollBarPolicy(vsbPolicy);
     setVerticalScrollBar(createVerticalScrollBar());
     setHorizontalScrollBarPolicy(hsbPolicy);
@@ -635,7 +529,6 @@
     viewport = createViewport();
     if (view != null)
       getViewport().setView(view);
-    viewport.addChangeListener(scrollListener);
     add(viewport,0);
     setLayout(new ScrollPaneLayout());
     setOpaque(false);
Index: javax/swing/plaf/basic/BasicScrollPaneUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java,v
retrieving revision 1.12
diff -u -r1.12 BasicScrollPaneUI.java
--- javax/swing/plaf/basic/BasicScrollPaneUI.java	26 Jul 2005 14:16:43 -0000	1.12
+++ javax/swing/plaf/basic/BasicScrollPaneUI.java	23 Sep 2005 20:23:59 -0000
@@ -40,13 +40,22 @@
 
 import java.awt.Dimension;
 import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 
 import javax.swing.JComponent;
+import javax.swing.JScrollBar;
 import javax.swing.JScrollPane;
+import javax.swing.JViewport;
 import javax.swing.ScrollPaneConstants;
 import javax.swing.ScrollPaneLayout;
 import javax.swing.UIDefaults;
 import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.ScrollPaneUI;
 
@@ -54,9 +63,195 @@
   implements ScrollPaneConstants
 {
 
+  /**
+   * Listens for changes in the state of the horizontal scrollbar's model and
+   * updates the scrollpane accordingly.
+   *
+   * @author Roman Kennke ([EMAIL PROTECTED])
+   */
+  public class HSBChangeListener implements ChangeListener
+  {
+
+    /**
+     * Receives notification when the state of the horizontal scrollbar
+     * model has changed.
+     *
+     * @param event the change event
+     */
+    public void stateChanged(ChangeEvent event)
+    {
+      JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+      JViewport vp = scrollpane.getViewport();
+      Point viewPosition = vp.getViewPosition();
+      int xpos = hsb.getValue();
+
+      if (xpos != viewPosition.x)
+        {
+          viewPosition.x = xpos;
+          vp.setViewPosition(viewPosition);
+        }
+
+      viewPosition.y = 0;
+      JViewport columnHeader = scrollpane.getColumnHeader();
+      if (columnHeader != null 
+          && !columnHeader.getViewPosition().equals(viewPosition))
+        columnHeader.setViewPosition(viewPosition);
+    }
+
+  }
+
+  /**
+   * Listens for changes in the state of the vertical scrollbar's model and
+   * updates the scrollpane accordingly.
+   *
+   * @author Roman Kennke ([EMAIL PROTECTED])
+   */
+  public class VSBChangeListener implements ChangeListener
+  {
+
+    /**
+     * Receives notification when the state of the vertical scrollbar
+     * model has changed.
+     *
+     * @param event the change event
+     */
+    public void stateChanged(ChangeEvent event)
+    {
+      JScrollBar vsb = scrollpane.getVerticalScrollBar();
+      JViewport vp = scrollpane.getViewport();
+      Point viewPosition = vp.getViewPosition();
+      int ypos = vsb.getValue();
+
+      if (ypos != viewPosition.x)
+        {
+          viewPosition.y = ypos;
+          vp.setViewPosition(viewPosition);
+        }
+
+      viewPosition.x = 0;
+      JViewport rowHeader = scrollpane.getRowHeader();
+      if (rowHeader != null 
+          && !rowHeader.getViewPosition().equals(viewPosition))
+        rowHeader.setViewPosition(viewPosition);
+    }
+ 
+  }
+
+  /**
+   * Listens for changes of the viewport's extent size and updates the
+   * scrollpane accordingly.
+   *
+   * @author Roman Kennke ([EMAIL PROTECTED])
+   */
+  public class ViewportChangeHandler implements ChangeListener
+  {
+
+    /**
+     * Receives notification when the view's size, position or extent size
+     * changes. When the extents size has changed, this method calls
+     * [EMAIL PROTECTED] BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the
+     * scrollbars extents as well.
+     * 
+     * @param event the change event
+     */
+    public void stateChanged(ChangeEvent event)
+    {
+      JViewport vp = scrollpane.getViewport();
+      JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+      JScrollBar vsb = scrollpane.getVerticalScrollBar();
+      Dimension extents = vp.getExtentSize();
+      if (extents.width != hsb.getModel().getExtent()
+          || extents.height != vsb.getModel().getExtent())
+        syncScrollPaneWithViewport();
+    }
+
+  }
+
+  /**
+   * Listens for property changes on the scrollpane and update the view
+   * accordingly.
+   *
+   * @author Roman Kennke ([EMAIL PROTECTED])
+   */
+  public class PropertyChangeHandler implements PropertyChangeListener
+  {
+
+    /**
+     * Receives notification when any of the scrollpane's bound property
+     * changes. This method calls the appropriate update method on the
+     * <code>ScrollBarUI</code>.
+     *
+     * @param e the property change event
+     *
+     * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent)
+     * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent)
+     * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent)
+     * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent)
+     */
+    public void propertyChange(PropertyChangeEvent e)
+    {
+      if (e.getPropertyName().equals("viewport"))
+        updateViewport(e);
+      else if (e.getPropertyName().equals("rowHeader"))
+        updateRowHeader(e);
+      else if (e.getPropertyName().equals("columnHeader"))
+        updateColumnHeader(e);
+      else if (e.getPropertyName().equals("horizontalScrollBarPolicy")
+          || e.getPropertyName().equals("verticalScrollBarPolicy"))
+        updateScrollBarDisplayPolicy(e);
+    }
+
+  }
+
+  /**
+   * Listens for mouse wheel events and update the scrollpane accordingly.
+   *
+   * @author Roman Kennke ([EMAIL PROTECTED])
+   *
+   * @since 1.4
+   */
+  protected class MouseWheelHandler implements MouseWheelListener
+  {
+
+    /**
+     * Receives notification whenever the mouse wheel is moved.
+     *
+     * @param event the mouse wheel event
+     */
+    public void mouseWheelMoved(MouseWheelEvent event)
+    {
+    }
+
+  }
+
   /** The Scrollpane for which the UI is provided by this class. */
   protected JScrollPane scrollpane;
 
+  /**
+   * The horizontal scrollbar listener.
+   */
+  protected ChangeListener hsbChangeListener;
+
+  /**
+   * The vertical scrollbar listener.
+   */
+  protected ChangeListener vsbChangeListener;
+
+  /**
+   * The viewport listener.
+   */
+  protected ChangeListener viewportChangeListener;
+
+  /**
+   * The scrollpane property change listener.
+   */
+  protected PropertyChangeListener spPropertyChangeListener;
+
+  /**
+   * The mousewheel listener for the scrollpane.
+   */
+  MouseWheelListener mouseWheelListener;
+
   public static ComponentUI createUI(final JComponent c) 
   {
     return new BasicScrollPaneUI();
@@ -85,16 +280,103 @@
   public void installUI(final JComponent c) 
   {
     super.installUI(c);
-    this.installDefaults((JScrollPane)c);
+    installDefaults((JScrollPane) c);
+    installListeners((JScrollPane) c);
+  }
+
+  /**
+   * Installs the listeners on the scrollbars, the viewport and the scrollpane.
+   *
+   * @param sp the scrollpane on which to install the listeners
+   */
+  protected void installListeners(JScrollPane sp)
+  {
+    if (spPropertyChangeListener == null)
+      spPropertyChangeListener = createPropertyChangeListener();
+    sp.addPropertyChangeListener(spPropertyChangeListener);
+
+    if (hsbChangeListener == null)
+      hsbChangeListener = createHSBChangeListener();
+    sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener);
+    
+    if (vsbChangeListener == null)
+      vsbChangeListener = createVSBChangeListener();
+    sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener);
+
+    if (viewportChangeListener == null)
+      viewportChangeListener = createViewportChangeListener();
+    sp.getViewport().addChangeListener(viewportChangeListener);
+
+    if (mouseWheelListener == null)
+      mouseWheelListener = new MouseWheelHandler();
+    sp.addMouseWheelListener(mouseWheelListener);
+  }
+
+  /**
+   * Creates and returns the change listener for the horizontal scrollbar.
+   *
+   * @return the change listener for the horizontal scrollbar
+   */
+  protected ChangeListener createHSBChangeListener()
+  {
+    return new HSBChangeListener();
+  }
+
+  /**
+   * Creates and returns the change listener for the vertical scrollbar.
+   *
+   * @return the change listener for the vertical scrollbar
+   */
+  protected ChangeListener createVSBChangeListener()
+  {
+    return new VSBChangeListener();
+  }
+
+  /**
+   * Creates and returns the change listener for the viewport.
+   *
+   * @return the change listener for the viewport
+   */
+  protected ChangeListener createViewportChangeListener()
+  {
+    return new ViewportChangeHandler();
+  }
+
+  /**
+   * Creates and returns the property change listener for the scrollpane.
+   *
+   * @return the property change listener for the scrollpane
+   */
+  protected PropertyChangeListener createPropertyChangeListener()
+  {
+    return new PropertyChangeHandler();
   }
 
   public void uninstallUI(final JComponent c) 
   {
     super.uninstallUI(c);
     this.uninstallDefaults((JScrollPane)c);
+    uninstallListeners((JScrollPane) c);
+  }
+
+  /**
+   * Uninstalls all the listeners that have been installed in
+   * [EMAIL PROTECTED] #installListeners(JScrollPane)}.
+   *
+   * @param c the scrollpane from which to uninstall the listeners 
+   */
+  protected void uninstallListeners(JComponent c)
+  {
+    JScrollPane sp = (JScrollPane) c;
+    sp.removePropertyChangeListener(spPropertyChangeListener);
+    sp.getHorizontalScrollBar().getModel()
+                               .removeChangeListener(hsbChangeListener);
+    sp.getVerticalScrollBar().getModel()
+                             .removeChangeListener(vsbChangeListener);
+    sp.getViewport().removeChangeListener(viewportChangeListener);
+    sp.removeMouseWheelListener(mouseWheelListener);
   }
 
-    
   public Dimension getMinimumSize(JComponent c) 
   {
     JScrollPane p = (JScrollPane ) c;
@@ -106,6 +388,68 @@
   {      
     // do nothing; the normal painting-of-children algorithm, along with
     // ScrollPaneLayout, does all the relevant work.
+  }
+
+  /**
+   * Synchronizes the scrollbars with the viewport's extents.
+   */
+  protected void syncScrollPaneWithViewport()
+  {
+    JViewport vp = scrollpane.getViewport();
+    JScrollBar vsb = scrollpane.getVerticalScrollBar();
+    JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+    hsb.getModel().setExtent(vp.getExtentSize().width);
+    vsb.getModel().setExtent(vp.getExtentSize().height);
+  }
+
+  /**
+   * Receives notification when the <code>columnHeader</code> property has
+   * changed on the scrollpane.
+   *
+   * @param ev the property change event
+   */
+  protected void updateColumnHeader(PropertyChangeEvent ev)
+  {
+    // TODO: Find out what should be done here. Or is this only a hook?
+  }
+
+  /**
+   * Receives notification when the <code>rowHeader</code> property has changed
+   * on the scrollpane.
+   *
+   * @param ev the property change event
+   */
+  protected void updateRowHeader(PropertyChangeEvent ev)
+  {
+    // TODO: Find out what should be done here. Or is this only a hook?
+  }
+
+  /**
+   * Receives notification when the <code>scrollBarDisplayPolicy</code>
+   * property has changed on the scrollpane.
+   *
+   * @param ev the property change event
+   */
+  protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev)
+  {
+    // TODO: Find out what should be done here. Or is this only a hook?
+  }
+
+  /**
+   * Receives notification when the <code>viewport</code> property has changed
+   * on the scrollpane.
+   *
+   * This method sets removes the viewportChangeListener from the old viewport
+   * and adds it to the new viewport.
+   *
+   * @param ev the property change event
+   */
+  protected void updateViewport(PropertyChangeEvent ev)
+  {
+    JViewport oldViewport = (JViewport) ev.getOldValue();
+    oldViewport.removeChangeListener(viewportChangeListener);
+    JViewport newViewport = (JViewport) ev.getNewValue();
+    oldViewport.addChangeListener(viewportChangeListener);
   }
 }
 
_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to