001/* MultiListUI.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.Point;
043import java.awt.Rectangle;
044import java.util.Iterator;
045import java.util.Vector;
046
047import javax.accessibility.Accessible;
048import javax.swing.JComponent;
049import javax.swing.JList;
050import javax.swing.LookAndFeel;
051import javax.swing.UIManager;
052import javax.swing.plaf.ComponentUI;
053import javax.swing.plaf.ListUI;
054
055/**
056 * A UI delegate that that coordinates multiple {@link ListUI} 
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 MultiListUI extends ListUI 
063{
064
065  /** A list of references to the actual component UIs. */
066  protected Vector uis;
067    
068  /**
069   * Creates a new <code>MultiListUI</code> instance.
070   * 
071   * @see #createUI(JComponent)
072   */
073  public MultiListUI() 
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>MultiListUI</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    MultiListUI mui = new MultiListUI();
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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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>MultiListUI</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 ListUI#locationToIndex(JList, Point)} method for all
357   * the UI delegates managed by this <code>MultiListUI</code>, 
358   * returning the index for the UI delegate from the primary look and 
359   * feel. 
360   * 
361   * @param list  the list.
362   * @param location  the location.
363   * 
364   * @return The index returned by the UI delegate from the primary 
365   *         look and feel. 
366   */
367  public int locationToIndex(JList list, Point location) 
368  {
369    int result = 0;
370    Iterator iterator = uis.iterator();
371    // first UI delegate provides the return value
372    if (iterator.hasNext()) 
373      {
374        ListUI ui = (ListUI) iterator.next();
375        result = ui.locationToIndex(list, location);
376      }
377    // return values from auxiliary UI delegates are ignored
378    while (iterator.hasNext())
379      {
380        ListUI ui = (ListUI) iterator.next();
381        /* int ignored = */ ui.locationToIndex(list, location);
382      }
383    return result;
384  }
385
386  /**
387   * Calls the {@link ListUI#indexToLocation(JList, int)} method for all
388   * the UI delegates managed by this <code>MultiListUI</code>, 
389   * returning the location for the UI delegate from the primary look and 
390   * feel. 
391   * 
392   * @param list  the list.
393   * @param index  the index.
394   * 
395   * @return The location returned by the UI delegate from the primary 
396   *         look and feel. 
397   */
398  public Point indexToLocation(JList list, int index) 
399  {
400    Point result = null;
401    Iterator iterator = uis.iterator();
402    // first UI delegate provides the return value
403    if (iterator.hasNext()) 
404      {
405        ListUI ui = (ListUI) iterator.next();
406        result = ui.indexToLocation(list, index);
407      }
408    // return values from auxiliary UI delegates are ignored
409    while (iterator.hasNext())
410      {
411        ListUI ui = (ListUI) iterator.next();
412        /* Point ignored = */ ui.indexToLocation(list, index);
413      }
414    return result;
415  }
416
417  /**
418   * Calls the {@link ListUI#getCellBounds(JList, int, int)} method for all
419   * the UI delegates managed by this <code>MultiListUI</code>, 
420   * returning the bounds for the UI delegate from the primary look and 
421   * feel. 
422   * 
423   * @param list  the list.
424   * @param index1  the first index.
425   * @param index2  the second index.
426   * 
427   * @return The bounds returned by the UI delegate from the primary 
428   *         look and feel. 
429   */
430  public Rectangle getCellBounds(JList list, int index1, int index2) 
431  {
432    Rectangle result = null;
433    Iterator iterator = uis.iterator();
434    // first UI delegate provides the return value
435    if (iterator.hasNext()) 
436      {
437        ListUI ui = (ListUI) iterator.next();
438        result = ui.getCellBounds(list, index1, index2);
439      }
440    // return values from auxiliary UI delegates are ignored
441    while (iterator.hasNext())
442      {
443        ListUI ui = (ListUI) iterator.next();
444        /* Rectangle ignored = */ ui.getCellBounds(list, index1, index2);
445      }
446    return result;
447  }
448
449}