1 /* MultiTextUI.java --
2    Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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 package javax.swing.plaf.multi;
39 
40 import java.awt.Dimension;
41 import java.awt.Graphics;
42 import java.awt.Point;
43 import java.awt.Rectangle;
44 import java.util.Iterator;
45 import java.util.Vector;
46 
47 import javax.accessibility.Accessible;
48 import javax.swing.JComponent;
49 import javax.swing.LookAndFeel;
50 import javax.swing.UIManager;
51 import javax.swing.plaf.ComponentUI;
52 import javax.swing.plaf.TextUI;
53 import javax.swing.text.BadLocationException;
54 import javax.swing.text.EditorKit;
55 import javax.swing.text.JTextComponent;
56 import javax.swing.text.Position;
57 import javax.swing.text.View;
58 import javax.swing.text.Position.Bias;
59 
60 /**
61  * A UI delegate that that coordinates multiple {@link TextUI}
62  * instances, one from the primary look and feel, and one or more from the
63  * auxiliary look and feel(s).
64  *
65  * @see UIManager#addAuxiliaryLookAndFeel(LookAndFeel)
66  */
67 public class MultiTextUI extends TextUI
68 {
69 
70   /** A list of references to the actual component UIs. */
71   protected Vector uis;
72 
73   /**
74    * Creates a new <code>MultiTextUI</code> instance.
75    *
76    * @see #createUI(JComponent)
77    */
MultiTextUI()78   public MultiTextUI()
79   {
80     uis = new Vector();
81   }
82 
83   /**
84    * Creates a delegate object for the specified component.  If any auxiliary
85    * look and feels support this component, a <code>MultiTextUI</code> is
86    * returned, otherwise the UI from the default look and feel is returned.
87    *
88    * @param target  the component.
89    *
90    * @see MultiLookAndFeel#createUIs(ComponentUI, Vector, JComponent)
91    */
createUI(JComponent target)92   public static ComponentUI createUI(JComponent target)
93   {
94     MultiTextUI mui = new MultiTextUI();
95     return MultiLookAndFeel.createUIs(mui, mui.uis, target);
96   }
97 
98   /**
99    * 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    */
installUI(JComponent c)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    */
uninstallUI(JComponent c)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    */
getUIs()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    */
contains(JComponent c, int x, int y)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    */
update(Graphics g, JComponent c)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    */
paint(Graphics g, JComponent c)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    */
getPreferredSize(JComponent c)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    */
getMinimumSize(JComponent c)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    */
getMaximumSize(JComponent c)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    */
getAccessibleChildrenCount(JComponent c)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    */
getAccessibleChild(JComponent c, int i)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    */
modelToView(JTextComponent tc, int pos)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    */
modelToView(JTextComponent tc, int pos, Bias bias)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    */
viewToModel(JTextComponent t, Point pt)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    */
viewToModel(JTextComponent tc, Point loc, Bias[] outBias)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    */
getNextVisualPositionFrom(JTextComponent tc, int pos, Bias bias, int direction, Bias[] outBias)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    */
damageRange(JTextComponent tc, int start, int end)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    */
damageRange(JTextComponent tc, int start, int end, Bias startBias, Bias endBias)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    */
getEditorKit(JTextComponent tc)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    */
getRootView(JTextComponent tc)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 }
618