001/* MultiTextUI.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.LookAndFeel;
050import javax.swing.UIManager;
051import javax.swing.plaf.ComponentUI;
052import javax.swing.plaf.TextUI;
053import javax.swing.text.BadLocationException;
054import javax.swing.text.EditorKit;
055import javax.swing.text.JTextComponent;
056import javax.swing.text.Position;
057import javax.swing.text.View;
058import 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 */
067public 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}