OSDN Git Service

2004-11-30 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / JScrollPane.java
1 /* JScrollPane.java -- 
2    Copyright (C) 2002, 2004 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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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;
40
41 import java.awt.Component;
42 import java.awt.ComponentOrientation;
43 import java.awt.Dimension;
44 import java.awt.Insets;
45 import java.awt.LayoutManager;
46 import java.awt.Point;
47 import java.awt.Rectangle;
48
49 import javax.accessibility.Accessible;
50 import javax.swing.border.Border;
51 import javax.swing.event.ChangeEvent;
52 import javax.swing.event.ChangeListener;
53 import javax.swing.plaf.ScrollPaneUI;
54 import javax.swing.plaf.UIResource;
55
56 /**
57  * <table>
58  * <tr><th>Property                    </th><th>Stored in       </th><th>Bound?</th></tr>
59  * <tr><td>columnHeader                </td><td>scrollPane      </td><td>yes   </td></tr>
60  * <tr><td>columnHeaderView            </td><td>columnHeader    </td><td>no    </td></tr>
61  * <tr><td>componentOrientation        </td><td>scrollPane      </td><td>yes   </td></tr>
62  * <tr><td>horizontalScrollBar         </td><td>scrollPane      </td><td>yes   </td></tr>
63  * <tr><td>horizontalScrollBarPolicy   </td><td>scrollPane      </td><td>yes   </td></tr>
64  * <tr><td>layout                      </td><td>scrollPane      </td><td>yes   </td></tr>
65  * <tr><td>rowHeader                   </td><td>scrollPane      </td><td>yes   </td></tr>
66  * <tr><td>rowHeaderView               </td><td>rowHeader       </td><td>no    </td></tr>
67  * <tr><td>validateRoot                </td><td>scrollPane      </td><td>no    </td></tr>
68  * <tr><td>verticalScrollBar           </td><td>scrollPane      </td><td>yes   </td></tr>
69  * <tr><td>verticalScrollBarPolicy     </td><td>scrollPane      </td><td>yes   </td></tr>
70  * <tr><td>viewport                    </td><td>scrollPane      </td><td>yes   </td></tr>
71  * <tr><td>viewportBorder              </td><td>scrollPane      </td><td>yes   </td></tr>
72  * <tr><td>viewportBorderBounds        </td><td>scrollPane      </td><td>no    </td></tr>
73  * <tr><td>viewportView                </td><td>viewport        </td><td>no    </td></tr>
74  * <tr><td>wheelScrollingEnabled       </td><td>scrollPane      </td><td>yes   </td></tr>
75  * </table>
76  */
77 public class JScrollPane 
78   extends JComponent 
79   implements Accessible, ScrollPaneConstants
80 {
81   private static final long serialVersionUID = 5203525440012340014L;
82   
83   protected JViewport columnHeader;
84   protected JViewport rowHeader;
85
86   protected Component lowerLeft;
87   protected Component lowerRight;
88   protected Component upperLeft;
89   protected Component upperRight;
90
91   protected JScrollBar horizontalScrollBar;
92   protected int horizontalScrollBarPolicy;
93   protected JScrollBar verticalScrollBar;
94   protected int verticalScrollBarPolicy;
95
96   protected JViewport viewport;
97   
98   Border viewportBorder;
99   boolean wheelScrollingEnabled;
100   ChangeListener scrollListener;  
101
102   public static final String COLUMN_HEADER_CHANGED_PROPERTY = "columnHeader";
103   public static final String COMPONENT_ORIENTATION_CHANGED_PROPERTY = "componentOrientation";
104   public static final String HORIZONTAL_SCROLLBAR_CHANGED_PROPERTY = "horizontalScrollBar";
105   public static final String HORIZONTAL_SCROLLBAR_POLICY_CHANGED_PROPERTY = "horizontalScrollBarPolicy";
106   public static final String LAYOUT_CHANGED_PROPERTY = "layout";
107   public static final String ROW_HEADER_CHANGED_PROPERTY = "rowHeader";
108   public static final String VERTICAL_SCROLLBAR_CHANGED_PROPERTY = "verticalScrollBar";
109   public static final String VERTICAL_SCROLLBAR_POLICY_CHANGED_PROPERTY = "verticalScrollBarPolicy";
110   public static final String VIEWPORT_CHANGED_PROPERTY = "viewport";
111   public static final String VIEWPORT_BORDER_CHANGED_PROPERTY = "viewportBorder";
112   public static final String WHEEL_SCROLLING_ENABLED_CHANGED_PROPERTY = "wheelScrollingEnabled";
113
114   public JViewport getColumnHeader()
115   {
116     return columnHeader;
117   }
118
119   public Component getCorner(String key) {
120     if (getComponentOrientation() 
121         == ComponentOrientation.LEFT_TO_RIGHT)
122       {
123         if (key == LOWER_LEADING_CORNER)
124           key = LOWER_LEFT_CORNER;
125         else if (key == LOWER_TRAILING_CORNER)
126           key = LOWER_RIGHT_CORNER;
127         else if (key == UPPER_LEADING_CORNER)
128           key = UPPER_LEFT_CORNER;
129         else if (key == UPPER_TRAILING_CORNER)
130           key = UPPER_RIGHT_CORNER;
131       }
132     else if (getComponentOrientation() 
133              == ComponentOrientation.RIGHT_TO_LEFT)
134       {
135         if (key == LOWER_LEADING_CORNER)
136           key = LOWER_RIGHT_CORNER;
137         else if (key == LOWER_TRAILING_CORNER)
138           key = LOWER_LEFT_CORNER;
139         else if (key == UPPER_LEADING_CORNER)
140           key = UPPER_RIGHT_CORNER;
141         else if (key == UPPER_TRAILING_CORNER)
142           key = UPPER_LEFT_CORNER;
143       }
144
145     if (key == LOWER_RIGHT_CORNER)
146       return lowerRight;
147     else if (key == UPPER_RIGHT_CORNER)
148       return upperRight;
149     else if (key == LOWER_LEFT_CORNER)
150       return lowerLeft;
151     else if (key == UPPER_LEFT_CORNER)
152       return upperLeft;
153     return null;
154   }
155
156   public JScrollBar getHorizontalScrollBar()
157   {
158     return horizontalScrollBar;
159   }
160
161   public int getHorizontalScrollBarPolicy()
162   {
163     return horizontalScrollBarPolicy;
164   }
165
166   public JViewport getRowHeader()
167   {
168     return rowHeader;
169   }
170
171   public JScrollBar getVerticalScrollBar()
172   {
173     return verticalScrollBar;
174   }
175
176   public int getVerticalScrollBarPolicy()
177   {
178     return verticalScrollBarPolicy;
179   }
180
181   public JViewport getViewport()
182   {
183     return viewport;
184   }
185
186   public Border getViewportBorder()
187   {
188     return viewportBorder;
189   }
190
191   public Rectangle getViewportBorderBounds()
192   {
193     if (viewportBorder == null)
194       {
195         if (getViewport() == null)
196           return new Rectangle(0,0,0,0);
197         else
198           return getViewport().getBounds();
199       }
200     else
201       {
202         Insets i = viewportBorder.getBorderInsets(getViewport());
203         if (getViewport() == null)
204           return new Rectangle(0,0,
205                                i.left+i.right, i.top+i.bottom);
206         else
207           {
208             Rectangle b = getViewport().getBounds();
209             return new Rectangle(b.x - i.left, 
210                                  b.y - i.top,
211                                  b.width + i.left + i.right, 
212                                  b.height + i.top + i.bottom);
213           }
214       }
215   }
216   
217   public boolean isWheelScrollingEnabled()
218   {
219     return wheelScrollingEnabled;
220   }
221
222
223
224   private void sync()
225   {
226     LayoutManager m = super.getLayout();
227     if (m != null && m instanceof ScrollPaneLayout)
228       {
229         ScrollPaneLayout sl = (ScrollPaneLayout) m;
230         sl.syncWithScrollPane(this);
231       }
232   }
233
234   private void removeNonNull(Component c)
235   {
236     if (c != null)
237       remove(c);
238   }
239
240   private void addNonNull(Component c)
241   {
242     if (c != null)
243       add(c);
244   }
245
246   public void setComponentOrientation(ComponentOrientation co)
247   {
248     ComponentOrientation old = super.getComponentOrientation();
249     super.setComponentOrientation(co);
250     firePropertyChange(COMPONENT_ORIENTATION_CHANGED_PROPERTY, old, co);
251     sync();
252   }
253
254   public void setColumnHeader(JViewport h)
255   {
256     JViewport old = columnHeader;
257     removeNonNull(old);
258     columnHeader = h;
259     addNonNull(h);
260     firePropertyChange(COLUMN_HEADER_CHANGED_PROPERTY, old, h);
261     sync();
262   }
263
264   public void setColumnHeaderView(Component c)
265   {
266     if (columnHeader == null)
267       setColumnHeader(createViewport());
268     columnHeader.setView(c);
269     sync();
270   }
271
272   public void setCorner(String key, Component c)
273   {
274     if (getComponentOrientation() 
275         == ComponentOrientation.LEFT_TO_RIGHT)
276       {
277         if (key == LOWER_LEADING_CORNER)
278           key = LOWER_LEFT_CORNER;
279         else if (key == LOWER_TRAILING_CORNER)
280           key = LOWER_RIGHT_CORNER;
281         else if (key == UPPER_LEADING_CORNER)
282           key = UPPER_LEFT_CORNER;
283         else if (key == UPPER_TRAILING_CORNER)
284           key = UPPER_RIGHT_CORNER;
285       }
286     else if (getComponentOrientation() 
287              == ComponentOrientation.RIGHT_TO_LEFT)
288       {
289         if (key == LOWER_LEADING_CORNER)
290           key = LOWER_RIGHT_CORNER;
291         else if (key == LOWER_TRAILING_CORNER)
292           key = LOWER_LEFT_CORNER;
293         else if (key == UPPER_LEADING_CORNER)
294           key = UPPER_RIGHT_CORNER;
295         else if (key == UPPER_TRAILING_CORNER)
296           key = UPPER_LEFT_CORNER;
297       }
298
299     if (key == LOWER_RIGHT_CORNER)
300       {
301         removeNonNull(lowerRight);
302         lowerRight = c;
303         addNonNull(c);
304       }
305     else if (key == UPPER_RIGHT_CORNER)
306       {
307         removeNonNull(upperRight);
308         upperRight = c;
309         addNonNull(c);
310       }
311     else if (key == LOWER_LEFT_CORNER)
312       {
313         removeNonNull(lowerLeft);
314         lowerLeft = c;
315         addNonNull(c);
316       }
317     else if (key == UPPER_LEFT_CORNER)
318       {
319         removeNonNull(upperLeft);
320         upperLeft = c;
321         addNonNull(c);
322       }
323     else
324       throw new IllegalArgumentException("unknown corner " + key);
325     sync();
326   }
327
328   public void setHorizontalScrollBar(JScrollBar h)
329   {
330     JScrollBar old = horizontalScrollBar;
331     removeNonNull(old);
332     horizontalScrollBar = h;
333     addNonNull(h);
334     firePropertyChange(HORIZONTAL_SCROLLBAR_CHANGED_PROPERTY, old, h);
335     sync();
336
337     if (old != null)
338       {
339         BoundedRangeModel model = old.getModel();
340         if (model != null)
341           model.removeChangeListener(scrollListener);
342       }
343     if (h != null)
344       {
345         BoundedRangeModel model = h.getModel();
346         if (model != null)
347           model.addChangeListener(scrollListener);
348       }
349   }
350
351   public void setHorizontalScrollBarPolicy(int h)
352   {    
353     if (h != HORIZONTAL_SCROLLBAR_AS_NEEDED
354         && h != HORIZONTAL_SCROLLBAR_NEVER
355         && h != HORIZONTAL_SCROLLBAR_ALWAYS)
356       throw new IllegalArgumentException("unknown horizontal scrollbar policy");    
357     int old = horizontalScrollBarPolicy;
358     horizontalScrollBarPolicy = h;
359     firePropertyChange(HORIZONTAL_SCROLLBAR_POLICY_CHANGED_PROPERTY, old, h);
360     sync();
361   }
362
363   public void setLayout(LayoutManager l)
364   {
365     LayoutManager old = super.getLayout();
366     ScrollPaneLayout tmp = (ScrollPaneLayout) l;
367     super.setLayout(l);
368     tmp.syncWithScrollPane(this);
369     firePropertyChange(LAYOUT_CHANGED_PROPERTY, old, l);
370     sync();
371   }
372
373   public void setRowHeader(JViewport v)
374   {
375     JViewport old = rowHeader;
376     removeNonNull(old);
377     rowHeader = v;
378     addNonNull(v);
379     firePropertyChange(ROW_HEADER_CHANGED_PROPERTY, old, v);
380     sync();
381   }
382
383   public void setRowHeaderView(Component c)
384   {
385     if (rowHeader == null)
386       setRowHeader(createViewport());
387     rowHeader.setView(c);
388     sync();
389   }
390
391   public void setVerticalScrollBar(JScrollBar v)
392   {
393     JScrollBar old = verticalScrollBar;
394     removeNonNull(old);
395     verticalScrollBar = v;
396     addNonNull(v);
397     firePropertyChange(VERTICAL_SCROLLBAR_CHANGED_PROPERTY, old, v);
398     sync();
399
400     if (old != null)
401       {
402         BoundedRangeModel model = old.getModel();
403         if (model != null)
404           model.removeChangeListener(scrollListener);
405       }
406     if (v != null)
407       {
408         BoundedRangeModel model = v.getModel();
409         if (model != null)
410           model.addChangeListener(scrollListener);
411       }
412   }
413
414   public void setVerticalScrollBarPolicy(int v)
415   {
416     if (v != VERTICAL_SCROLLBAR_AS_NEEDED
417         && v != VERTICAL_SCROLLBAR_NEVER
418         && v != VERTICAL_SCROLLBAR_ALWAYS)
419       throw new IllegalArgumentException("unknown vertical scrollbar policy");    
420     int old = verticalScrollBarPolicy;
421     verticalScrollBarPolicy = v;
422     firePropertyChange(VERTICAL_SCROLLBAR_POLICY_CHANGED_PROPERTY, old, v);
423     sync();
424   }
425
426   public void setWheelScrollingEnabled(boolean b)
427   {
428     boolean old = wheelScrollingEnabled;
429     wheelScrollingEnabled = b;
430     firePropertyChange(WHEEL_SCROLLING_ENABLED_CHANGED_PROPERTY, old, b);
431     sync();
432   }
433
434   public void setViewport(JViewport v)
435   {
436     JViewport old = viewport;
437     removeNonNull(old);
438     if (old != null)
439       old.removeChangeListener(scrollListener);
440     viewport = v;
441     if (v != null)
442       v.addChangeListener(scrollListener);
443     addNonNull(v);
444     revalidate();
445     repaint();
446     firePropertyChange(VIEWPORT_CHANGED_PROPERTY, old, v);
447     sync();
448   }
449
450   public void setViewportBorder(Border b)
451   {
452     Border old = viewportBorder;
453     viewportBorder = b;
454     firePropertyChange(VIEWPORT_BORDER_CHANGED_PROPERTY, old, b);
455     sync();
456   }
457     
458   public void setViewportView(Component view)
459   {
460     if (getViewport() == null)
461       {
462         setViewport(createViewport());
463       }
464         
465     if (view != null)
466       {
467         getViewport().setView(view);
468       }
469     sync();
470   }
471
472   public boolean isValidateRoot()
473   {
474     return true;
475   }
476
477   ChangeListener createScrollListener()
478   {
479     return new ChangeListener() 
480       {
481         
482         public void stateChanged(ChangeEvent event)
483         {
484           JScrollBar vsb = JScrollPane.this.getVerticalScrollBar();
485           JScrollBar hsb = JScrollPane.this.getHorizontalScrollBar();
486           JViewport vp = JScrollPane.this.getViewport();
487
488           if (vp != null && event.getSource() == vp)
489             {
490               // if the viewport changed, we should update the VSB / HSB
491               // models according to the new vertical and horizontal sizes
492
493               Rectangle vr = vp.getViewRect();
494               Dimension vs = vp.getViewSize();
495               if (vsb != null
496                   && (vsb.getMinimum() != 0
497                       || vsb.getMaximum() != vs.height
498                       || vsb.getValue() != vr.y
499                       || vsb.getVisibleAmount() != vr.height))
500                 vsb.setValues(vr.y, vr.height, 0, vs.height);
501
502               if (hsb != null
503                   && (hsb.getMinimum() != 0
504                       || hsb.getMaximum() != vs.width
505                       || hsb.getValue() != vr.width
506                       || hsb.getVisibleAmount() != vr.height))
507                 hsb.setValues(vr.x, vr.width, 0, vs.width);
508             }
509           else
510             {
511               // otherwise we got a change update from either the VSB or
512               // HSB model, and we need to update the viewport positions of
513               // both the main viewport and any row or column headers to
514               // match.
515
516               int xpos = 0;
517               int ypos = 0;
518               
519               if (vsb != null)
520                 ypos = vsb.getValue();
521               
522               if (hsb != null)
523                 xpos = hsb.getValue();
524
525               Point pt = new Point(xpos, ypos);
526
527               if (vp != null
528                   && vp.getViewPosition() != pt)
529                 vp.setViewPosition(pt);
530
531               pt.x = 0;
532
533               if (rowHeader != null 
534                   && rowHeader.getViewPosition() != pt)
535                 rowHeader.setViewPosition(pt);
536               
537               pt.x = xpos;
538               pt.y = 0;
539
540               if (columnHeader != null 
541                   && columnHeader.getViewPosition() != pt)
542                 columnHeader.setViewPosition(pt);
543
544             }
545         }
546       };
547   }
548
549
550   public JScrollPane() 
551   {
552     this(null);
553   }
554     
555   public JScrollPane(Component view) 
556   {
557     this(view, 
558          VERTICAL_SCROLLBAR_AS_NEEDED, 
559          HORIZONTAL_SCROLLBAR_AS_NEEDED);
560   }
561
562   public JScrollPane(int vsbPolicy, int hsbPolicy) 
563   {
564     this(null, vsbPolicy, hsbPolicy);
565   }
566
567   public JScrollPane(Component view, int vsbPolicy, int hsbPolicy) 
568   {
569     scrollListener = createScrollListener();
570     setVerticalScrollBarPolicy(vsbPolicy);
571     setVerticalScrollBar(createVerticalScrollBar());
572     setHorizontalScrollBarPolicy(hsbPolicy);
573     setHorizontalScrollBar(createHorizontalScrollBar());
574     setViewportView(view);
575     setLayout(new ScrollPaneLayout());
576     setOpaque(false);
577     updateUI();
578   }
579
580   
581   public JScrollBar createHorizontalScrollBar()
582   {
583     return new ScrollBar(SwingConstants.HORIZONTAL);
584   }
585
586   public JScrollBar createVerticalScrollBar()
587   {
588     return new ScrollBar(SwingConstants.VERTICAL);
589   }
590     
591   public JViewport createViewport()
592   {
593     return new JViewport();
594   }
595
596   public String getUIClassID()
597   {
598     return "ScrollPaneUI";
599   }
600   
601   public void updateUI()
602   {
603     ScrollPaneUI b = (ScrollPaneUI)UIManager.getUI(this);
604     setUI(b);
605   }  
606
607   /**
608    * This method returns the scrollpane's UI delegate.
609    *
610    * @return The scrollpane's UI delegate.
611    */
612   public ScrollPaneUI getUI()
613   {
614     return (ScrollPaneUI) ui;
615   }
616
617   /**
618    * This method sets the scrollpane's UI delegate.
619    *
620    * @param ui The scrollpane's UI delegate.
621    */
622   public void setUI(ScrollPaneUI ui)
623   {
624     super.setUI(ui);
625   }
626
627   class ScrollBar 
628     extends JScrollBar
629     implements UIResource
630   {
631     public ScrollBar(int orientation)
632     {
633       super(orientation);
634     }
635
636     public int getBlockIncrement(int direction)
637     {
638       Component view = JScrollPane.this.getViewport().getView();
639       if (view == null || (! (view instanceof Scrollable)))
640         return super.getBlockIncrement(direction);
641       else
642         {
643           Scrollable s = (Scrollable) view;
644           return s.getScrollableBlockIncrement(JScrollPane.this.getViewport().getViewRect(), 
645                                                this.getOrientation(),
646                                                direction);
647         }
648     }
649
650     public int getUnitIncrement(int direction)
651     {
652       Component view = JScrollPane.this.getViewport().getView();
653       if (view == null || (! (view instanceof Scrollable)))
654         return super.getUnitIncrement(direction);
655       else
656         {
657           Scrollable s = (Scrollable) view;
658           return s.getScrollableUnitIncrement(JScrollPane.this.getViewport().getViewRect(), 
659                                               this.getOrientation(),
660                                               direction);
661         }
662     }
663
664
665   }
666   
667 }