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