001    /* MultiTextUI.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.awt.Point;
043    import java.awt.Rectangle;
044    import java.util.Iterator;
045    import java.util.Vector;
046    
047    import javax.accessibility.Accessible;
048    import javax.swing.JComponent;
049    import javax.swing.LookAndFeel;
050    import javax.swing.UIManager;
051    import javax.swing.plaf.ComponentUI;
052    import javax.swing.plaf.TextUI;
053    import javax.swing.text.BadLocationException;
054    import javax.swing.text.EditorKit;
055    import javax.swing.text.JTextComponent;
056    import javax.swing.text.Position;
057    import javax.swing.text.View;
058    import javax.swing.text.Position.Bias;
059    
060    /**
061     * A UI delegate that that coordinates multiple {@link TextUI}
062     * instances, one from the primary look and feel, and one or more from the
063     * auxiliary look and feel(s).
064     *
065     * @see UIManager#addAuxiliaryLookAndFeel(LookAndFeel)
066     */
067    public class MultiTextUI extends TextUI
068    {
069    
070      /** A list of references to the actual component UIs. */
071      protected Vector uis;
072    
073      /**
074       * Creates a new <code>MultiTextUI</code> instance.
075       *
076       * @see #createUI(JComponent)
077       */
078      public MultiTextUI()
079      {
080        uis = new Vector();
081      }
082    
083      /**
084       * Creates a delegate object for the specified component.  If any auxiliary
085       * look and feels support this component, a <code>MultiTextUI</code> is
086       * returned, otherwise the UI from the default look and feel is returned.
087       *
088       * @param target  the component.
089       *
090       * @see MultiLookAndFeel#createUIs(ComponentUI, Vector, JComponent)
091       */
092      public static ComponentUI createUI(JComponent target)
093      {
094        MultiTextUI mui = new MultiTextUI();
095        return MultiLookAndFeel.createUIs(mui, mui.uis, target);
096      }
097    
098      /**
099       * Calls the {@link ComponentUI#installUI(JComponent)} method for all
100       * the UI delegates managed by this <code>MultiTextUI</code>.
101       *
102       * @param c  the component.
103       */
104      public void installUI(JComponent c)
105      {
106        Iterator iterator = uis.iterator();
107        while (iterator.hasNext())
108        {
109          ComponentUI ui = (ComponentUI) iterator.next();
110          ui.installUI(c);
111        }
112      }
113    
114      /**
115       * Calls the {@link ComponentUI#uninstallUI(JComponent)} method for all
116       * the UI delegates managed by this <code>MultiTextUI</code>.
117       *
118       * @param c  the component.
119       */
120      public void uninstallUI(JComponent c)
121      {
122        Iterator iterator = uis.iterator();
123        while (iterator.hasNext())
124        {
125          ComponentUI ui = (ComponentUI) iterator.next();
126          ui.uninstallUI(c);
127        }
128      }
129    
130      /**
131       * Returns an array containing the UI delegates managed by this
132       * <code>MultiTextUI</code>.  The first item in the array is always
133       * the UI delegate from the installed default look and feel.
134       *
135       * @return An array of UI delegates.
136       */
137      public ComponentUI[] getUIs()
138      {
139        return MultiLookAndFeel.uisToArray(uis);
140      }
141    
142      /**
143       * Calls the {@link ComponentUI#contains(JComponent, int, int)} method for all
144       * the UI delegates managed by this <code>MultiTextUI</code>,
145       * returning the result for the UI delegate from the primary look and
146       * feel.
147       *
148       * @param c  the component.
149       * @param x  the x-coordinate.
150       * @param y  the y-coordinate.
151       *
152       * @return <code>true</code> if the specified (x, y) coordinate falls within
153       *         the bounds of the component as rendered by the UI delegate in the
154       *         primary look and feel, and <code>false</code> otherwise.
155       */
156      public boolean contains(JComponent c, int x, int y)
157      {
158        boolean result = false;
159        Iterator iterator = uis.iterator();
160        // first UI delegate provides the return value
161        if (iterator.hasNext())
162          {
163            ComponentUI ui = (ComponentUI) iterator.next();
164            result = ui.contains(c, x, y);
165          }
166        // return values from auxiliary UI delegates are ignored
167        while (iterator.hasNext())
168          {
169            ComponentUI ui = (ComponentUI) iterator.next();
170            /* boolean ignored = */ ui.contains(c, x, y);
171          }
172        return result;
173      }
174    
175      /**
176       * Calls the {@link ComponentUI#update(Graphics, JComponent)} method for all
177       * the UI delegates managed by this <code>MultiTextUI</code>.
178       *
179       * @param g  the graphics device.
180       * @param c  the component.
181       */
182      public void update(Graphics g, JComponent c)
183      {
184        Iterator iterator = uis.iterator();
185        while (iterator.hasNext())
186        {
187          ComponentUI ui = (ComponentUI) iterator.next();
188          ui.update(g, c);
189        }
190      }
191    
192      /**
193       * Calls the <code>paint(Graphics, JComponent)</code> method for all the UI
194       * delegates managed by this <code>MultiTextUI</code>.
195       *
196       * @param g  the graphics device.
197       * @param c  the component.
198       */
199      public void paint(Graphics g, JComponent c)
200      {
201        Iterator iterator = uis.iterator();
202        while (iterator.hasNext())
203        {
204          ComponentUI ui = (ComponentUI) iterator.next();
205          ui.paint(g, c);
206        }
207      }
208    
209      /**
210       * Calls the {@link ComponentUI#getPreferredSize(JComponent)} method for all
211       * the UI delegates managed by this <code>MultiTextUI</code>,
212       * returning the preferred size for the UI delegate from the primary look and
213       * feel.
214       *
215       * @param c  the component.
216       *
217       * @return The preferred size returned by the UI delegate from the primary
218       *         look and feel.
219       */
220      public Dimension getPreferredSize(JComponent c)
221      {
222        Dimension result = null;
223        Iterator iterator = uis.iterator();
224        // first UI delegate provides the return value
225        if (iterator.hasNext())
226          {
227            ComponentUI ui = (ComponentUI) iterator.next();
228            result = ui.getPreferredSize(c);
229          }
230        // return values from auxiliary UI delegates are ignored
231        while (iterator.hasNext())
232          {
233            ComponentUI ui = (ComponentUI) iterator.next();
234            /* Dimension ignored = */ ui.getPreferredSize(c);
235          }
236        return result;
237      }
238    
239      /**
240       * Calls the {@link ComponentUI#getMinimumSize(JComponent)} method for all
241       * the UI delegates managed by this <code>MultiTextUI</code>,
242       * returning the minimum size for the UI delegate from the primary look and
243       * feel.
244       *
245       * @param c  the component.
246       *
247       * @return The minimum size returned by the UI delegate from the primary
248       *         look and feel.
249       */
250      public Dimension getMinimumSize(JComponent c)
251      {
252        Dimension result = null;
253        Iterator iterator = uis.iterator();
254        // first UI delegate provides the return value
255        if (iterator.hasNext())
256          {
257            ComponentUI ui = (ComponentUI) iterator.next();
258            result = ui.getMinimumSize(c);
259          }
260        // return values from auxiliary UI delegates are ignored
261        while (iterator.hasNext())
262          {
263            ComponentUI ui = (ComponentUI) iterator.next();
264            /* Dimension ignored = */ ui.getMinimumSize(c);
265          }
266        return result;
267      }
268    
269      /**
270       * Calls the {@link ComponentUI#getMaximumSize(JComponent)} method for all
271       * the UI delegates managed by this <code>MultiTextUI</code>,
272       * returning the maximum size for the UI delegate from the primary look and
273       * feel.
274       *
275       * @param c  the component.
276       *
277       * @return The maximum size returned by the UI delegate from the primary
278       *         look and feel.
279       */
280      public Dimension getMaximumSize(JComponent c)
281      {
282        Dimension result = null;
283        Iterator iterator = uis.iterator();
284        // first UI delegate provides the return value
285        if (iterator.hasNext())
286          {
287            ComponentUI ui = (ComponentUI) iterator.next();
288            result = ui.getMaximumSize(c);
289          }
290        // return values from auxiliary UI delegates are ignored
291        while (iterator.hasNext())
292          {
293            ComponentUI ui = (ComponentUI) iterator.next();
294            /* Dimension ignored = */ ui.getMaximumSize(c);
295          }
296        return result;
297      }
298    
299      /**
300       * Calls the {@link ComponentUI#getAccessibleChildrenCount(JComponent)} method
301       * for all the UI delegates managed by this <code>MultiTextUI</code>,
302       * returning the count for the UI delegate from the primary look and
303       * feel.
304       *
305       * @param c  the component.
306       *
307       * @return The count returned by the UI delegate from the primary
308       *         look and feel.
309       */
310      public int getAccessibleChildrenCount(JComponent c)
311      {
312        int result = 0;
313        Iterator iterator = uis.iterator();
314        // first UI delegate provides the return value
315        if (iterator.hasNext())
316          {
317            ComponentUI ui = (ComponentUI) iterator.next();
318            result = ui.getAccessibleChildrenCount(c);
319          }
320        // return values from auxiliary UI delegates are ignored
321        while (iterator.hasNext())
322          {
323            ComponentUI ui = (ComponentUI) iterator.next();
324            /* int ignored = */ ui.getAccessibleChildrenCount(c);
325          }
326        return result;
327      }
328    
329      /**
330       * Calls the {@link ComponentUI#getAccessibleChild(JComponent, int)} method
331       * for all the UI delegates managed by this <code>MultiTextUI</code>,
332       * returning the child for the UI delegate from the primary look and
333       * feel.
334       *
335       * @param c  the component
336       * @param i  the child index.
337       *
338       * @return The child returned by the UI delegate from the primary
339       *         look and feel.
340       */
341      public Accessible getAccessibleChild(JComponent c, int i)
342      {
343        Accessible result = null;
344        Iterator iterator = uis.iterator();
345        // first UI delegate provides the return value
346        if (iterator.hasNext())
347          {
348            ComponentUI ui = (ComponentUI) iterator.next();
349            result = ui.getAccessibleChild(c, i);
350          }
351        // return values from auxiliary UI delegates are ignored
352        while (iterator.hasNext())
353          {
354            ComponentUI ui = (ComponentUI) iterator.next();
355            /* Accessible ignored = */ ui.getAccessibleChild(c, i);
356          }
357        return result;
358      }
359    
360      /**
361       * Calls the {@link TextUI#modelToView(JTextComponent, int)} method for all
362       * the UI delegates managed by this <code>MultiTextUI</code>,
363       * returning the bounds for the UI delegate from the primary look and
364       * feel.
365       *
366       * @param tc  the text component.
367       *
368       * @return The bounds returned by the UI delegate from the primary
369       *         look and feel.
370       */
371      public Rectangle modelToView(JTextComponent tc, int pos)
372          throws BadLocationException
373      {
374        Rectangle result = null;
375        Iterator iterator = uis.iterator();
376        // first UI delegate provides the return value
377        if (iterator.hasNext())
378          {
379            TextUI ui = (TextUI) iterator.next();
380            result = ui.modelToView(tc, pos);
381          }
382        // return values from auxiliary UI delegates are ignored
383        while (iterator.hasNext())
384          {
385            TextUI ui = (TextUI) iterator.next();
386            /* Rectangle ignored = */ ui.modelToView(tc, pos);
387          }
388        return result;
389      }
390    
391      /**
392       * Calls the {@link TextUI#modelToView(JTextComponent, int, Position.Bias)}
393       * method for all the UI delegates managed by this <code>MultiTextUI</code>,
394       * returning the bounds for the UI delegate from the primary look and
395       * feel.
396       *
397       * @param tc  the text component.
398       *
399       * @return The bounds returned by the UI delegate from the primary
400       *         look and feel.
401       */
402      public Rectangle modelToView(JTextComponent tc, int pos, Bias bias)
403              throws BadLocationException
404      {
405        Rectangle result = null;
406        Iterator iterator = uis.iterator();
407        // first UI delegate provides the return value
408        if (iterator.hasNext())
409          {
410            TextUI ui = (TextUI) iterator.next();
411            result = ui.modelToView(tc, pos, bias);
412          }
413        // return values from auxiliary UI delegates are ignored
414        while (iterator.hasNext())
415          {
416            TextUI ui = (TextUI) iterator.next();
417            /* Rectangle ignored = */ ui.modelToView(tc, pos, bias);
418          }
419        return result;
420      }
421    
422      /**
423       * Calls the {@link TextUI#viewToModel(JTextComponent, Point)} method for all
424       * the UI delegates managed by this <code>MultiTextUI</code>,
425       * returning the position for the UI delegate from the primary look and
426       * feel.
427       *
428       * @param t  the text component.
429       * @param pt  the point.
430       *
431       * @return The position returned by the UI delegate from the primary
432       *         look and feel.
433       */
434      public int viewToModel(JTextComponent t, Point pt)
435      {
436        int result = 0;
437        Iterator iterator = uis.iterator();
438        // first UI delegate provides the return value
439        if (iterator.hasNext())
440          {
441            TextUI ui = (TextUI) iterator.next();
442            result = ui.viewToModel(t, pt);
443          }
444        // return values from auxiliary UI delegates are ignored
445        while (iterator.hasNext())
446          {
447            TextUI ui = (TextUI) iterator.next();
448            /* int ignored = */ ui.viewToModel(t, pt);
449          }
450        return result;
451      }
452    
453      /**
454       * Calls the {@link TextUI#viewToModel(JTextComponent, Point, Bias[])} method
455       * for all the UI delegates managed by this <code>MultiTextUI</code>,
456       * returning the position for the UI delegate from the primary look and
457       * feel.
458       *
459       * @param tc  the text component.
460       *
461       * @return The position returned by the UI delegate from the primary
462       *         look and feel.
463       */
464      public int viewToModel(JTextComponent tc, Point loc, Bias[] outBias)
465      {
466        int result = 0;
467        Iterator iterator = uis.iterator();
468        // first UI delegate provides the return value
469        if (iterator.hasNext())
470          {
471            TextUI ui = (TextUI) iterator.next();
472            result = ui.viewToModel(tc, loc, outBias);
473          }
474        // return values from auxiliary UI delegates are ignored
475        while (iterator.hasNext())
476          {
477            TextUI ui = (TextUI) iterator.next();
478            /* int ignored = */ ui.viewToModel(tc, loc, outBias);
479          }
480        return result;
481      }
482    
483      /**
484       * Calls the {@link TextUI#getNextVisualPositionFrom(JTextComponent, int,
485       * Position.Bias, int, Position.Bias[])} method for all
486       * the UI delegates managed by this <code>MultiTextUI</code>,
487       * returning the position for the UI delegate from the primary look and
488       * feel.
489       *
490       * @param tc  the text component.
491       *
492       * @return The position returned by the UI delegate from the primary
493       *         look and feel.
494       */
495      public int getNextVisualPositionFrom(JTextComponent tc, int pos, Bias bias,
496              int direction, Bias[] outBias) throws BadLocationException
497      {
498        int result = 0;
499        Iterator iterator = uis.iterator();
500        // first UI delegate provides the return value
501        if (iterator.hasNext())
502          {
503            TextUI ui = (TextUI) iterator.next();
504            result = ui.getNextVisualPositionFrom(tc, pos, bias, direction,
505                    outBias);
506          }
507        // return values from auxiliary UI delegates are ignored
508        while (iterator.hasNext())
509          {
510            TextUI ui = (TextUI) iterator.next();
511            /* int ignored = */ ui.getNextVisualPositionFrom(tc, pos, bias,
512                direction, outBias);
513          }
514        return result;
515      }
516    
517      /**
518       * Calls the {@link TextUI#damageRange(JTextComponent, int, int)} method for
519       * all the UI delegates managed by this <code>MultiTextUI</code>.
520       *
521       * @param tc  the component.
522       * @param start  the start position.
523       * @param end  the end position.
524       */
525      public void damageRange(JTextComponent tc, int start, int end)
526      {
527        Iterator iterator = uis.iterator();
528        while (iterator.hasNext())
529        {
530          TextUI ui = (TextUI) iterator.next();
531          ui.damageRange(tc, start, end);
532        }
533      }
534    
535      /**
536       * Calls the {@link TextUI#damageRange(JTextComponent, int, int,
537       * Position.Bias, Position.Bias)} method for all the UI delegates managed by
538       * this <code>MultiTextUI</code>.
539       *
540       * @param tc  the component.
541       * @param start  the start position.
542       * @param end  the end position.
543       * @param startBias  the start bias.
544       * @param endBias  the end bias.
545       */
546      public void damageRange(JTextComponent tc, int start, int end,
547            Bias startBias, Bias endBias)
548      {
549        Iterator iterator = uis.iterator();
550        while (iterator.hasNext())
551        {
552          TextUI ui = (TextUI) iterator.next();
553          ui.damageRange(tc, start, end, startBias, endBias);
554        }
555      }
556    
557      /**
558       * Calls the {@link TextUI#getEditorKit(JTextComponent)} method for all
559       * the UI delegates managed by this <code>MultiTextUI</code>,
560       * returning the editor kit for the UI delegate from the primary look and
561       * feel.
562       *
563       * @param tc  the text component.
564       *
565       * @return The editor kit returned by the UI delegate from the primary
566       *         look and feel.
567       */
568      public EditorKit getEditorKit(JTextComponent tc)
569      {
570        EditorKit result = null;
571        Iterator iterator = uis.iterator();
572        // first UI delegate provides the return value
573        if (iterator.hasNext())
574          {
575            TextUI ui = (TextUI) iterator.next();
576            result = ui.getEditorKit(tc);
577          }
578        // return values from auxiliary UI delegates are ignored
579        while (iterator.hasNext())
580          {
581            TextUI ui = (TextUI) iterator.next();
582            /* EditorKit ignored = */ ui.getEditorKit(tc);
583          }
584        return result;
585      }
586    
587      /**
588       * Calls the {@link TextUI#getRootView(JTextComponent)} method for all
589       * the UI delegates managed by this <code>MultiTextUI</code>,
590       * returning the view for the UI delegate from the primary look and
591       * feel.
592       *
593       * @param tc  the text component.
594       *
595       * @return The view returned by the UI delegate from the primary
596       *         look and feel.
597       */
598      public View getRootView(JTextComponent tc)
599      {
600        View result = null;
601        Iterator iterator = uis.iterator();
602        // first UI delegate provides the return value
603        if (iterator.hasNext())
604          {
605            TextUI ui = (TextUI) iterator.next();
606            result = ui.getRootView(tc);
607          }
608        // return values from auxiliary UI delegates are ignored
609        while (iterator.hasNext())
610          {
611            TextUI ui = (TextUI) iterator.next();
612            /* View ignored = */ ui.getRootView(tc);
613          }
614        return result;
615      }
616    
617    }