001/* MultiTreeUI.java --
002   Copyright (C) 2005 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.swing.plaf.multi;
039
040import java.awt.Dimension;
041import java.awt.Graphics;
042import java.awt.Rectangle;
043import java.util.Iterator;
044import java.util.Vector;
045
046import javax.accessibility.Accessible;
047import javax.swing.JComponent;
048import javax.swing.JTree;
049import javax.swing.LookAndFeel;
050import javax.swing.UIManager;
051import javax.swing.plaf.ComponentUI;
052import javax.swing.plaf.TreeUI;
053import javax.swing.tree.TreePath;
054
055/**
056 * A UI delegate that that coordinates multiple {@link TreeUI} 
057 * instances, one from the primary look and feel, and one or more from the 
058 * auxiliary look and feel(s).
059 * 
060 * @see UIManager#addAuxiliaryLookAndFeel(LookAndFeel)
061 */
062public class MultiTreeUI extends TreeUI 
063{
064
065  /** A list of references to the actual component UIs. */
066  protected Vector uis;
067    
068  /**
069   * Creates a new <code>MultiTreeUI</code> instance.
070   * 
071   * @see #createUI(JComponent)
072   */
073  public MultiTreeUI() 
074  {
075    uis = new Vector();
076  }
077  
078  /**
079   * Creates a delegate object for the specified component.  If any auxiliary 
080   * look and feels support this component, a <code>MultiTreeUI</code> is
081   * returned, otherwise the UI from the default look and feel is returned.
082   * 
083   * @param target  the component.
084   * 
085   * @see MultiLookAndFeel#createUIs(ComponentUI, Vector, JComponent)
086   */
087  public static ComponentUI createUI(JComponent target)
088  {
089    MultiTreeUI mui = new MultiTreeUI();
090    return MultiLookAndFeel.createUIs(mui, mui.uis, target);
091  }
092  
093  /**
094   * Calls the {@link ComponentUI#installUI(JComponent)} method for all 
095   * the UI delegates managed by this <code>MultiTreeUI</code>.
096   * 
097   * @param c  the component.
098   */
099  public void installUI(JComponent c)
100  {
101    Iterator iterator = uis.iterator();
102    while (iterator.hasNext())
103    {
104      ComponentUI ui = (ComponentUI) iterator.next();
105      ui.installUI(c);
106    }
107  }
108
109  /**
110   * Calls the {@link ComponentUI#uninstallUI(JComponent)} method for all 
111   * the UI delegates managed by this <code>MultiTreeUI</code>.
112   * 
113   * @param c  the component.
114   */
115  public void uninstallUI(JComponent c)
116  {
117    Iterator iterator = uis.iterator();
118    while (iterator.hasNext())
119    {
120      ComponentUI ui = (ComponentUI) iterator.next();
121      ui.uninstallUI(c);
122    }
123  }
124  
125  /**
126   * Returns an array containing the UI delegates managed by this
127   * <code>MultiTreeUI</code>.  The first item in the array is always 
128   * the UI delegate from the installed default look and feel.
129   * 
130   * @return An array of UI delegates.
131   */
132  public ComponentUI[] getUIs()
133  {
134    return MultiLookAndFeel.uisToArray(uis);
135  }
136  
137  /**
138   * Calls the {@link ComponentUI#contains(JComponent, int, int)} method for all 
139   * the UI delegates managed by this <code>MultiTreeUI</code>, 
140   * returning the result for the UI delegate from the primary look and 
141   * feel. 
142   * 
143   * @param c  the component.
144   * @param x  the x-coordinate.
145   * @param y  the y-coordinate.
146   * 
147   * @return <code>true</code> if the specified (x, y) coordinate falls within
148   *         the bounds of the component as rendered by the UI delegate in the
149   *         primary look and feel, and <code>false</code> otherwise. 
150   */
151  public boolean contains(JComponent c, int x, int y) 
152  {
153    boolean result = false;
154    Iterator iterator = uis.iterator();
155    // first UI delegate provides the return value
156    if (iterator.hasNext()) 
157      {
158        ComponentUI ui = (ComponentUI) iterator.next();
159        result = ui.contains(c, x, y);
160      }
161    // return values from auxiliary UI delegates are ignored
162    while (iterator.hasNext())
163      {
164        ComponentUI ui = (ComponentUI) iterator.next();
165        /* boolean ignored = */ ui.contains(c, x, y);
166      }
167    return result;
168  }
169  
170  /**
171   * Calls the {@link ComponentUI#update(Graphics, JComponent)} method for all 
172   * the UI delegates managed by this <code>MultiTreeUI</code>.
173   * 
174   * @param g  the graphics device.
175   * @param c  the component.
176   */
177  public void update(Graphics g, JComponent c)
178  {
179    Iterator iterator = uis.iterator();
180    while (iterator.hasNext())
181    {
182      ComponentUI ui = (ComponentUI) iterator.next();
183      ui.update(g, c);
184    }
185  }
186
187  /**
188   * Calls the <code>paint(Graphics, JComponent)</code> method for all the UI 
189   * delegates managed by this <code>MultiTreeUI</code>.
190   * 
191   * @param g  the graphics device.
192   * @param c  the component.
193   */
194  public void paint(Graphics g, JComponent c)
195  {
196    Iterator iterator = uis.iterator();
197    while (iterator.hasNext())
198    {
199      ComponentUI ui = (ComponentUI) iterator.next();
200      ui.paint(g, c);
201    }
202  }
203  
204  /**
205   * Calls the {@link ComponentUI#getPreferredSize(JComponent)} method for all
206   * the UI delegates managed by this <code>MultiTreeUI</code>, 
207   * returning the preferred size for the UI delegate from the primary look and 
208   * feel. 
209   * 
210   * @param c  the component.
211   * 
212   * @return The preferred size returned by the UI delegate from the primary 
213   *         look and feel. 
214   */
215  public Dimension getPreferredSize(JComponent c)
216  {
217    Dimension result = null;
218    Iterator iterator = uis.iterator();
219    // first UI delegate provides the return value
220    if (iterator.hasNext()) 
221      {
222        ComponentUI ui = (ComponentUI) iterator.next();
223        result = ui.getPreferredSize(c);
224      }
225    // return values from auxiliary UI delegates are ignored
226    while (iterator.hasNext())
227      {
228        ComponentUI ui = (ComponentUI) iterator.next();
229        /* Dimension ignored = */ ui.getPreferredSize(c);
230      }
231    return result;
232  }
233 
234  /**
235   * Calls the {@link ComponentUI#getMinimumSize(JComponent)} method for all
236   * the UI delegates managed by this <code>MultiTreeUI</code>, 
237   * returning the minimum size for the UI delegate from the primary look and 
238   * feel. 
239   * 
240   * @param c  the component.
241   * 
242   * @return The minimum size returned by the UI delegate from the primary 
243   *         look and feel. 
244   */
245  public Dimension getMinimumSize(JComponent c)
246  {
247    Dimension result = null;
248    Iterator iterator = uis.iterator();
249    // first UI delegate provides the return value
250    if (iterator.hasNext()) 
251      {
252        ComponentUI ui = (ComponentUI) iterator.next();
253        result = ui.getMinimumSize(c);
254      }
255    // return values from auxiliary UI delegates are ignored
256    while (iterator.hasNext())
257      {
258        ComponentUI ui = (ComponentUI) iterator.next();
259        /* Dimension ignored = */ ui.getMinimumSize(c);
260      }
261    return result;
262  }
263  
264  /**
265   * Calls the {@link ComponentUI#getMaximumSize(JComponent)} method for all
266   * the UI delegates managed by this <code>MultiTreeUI</code>, 
267   * returning the maximum size for the UI delegate from the primary look and 
268   * feel. 
269   * 
270   * @param c  the component.
271   * 
272   * @return The maximum size returned by the UI delegate from the primary 
273   *         look and feel. 
274   */
275  public Dimension getMaximumSize(JComponent c)
276  {
277    Dimension result = null;
278    Iterator iterator = uis.iterator();
279    // first UI delegate provides the return value
280    if (iterator.hasNext()) 
281      {
282        ComponentUI ui = (ComponentUI) iterator.next();
283        result = ui.getMaximumSize(c);
284      }
285    // return values from auxiliary UI delegates are ignored
286    while (iterator.hasNext())
287      {
288        ComponentUI ui = (ComponentUI) iterator.next();
289        /* Dimension ignored = */ ui.getMaximumSize(c);
290      }
291    return result;
292  }
293  
294  /**
295   * Calls the {@link ComponentUI#getAccessibleChildrenCount(JComponent)} method
296   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
297   * returning the count for the UI delegate from the primary look and 
298   * feel. 
299   * 
300   * @param c  the component.
301   * 
302   * @return The count returned by the UI delegate from the primary 
303   *         look and feel. 
304   */
305  public int getAccessibleChildrenCount(JComponent c)
306  {
307    int result = 0;
308    Iterator iterator = uis.iterator();
309    // first UI delegate provides the return value
310    if (iterator.hasNext()) 
311      {
312        ComponentUI ui = (ComponentUI) iterator.next();
313        result = ui.getAccessibleChildrenCount(c);
314      }
315    // return values from auxiliary UI delegates are ignored
316    while (iterator.hasNext())
317      {
318        ComponentUI ui = (ComponentUI) iterator.next();
319        /* int ignored = */ ui.getAccessibleChildrenCount(c);
320      }
321    return result;
322  }
323  
324  /**
325   * Calls the {@link ComponentUI#getAccessibleChild(JComponent, int)} method
326   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
327   * returning the child for the UI delegate from the primary look and 
328   * feel. 
329   * 
330   * @param c  the component
331   * @param i  the child index.
332   * 
333   * @return The child returned by the UI delegate from the primary 
334   *         look and feel. 
335   */
336  public Accessible getAccessibleChild(JComponent c, int i)
337  {
338    Accessible result = null;
339    Iterator iterator = uis.iterator();
340    // first UI delegate provides the return value
341    if (iterator.hasNext()) 
342      {
343        ComponentUI ui = (ComponentUI) iterator.next();
344        result = ui.getAccessibleChild(c, i);
345      }
346    // return values from auxiliary UI delegates are ignored
347    while (iterator.hasNext())
348      {
349        ComponentUI ui = (ComponentUI) iterator.next();
350        /* Accessible ignored = */ ui.getAccessibleChild(c, i);
351      }
352    return result;
353  }
354  
355  /**
356   * Calls the {@link TreeUI#getPathBounds(JTree, TreePath)} method
357   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
358   * returning the bounds for the UI delegate from the primary look and 
359   * feel. 
360   * 
361   * @param tree  the tree component.
362   * 
363   * @return The bounds returned by the UI delegate from the primary 
364   *         look and feel. 
365   */
366  public Rectangle getPathBounds(JTree tree, TreePath path) 
367  {
368    Rectangle result = null;
369    Iterator iterator = uis.iterator();
370    // first UI delegate provides the return value
371    if (iterator.hasNext()) 
372      {
373        TreeUI ui = (TreeUI) iterator.next();
374        result = ui.getPathBounds(tree, path);
375      }
376    // return values from auxiliary UI delegates are ignored
377    while (iterator.hasNext())
378      {
379        TreeUI ui = (TreeUI) iterator.next();
380        /* Rectangle ignored = */ ui.getPathBounds(tree, path);
381      }
382    return result;
383  }
384
385  /**
386   * Calls the {@link TreeUI#getPathForRow(JTree, int)} method
387   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
388   * returning the path for the UI delegate from the primary look and 
389   * feel. 
390   * 
391   * @param tree  the tree component.
392   * 
393   * @return The path returned by the UI delegate from the primary 
394   *         look and feel. 
395   */
396  public TreePath getPathForRow(JTree tree, int row) 
397  {
398    TreePath result = null;
399    Iterator iterator = uis.iterator();
400    // first UI delegate provides the return value
401    if (iterator.hasNext()) 
402      {
403        TreeUI ui = (TreeUI) iterator.next();
404        result = ui.getPathForRow(tree, row);
405      }
406    // return values from auxiliary UI delegates are ignored
407    while (iterator.hasNext())
408      {
409        TreeUI ui = (TreeUI) iterator.next();
410        /* TreePath ignored = */ ui.getPathForRow(tree, row);
411      }
412    return result;
413  }
414
415  /**
416   * Calls the {@link TreeUI#getRowForPath(JTree, TreePath)} method
417   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
418   * returning the row index for the UI delegate from the primary look and 
419   * feel. 
420   * 
421   * @param tree  the tree component.
422   * 
423   * @return The row index returned by the UI delegate from the primary 
424   *         look and feel. 
425   */
426  public int getRowForPath(JTree tree, TreePath path) 
427  {
428    int result = 0;
429    Iterator iterator = uis.iterator();
430    // first UI delegate provides the return value
431    if (iterator.hasNext()) 
432      {
433        TreeUI ui = (TreeUI) iterator.next();
434        result = ui.getRowForPath(tree, path);
435      }
436    // return values from auxiliary UI delegates are ignored
437    while (iterator.hasNext())
438      {
439        TreeUI ui = (TreeUI) iterator.next();
440        /* int ignored = */ ui.getRowForPath(tree, path);
441      }
442    return result;  
443  }
444
445  /**
446   * Calls the {@link TreeUI#getRowCount(JTree)} method
447   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
448   * returning the count for the UI delegate from the primary look and 
449   * feel. 
450   * 
451   * @param tree  the tree component.
452   * 
453   * @return The count returned by the UI delegate from the primary 
454   *         look and feel. 
455   */
456  public int getRowCount(JTree tree) 
457  {
458    int result = 0;
459    Iterator iterator = uis.iterator();
460    // first UI delegate provides the return value
461    if (iterator.hasNext()) 
462      {
463        TreeUI ui = (TreeUI) iterator.next();
464        result = ui.getRowCount(tree);
465      }
466    // return values from auxiliary UI delegates are ignored
467    while (iterator.hasNext())
468      {
469        TreeUI ui = (TreeUI) iterator.next();
470        /* int ignored = */ ui.getRowCount(tree);
471      }
472    return result;  
473  }
474
475  /**
476   * Calls the {@link TreeUI#getClosestPathForLocation(JTree, int, int)} method
477   * for all the UI delegates managed by this <code>MultiTreeUI</code>, 
478   * returning the path for the UI delegate from the primary look and 
479   * feel. 
480   * 
481   * @param tree  the tree component.
482   * 
483   * @return The path returned by the UI delegate from the primary 
484   *         look and feel. 
485   */
486  public TreePath getClosestPathForLocation(JTree tree, int x, int y) 
487  {
488    TreePath result = null;
489    Iterator iterator = uis.iterator();
490    // first UI delegate provides the return value
491    if (iterator.hasNext()) 
492      {
493        TreeUI ui = (TreeUI) iterator.next();
494        result = ui.getClosestPathForLocation(tree, x, y);
495      }
496    // return values from auxiliary UI delegates are ignored
497    while (iterator.hasNext())
498      {
499        TreeUI ui = (TreeUI) iterator.next();
500        /* TreePath ignored = */ ui.getClosestPathForLocation(tree, x, y);
501      }
502    return result;  
503  }
504
505  /**
506   * Calls the {@link TreeUI#isEditing(JTree)} method for all
507   * the UI delegates managed by this <code>MultiTreeUI</code>, 
508   * returning the result for the UI delegate from the primary look and 
509   * feel. 
510   * 
511   * @param tree  the tree component.
512   * 
513   * @return The result returned by the UI delegate from the primary 
514   *         look and feel. 
515   */
516  public boolean isEditing(JTree tree) 
517  {
518    boolean result = false;
519    Iterator iterator = uis.iterator();
520    // first UI delegate provides the return value
521    if (iterator.hasNext()) 
522      {
523        TreeUI ui = (TreeUI) iterator.next();
524        result = ui.isEditing(tree);
525      }
526    // return values from auxiliary UI delegates are ignored
527    while (iterator.hasNext())
528      {
529        TreeUI ui = (TreeUI) iterator.next();
530        /* boolean ignored = */ ui.isEditing(tree);
531      }
532    return result;
533  }
534
535  /**
536   * Calls the {@link TreeUI#stopEditing(JTree)} method for all
537   * the UI delegates managed by this <code>MultiTreeUI</code>, 
538   * returning the result for the UI delegate from the primary look and 
539   * feel. 
540   * 
541   * @param tree  the tree component.
542   * 
543   * @return The result returned by the UI delegate from the primary 
544   *         look and feel. 
545   */
546  public boolean stopEditing(JTree tree) 
547  {
548    boolean result = false;
549    Iterator iterator = uis.iterator();
550    // first UI delegate provides the return value
551    if (iterator.hasNext()) 
552      {
553        TreeUI ui = (TreeUI) iterator.next();
554        result = ui.stopEditing(tree);
555      }
556    // return values from auxiliary UI delegates are ignored
557    while (iterator.hasNext())
558      {
559        TreeUI ui = (TreeUI) iterator.next();
560        /* boolean ignored = */ ui.stopEditing(tree);
561      }
562    return result;
563  }
564
565  /**
566   * Calls the {@link TreeUI#cancelEditing(JTree)} method for 
567   * all the UI delegates managed by this <code>MultiTreeUI</code>.
568   * 
569   * @param tree  the tree component.
570   */
571  public void cancelEditing(JTree tree) 
572  {
573    Iterator iterator = uis.iterator();
574    while (iterator.hasNext())
575    {
576      TreeUI ui = (TreeUI) iterator.next();
577      ui.cancelEditing(tree);
578    }
579  }
580
581  /**
582   * Calls the {@link TreeUI#startEditingAtPath(JTree, TreePath)} method for 
583   * all the UI delegates managed by this <code>MultiTreeUI</code>.
584   * 
585   * @param tree  the tree component.
586   * @param path  the path.
587   */
588  public void startEditingAtPath(JTree tree, TreePath path) 
589  {
590    Iterator iterator = uis.iterator();
591    while (iterator.hasNext())
592    {
593      TreeUI ui = (TreeUI) iterator.next();
594      ui.startEditingAtPath(tree, path);
595    }
596  }
597
598  /**
599   * Calls the {@link TreeUI#getEditingPath(JTree)} method for all
600   * the UI delegates managed by this <code>MultiTreeUI</code>, 
601   * returning the path for the UI delegate from the primary look and 
602   * feel. 
603   * 
604   * @param tree  the tree component.
605   * 
606   * @return The path returned by the UI delegate from the primary 
607   *         look and feel. 
608   */
609  public TreePath getEditingPath(JTree tree) 
610  {
611    TreePath result = null;
612    Iterator iterator = uis.iterator();
613    // first UI delegate provides the return value
614    if (iterator.hasNext()) 
615      {
616        TreeUI ui = (TreeUI) iterator.next();
617        result = ui.getEditingPath(tree);
618      }
619    // return values from auxiliary UI delegates are ignored
620    while (iterator.hasNext())
621      {
622        TreeUI ui = (TreeUI) iterator.next();
623        /* TreePath ignored = */ ui.getEditingPath(tree);
624      }
625    return result;  
626  }
627
628}