OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / plaf / basic / BasicScrollPaneUI.java
1 /* BasicScrollPaneUI.java
2    Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing.plaf.basic;
40
41 import java.awt.Dimension;
42 import java.awt.Graphics;
43 import java.awt.Point;
44 import java.awt.Rectangle;
45 import java.awt.event.ActionEvent;
46 import java.awt.event.ContainerEvent;
47 import java.awt.event.ContainerListener;
48 import java.awt.event.MouseWheelEvent;
49 import java.awt.event.MouseWheelListener;
50 import java.beans.PropertyChangeEvent;
51 import java.beans.PropertyChangeListener;
52
53 import javax.swing.AbstractAction;
54 import javax.swing.ActionMap;
55 import javax.swing.InputMap;
56 import javax.swing.JComponent;
57 import javax.swing.JScrollBar;
58 import javax.swing.JScrollPane;
59 import javax.swing.JSlider;
60 import javax.swing.JViewport;
61 import javax.swing.LookAndFeel;
62 import javax.swing.ScrollPaneConstants;
63 import javax.swing.ScrollPaneLayout;
64 import javax.swing.SwingUtilities;
65 import javax.swing.UIManager;
66 import javax.swing.border.Border;
67 import javax.swing.event.ChangeEvent;
68 import javax.swing.event.ChangeListener;
69 import javax.swing.plaf.ActionMapUIResource;
70 import javax.swing.plaf.ComponentUI;
71 import javax.swing.plaf.ScrollPaneUI;
72 import javax.swing.plaf.UIResource;
73
74 /**
75  * A UI delegate for the {@link JScrollPane} component.
76  */
77 public class BasicScrollPaneUI extends ScrollPaneUI
78   implements ScrollPaneConstants
79 {
80
81   /**
82    * Listens for changes in the state of the horizontal scrollbar's model and
83    * updates the scrollpane accordingly.
84    *
85    * @author Roman Kennke (kennke@aicas.com)
86    */
87   public class HSBChangeListener implements ChangeListener
88   {
89
90     /**
91      * Receives notification when the state of the horizontal scrollbar
92      * model has changed.
93      *
94      * @param event the change event
95      */
96     public void stateChanged(ChangeEvent event)
97     {
98       JScrollBar hsb = scrollpane.getHorizontalScrollBar();
99       JViewport vp = scrollpane.getViewport();
100       Point viewPosition = vp.getViewPosition();
101       viewPosition.x = hsb.getValue();
102       vp.setViewPosition(viewPosition);
103     }
104
105   }
106
107   /**
108    * Listens for changes in the state of the vertical scrollbar's model and
109    * updates the scrollpane accordingly.
110    *
111    * @author Roman Kennke (kennke@aicas.com)
112    */
113   public class VSBChangeListener implements ChangeListener
114   {
115
116     /**
117      * Receives notification when the state of the vertical scrollbar
118      * model has changed.
119      *
120      * @param event the change event
121      */
122     public void stateChanged(ChangeEvent event)
123     {
124       JScrollBar vsb = scrollpane.getVerticalScrollBar();
125       JViewport vp = scrollpane.getViewport();
126       Point viewPosition = vp.getViewPosition();
127       viewPosition.y = vsb.getValue();
128       vp.setViewPosition(viewPosition);
129     }
130  
131   }
132
133   /**
134    * Listens for changes of the viewport's extent size and updates the
135    * scrollpane accordingly.
136    *
137    * @author Roman Kennke (kennke@aicas.com)
138    */
139   public class ViewportChangeHandler implements ChangeListener
140   {
141
142     /**
143      * Receives notification when the view's size, position or extent size
144      * changes. When the extents size has changed, this method calls
145      * {@link BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the
146      * scrollbars extents as well.
147      * 
148      * @param event the change event
149      */
150     public void stateChanged(ChangeEvent event)
151     {
152       syncScrollPaneWithViewport();
153     }
154
155   }
156
157   /**
158    * Listens for property changes on the scrollpane and update the view
159    * accordingly.
160    *
161    * @author Roman Kennke (kennke@aicas.com)
162    */
163   public class PropertyChangeHandler implements PropertyChangeListener
164   {
165
166     /**
167      * Receives notification when any of the scrollpane's bound property
168      * changes. This method calls the appropriate update method on the
169      * <code>ScrollBarUI</code>.
170      *
171      * @param e the property change event
172      *
173      * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent)
174      * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent)
175      * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent)
176      * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent)
177      */
178     public void propertyChange(PropertyChangeEvent e)
179     {
180       String propName = e.getPropertyName();
181       if (propName.equals("viewport"))
182         updateViewport(e);
183       else if (propName.equals("rowHeader"))
184         updateRowHeader(e);
185       else if (propName.equals("columnHeader"))
186         updateColumnHeader(e);
187       else if (propName.equals("horizontalScrollBarPolicy")
188           || e.getPropertyName().equals("verticalScrollBarPolicy"))
189         updateScrollBarDisplayPolicy(e);
190       else if (propName.equals("verticalScrollBar"))
191         {
192           JScrollBar oldSb = (JScrollBar) e.getOldValue();
193           oldSb.getModel().removeChangeListener(vsbChangeListener);
194           JScrollBar newSb = (JScrollBar) e.getNewValue();
195           newSb.getModel().addChangeListener(vsbChangeListener);
196         }
197       else if (propName.equals("horizontalScrollBar"))
198         {
199           JScrollBar oldSb = (JScrollBar) e.getOldValue();
200           oldSb.getModel().removeChangeListener(hsbChangeListener);
201           JScrollBar newSb = (JScrollBar) e.getNewValue();
202           newSb.getModel().addChangeListener(hsbChangeListener);
203         }
204     }
205
206   }
207
208   /**
209    * Listens for mouse wheel events and update the scrollpane accordingly.
210    *
211    * @author Roman Kennke (kennke@aicas.com)
212    *
213    * @since 1.4
214    */
215   protected class MouseWheelHandler implements MouseWheelListener
216   {
217     /**
218      * Use to compute the visible rectangle.
219      */
220     final Rectangle rect = new Rectangle();
221
222     /**
223      * Scroll with the mouse wheel.
224      * 
225      * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
226      */
227     public void mouseWheelMoved(MouseWheelEvent e)
228     {
229       if (scrollpane.isWheelScrollingEnabled() && e.getScrollAmount() != 0)
230         {
231           // Try to scroll vertically first.
232           JScrollBar scrollBar = scrollpane.getVerticalScrollBar();
233           if (scrollBar == null || ! scrollBar.isVisible())
234             scrollBar = scrollpane.getHorizontalScrollBar();
235           if (scrollBar != null && scrollBar.isVisible())
236             {
237               int direction = e.getWheelRotation() < 0 ? -1 : 1;
238               int scrollType = e.getScrollType();
239               if (scrollType == MouseWheelEvent.WHEEL_UNIT_SCROLL)
240                 BasicScrollBarUI.scrollByUnits(scrollBar, direction,
241                                                e.getScrollAmount());
242               else if (scrollType == MouseWheelEvent.WHEEL_BLOCK_SCROLL)
243                 BasicScrollBarUI.scrollByBlock(scrollBar, direction);
244             }
245         }
246     }
247   }
248   
249   /**
250    * Adds/removes the mouse wheel listener when the component is added/removed
251    * to/from the scroll pane view port.
252    * 
253    * @author Audrius Meskauskas (audriusa@bioinformatics.org)
254    */
255   class ViewportContainerListener implements ContainerListener
256   {
257     /**
258      * Add the mouse wheel listener, allowing to scroll with the mouse.
259      */
260     public void componentAdded(ContainerEvent e)
261     {
262       e.getChild().addMouseWheelListener(mouseWheelListener);
263     }
264     
265     /**
266      * Remove the mouse wheel listener.
267      */
268     public void componentRemoved(ContainerEvent e)
269     {
270       e.getChild().removeMouseWheelListener(mouseWheelListener);
271     }
272   }
273   
274   /**
275    * The number of pixels by that we should scroll the content that does
276    * not implement Scrollable.
277    */
278   static int SCROLL_NON_SCROLLABLES = 10;
279   
280   /**
281    * The number of rows to scroll per mouse wheel click. From impression,
282    * Sun seems using the value 3.
283    */
284   static int ROWS_PER_WHEEL_CLICK = 3;     
285
286   /** The Scrollpane for which the UI is provided by this class. */
287   protected JScrollPane scrollpane;
288
289   /**
290    * The horizontal scrollbar listener.
291    */
292   protected ChangeListener hsbChangeListener;
293
294   /**
295    * The vertical scrollbar listener.
296    */
297   protected ChangeListener vsbChangeListener;
298
299   /**
300    * The viewport listener.
301    */
302   protected ChangeListener viewportChangeListener;
303
304   /**
305    * The scrollpane property change listener.
306    */
307   protected PropertyChangeListener spPropertyChangeListener;
308
309   /**
310    * The mousewheel listener for the scrollpane.
311    */
312   MouseWheelListener mouseWheelListener;
313   
314   /**
315    * The listener to add and remove the mouse wheel listener to/from
316    * the component container.
317    */
318   ContainerListener containerListener;
319
320   public static ComponentUI createUI(final JComponent c) 
321   {
322     return new BasicScrollPaneUI();
323   }
324
325   protected void installDefaults(JScrollPane p)
326   {
327     scrollpane = p;
328     LookAndFeel.installColorsAndFont(p, "ScrollPane.background",
329                                      "ScrollPane.foreground",
330                                      "ScrollPane.font");
331     LookAndFeel.installBorder(p, "ScrollPane.border");
332
333     // Install Viewport border.
334     Border vpBorder = p.getViewportBorder();
335     if (vpBorder == null || vpBorder instanceof UIResource)
336       {
337         vpBorder = UIManager.getBorder("ScrollPane.viewportBorder");
338         p.setViewportBorder(vpBorder);
339       }
340
341     p.setOpaque(true);
342   }
343
344   protected void uninstallDefaults(JScrollPane p)
345   {
346     LookAndFeel.uninstallBorder(p);
347     Border vpBorder = p.getViewportBorder();
348     if (vpBorder != null && vpBorder instanceof UIResource)
349       p.setViewportBorder(null);
350   }
351     
352   public void installUI(final JComponent c) 
353   {
354     super.installUI(c);
355     installDefaults((JScrollPane) c);
356     installListeners((JScrollPane) c);
357     installKeyboardActions((JScrollPane) c);
358   }
359
360   /**
361    * Installs the listeners on the scrollbars, the viewport and the scrollpane.
362    *
363    * @param sp the scrollpane on which to install the listeners
364    */
365   protected void installListeners(JScrollPane sp)
366   {
367     if (spPropertyChangeListener == null)
368       spPropertyChangeListener = createPropertyChangeListener();
369     sp.addPropertyChangeListener(spPropertyChangeListener);
370
371     if (hsbChangeListener == null)
372       hsbChangeListener = createHSBChangeListener();
373     sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener);
374     
375     if (vsbChangeListener == null)
376       vsbChangeListener = createVSBChangeListener();
377     sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener);
378
379     if (viewportChangeListener == null)
380       viewportChangeListener = createViewportChangeListener();
381     
382     if (mouseWheelListener == null)
383       mouseWheelListener = createMouseWheelListener();
384     
385     if (containerListener == null)
386       containerListener = new ViewportContainerListener();
387     
388     JViewport v = sp.getViewport();
389     v.addChangeListener(viewportChangeListener);
390     v.addContainerListener(containerListener);
391     
392     // Add mouse wheel listeners to the componets that are probably already
393     // in the view port.
394     for (int i = 0; i < v.getComponentCount(); i++)
395       v.getComponent(i).addMouseWheelListener(mouseWheelListener);
396   }
397
398   InputMap getInputMap(int condition) 
399   {
400     if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
401       return (InputMap) UIManager.get("ScrollPane.ancestorInputMap");
402     return null;
403   }
404
405   /**
406    * Returns the action map for the {@link JScrollPane}.  All scroll panes 
407    * share a single action map which is created the first time this method is 
408    * called, then stored in the UIDefaults table for subsequent access.
409    * 
410    * @return The shared action map.
411    */
412   ActionMap getActionMap() 
413   {
414     ActionMap map = (ActionMap) UIManager.get("ScrollPane.actionMap");
415
416     if (map == null) // first time here
417       {
418         map = createActionMap();
419         if (map != null)
420           UIManager.put("ScrollPane.actionMap", map);
421       }
422     return map;
423   }
424
425   /**
426    * Creates the action map shared by all {@link JSlider} instances.
427    * This method is called once by {@link #getActionMap()} when it 
428    * finds no action map in the UIDefaults table...after the map is 
429    * created, it gets added to the defaults table so that subsequent 
430    * calls to {@link #getActionMap()} will return the same shared 
431    * instance.
432    * 
433    * @return The action map.
434    */
435   ActionMap createActionMap()
436   {
437     ActionMap map = new ActionMapUIResource();
438     map.put("scrollLeft", 
439             new AbstractAction("scrollLeft") {
440               public void actionPerformed(ActionEvent event)
441               {
442                 JScrollPane sp = (JScrollPane) event.getSource();
443                 JScrollBar sb = sp.getHorizontalScrollBar();
444                 if (sb.isVisible()) 
445                   {
446                     int delta = sb.getBlockIncrement(-1);
447                     sb.setValue(sb.getValue() + delta);
448                   }
449               }
450             }
451     );
452     map.put("scrollEnd", 
453             new AbstractAction("scrollEnd") {
454               public void actionPerformed(ActionEvent event)
455               {
456                 JScrollPane sp = (JScrollPane) event.getSource();
457                 JScrollBar sb1 = sp.getHorizontalScrollBar();
458                 if (sb1.isVisible()) 
459                   {
460                     sb1.setValue(sb1.getMaximum());
461                   }
462                 JScrollBar sb2 = sp.getVerticalScrollBar();
463                 if (sb2.isVisible()) 
464                   {
465                     sb2.setValue(sb2.getMaximum());
466                   }
467               }
468             }
469     );
470     map.put("unitScrollUp", 
471             new AbstractAction("unitScrollUp") {
472               public void actionPerformed(ActionEvent event)
473               {
474                 JScrollPane sp = (JScrollPane) event.getSource();
475                 JScrollBar sb = sp.getVerticalScrollBar();
476                 if (sb.isVisible()) 
477                   {
478                     int delta = sb.getUnitIncrement(-1);
479                     sb.setValue(sb.getValue() + delta);
480                   }
481               }
482             }
483     );
484     map.put("unitScrollLeft", 
485             new AbstractAction("unitScrollLeft") {
486               public void actionPerformed(ActionEvent event)
487               {
488                 JScrollPane sp = (JScrollPane) event.getSource();
489                 JScrollBar sb = sp.getHorizontalScrollBar();
490                 if (sb.isVisible()) 
491                   {
492                     int delta = sb.getUnitIncrement(-1);
493                     sb.setValue(sb.getValue() + delta);
494                   }
495               }
496             }
497     );
498     map.put("scrollUp", 
499             new AbstractAction("scrollUp") {
500               public void actionPerformed(ActionEvent event)
501               {
502                 JScrollPane sp = (JScrollPane) event.getSource();
503                 JScrollBar sb = sp.getVerticalScrollBar();
504                 if (sb.isVisible()) 
505                   {
506                     int delta = sb.getBlockIncrement(-1);
507                     sb.setValue(sb.getValue() + delta);
508                   }
509               }
510             }
511     );
512     map.put("scrollRight", 
513             new AbstractAction("scrollRight") {
514               public void actionPerformed(ActionEvent event)
515               {
516                 JScrollPane sp = (JScrollPane) event.getSource();
517                 JScrollBar sb = sp.getHorizontalScrollBar();
518                 if (sb.isVisible()) 
519                   {
520                     int delta = sb.getBlockIncrement(1);
521                     sb.setValue(sb.getValue() + delta);
522                   }
523               }
524             }
525     );
526     map.put("scrollHome", 
527             new AbstractAction("scrollHome") {
528               public void actionPerformed(ActionEvent event)
529               {
530                 JScrollPane sp = (JScrollPane) event.getSource();
531                 JScrollBar sb1 = sp.getHorizontalScrollBar();
532                 if (sb1.isVisible()) 
533                   {
534                     sb1.setValue(sb1.getMinimum());
535                   }
536                 JScrollBar sb2 = sp.getVerticalScrollBar();
537                 if (sb2.isVisible()) 
538                   {
539                     sb2.setValue(sb2.getMinimum());
540                   }
541               }
542             }
543     );
544     map.put("scrollDown", 
545             new AbstractAction("scrollDown") {
546               public void actionPerformed(ActionEvent event)
547               {
548                 JScrollPane sp = (JScrollPane) event.getSource();
549                 JScrollBar sb = sp.getVerticalScrollBar();
550                 if (sb.isVisible()) 
551                   {
552                     int delta = sb.getBlockIncrement(1);
553                     sb.setValue(sb.getValue() + delta);
554                   }
555               }
556             }
557     );
558     map.put("unitScrollDown", 
559             new AbstractAction("unitScrollDown") {
560               public void actionPerformed(ActionEvent event)
561               {
562                 JScrollPane sp = (JScrollPane) event.getSource();
563                 JScrollBar sb = sp.getVerticalScrollBar();
564                 if (sb.isVisible()) 
565                   {
566                     int delta = sb.getUnitIncrement(1);
567                     sb.setValue(sb.getValue() + delta);
568                   }
569               }
570             }
571     );
572     map.put("unitScrollRight", 
573             new AbstractAction("unitScrollRight") {
574               public void actionPerformed(ActionEvent event)
575               {
576                 JScrollPane sp = (JScrollPane) event.getSource();
577                 JScrollBar sb = sp.getHorizontalScrollBar();
578                 if (sb.isVisible()) 
579                   {
580                     int delta = sb.getUnitIncrement(1);
581                     sb.setValue(sb.getValue() + delta);
582                   }
583               }
584             }
585     );
586     return map;
587   }
588   
589   /**
590    * Installs additional keyboard actions on the scrollpane. This is a hook
591    * method provided to subclasses in order to install their own keyboard
592    * actions.
593    *
594    * @param sp the scrollpane to install keyboard actions on
595    */
596   protected void installKeyboardActions(JScrollPane sp)
597   {
598     InputMap keyMap = getInputMap(
599         JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
600     SwingUtilities.replaceUIInputMap(sp, 
601         JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keyMap);
602     ActionMap map = getActionMap();
603     SwingUtilities.replaceUIActionMap(sp, map);
604   }
605
606   /**
607    * Uninstalls all keyboard actions from the JScrollPane that have been
608    * installed by {@link #installKeyboardActions}. This is a hook method
609    * provided to subclasses to add their own keyboard actions.
610    *
611    * @param sp the scrollpane to uninstall keyboard actions from
612    */
613   protected void uninstallKeyboardActions(JScrollPane sp)
614   {
615     SwingUtilities.replaceUIActionMap(sp, null);
616     SwingUtilities.replaceUIInputMap(sp, 
617         JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
618   }
619   
620   /**
621    * Creates and returns the change listener for the horizontal scrollbar.
622    *
623    * @return the change listener for the horizontal scrollbar
624    */
625   protected ChangeListener createHSBChangeListener()
626   {
627     return new HSBChangeListener();
628   }
629
630   /**
631    * Creates and returns the change listener for the vertical scrollbar.
632    *
633    * @return the change listener for the vertical scrollbar
634    */
635   protected ChangeListener createVSBChangeListener()
636   {
637     return new VSBChangeListener();
638   }
639
640   /**
641    * Creates and returns the change listener for the viewport.
642    *
643    * @return the change listener for the viewport
644    */
645   protected ChangeListener createViewportChangeListener()
646   {
647     return new ViewportChangeHandler();
648   }
649
650   /**
651    * Creates and returns the property change listener for the scrollpane.
652    *
653    * @return the property change listener for the scrollpane
654    */
655   protected PropertyChangeListener createPropertyChangeListener()
656   {
657     return new PropertyChangeHandler();
658   }
659
660   /**
661    * Creates and returns the mouse wheel listener for the scrollpane.
662    *
663    * @return the mouse wheel listener for the scrollpane
664    * 
665    * @since 1.4
666    */
667   protected MouseWheelListener createMouseWheelListener()
668   {
669     return new MouseWheelHandler();
670   }
671
672   public void uninstallUI(final JComponent c) 
673   {
674     uninstallDefaults((JScrollPane) c);
675     uninstallListeners(c);
676     installKeyboardActions((JScrollPane) c);
677   }
678
679   /**
680    * Uninstalls all the listeners that have been installed in
681    * {@link #installListeners(JScrollPane)}.
682    *
683    * @param c the scrollpane from which to uninstall the listeners 
684    */
685   protected void uninstallListeners(JComponent c)
686   {
687     JScrollPane sp = (JScrollPane) c;
688     sp.removePropertyChangeListener(spPropertyChangeListener);
689     sp.getHorizontalScrollBar().getModel()
690                                .removeChangeListener(hsbChangeListener);
691     sp.getVerticalScrollBar().getModel()
692                              .removeChangeListener(vsbChangeListener);
693     
694     JViewport v = sp.getViewport();
695     v.removeChangeListener(viewportChangeListener);
696     v.removeContainerListener(containerListener);
697  
698     for (int i = 0; i < v.getComponentCount(); i++)
699       v.getComponent(i).removeMouseWheelListener(mouseWheelListener);
700
701   }
702
703   public Dimension getMinimumSize(JComponent c) 
704   {
705     JScrollPane p = (JScrollPane) c;
706     ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout();
707     return sl.minimumLayoutSize(c);
708   }
709
710   public void paint(Graphics g, JComponent c)
711   {
712     Border vpBorder = scrollpane.getViewportBorder();
713     if (vpBorder != null)
714       {
715         Rectangle r = scrollpane.getViewportBorderBounds();
716         vpBorder.paintBorder(scrollpane, g, r.x, r.y, r.width, r.height);
717       }
718   }
719
720   /**
721    * Synchronizes the scrollbar and header settings positions and extent
722    * with the viewport's view position and extent.
723    */
724   protected void syncScrollPaneWithViewport()
725   {
726     JViewport vp = scrollpane.getViewport();
727
728     if (vp != null)
729       {
730         Dimension extentSize = vp.getExtentSize();
731         Point viewPos = vp.getViewPosition();
732         Dimension viewSize = vp.getViewSize();
733
734         // Update the vertical scrollbar.
735         JScrollBar vsb = scrollpane.getVerticalScrollBar();
736         if (vsb != null)
737           {
738             int extent = extentSize.height;
739             int max = viewSize.height;
740             int val = Math.max(0, Math.min(viewPos.y, max - extent));
741             vsb.setValues(val, extent, 0, max);
742           }
743
744         // Update the horizontal scrollbar.
745         JScrollBar hsb = scrollpane.getHorizontalScrollBar();
746         if (hsb != null)
747           {
748             int extent = extentSize.width;
749             int max = viewSize.width;
750             int val = Math.max(0, Math.min(viewPos.x, max - extent));
751             hsb.setValues(val, extent, 0, max);
752           }
753
754         // Update the row header.
755         JViewport rowHeader = scrollpane.getRowHeader();
756         if (rowHeader != null)
757           {
758             Point p = new Point(0, viewPos.y);
759             rowHeader.setViewPosition(p);
760           }
761
762         // Update the column header.
763         JViewport colHeader = scrollpane.getColumnHeader();
764         if (colHeader != null)
765           {
766             Point p = new Point(viewPos.x, 0);
767             colHeader.setViewPosition(p);
768           }
769       }
770   }
771
772   /**
773    * Receives notification when the <code>columnHeader</code> property has
774    * changed on the scrollpane.
775    *
776    * @param ev the property change event
777    */
778   protected void updateColumnHeader(PropertyChangeEvent ev)
779   {
780     // TODO: Find out what should be done here. Or is this only a hook?
781   }
782
783   /**
784    * Receives notification when the <code>rowHeader</code> property has changed
785    * on the scrollpane.
786    *
787    * @param ev the property change event
788    */
789   protected void updateRowHeader(PropertyChangeEvent ev)
790   {
791     // TODO: Find out what should be done here. Or is this only a hook?
792   }
793
794   /**
795    * Receives notification when the <code>scrollBarDisplayPolicy</code>
796    * property has changed on the scrollpane.
797    *
798    * @param ev the property change event
799    */
800   protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev)
801   {
802     scrollpane.revalidate();
803     scrollpane.repaint();
804   }
805
806   /**
807    * Receives notification when the <code>viewport</code> property has changed
808    * on the scrollpane.
809    *
810    * This method sets removes the viewportChangeListener from the old viewport
811    * and adds it to the new viewport.
812    *
813    * @param ev the property change event
814    */
815   protected void updateViewport(PropertyChangeEvent ev)
816   {
817     JViewport oldViewport = (JViewport) ev.getOldValue();
818     oldViewport.removeChangeListener(viewportChangeListener);
819     JViewport newViewport = (JViewport) ev.getNewValue();
820     newViewport.addChangeListener(viewportChangeListener);
821     syncScrollPaneWithViewport();
822   }
823 }
824
825
826
827
828
829
830
831
832
833
834
835