OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicTextUI.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* BasicTextUI.java --
2
   Copyright (C) 2002, 2003, 2004, 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
 
39
package javax.swing.plaf.basic;
40
 
41
import java.awt.Color;
42
import java.awt.Container;
43
import java.awt.Dimension;
44
import java.awt.Graphics;
45
import java.awt.Insets;
46
import java.awt.Point;
47
import java.awt.Rectangle;
48
import java.awt.Shape;
49
import java.awt.event.FocusEvent;
50
import java.awt.event.FocusListener;
51
import java.beans.PropertyChangeEvent;
52
import java.beans.PropertyChangeListener;
53
 
54
import javax.swing.Action;
55
import javax.swing.ActionMap;
56
import javax.swing.InputMap;
57
import javax.swing.JComponent;
58
import javax.swing.LookAndFeel;
59
import javax.swing.SwingConstants;
60
import javax.swing.SwingUtilities;
61
import javax.swing.UIManager;
62
import javax.swing.event.DocumentEvent;
63
import javax.swing.event.DocumentListener;
64
import javax.swing.plaf.ActionMapUIResource;
65
import javax.swing.plaf.TextUI;
66
import javax.swing.plaf.UIResource;
67
import javax.swing.text.BadLocationException;
68
import javax.swing.text.Caret;
69
import javax.swing.text.DefaultCaret;
70
import javax.swing.text.DefaultEditorKit;
71
import javax.swing.text.DefaultHighlighter;
72
import javax.swing.text.Document;
73
import javax.swing.text.EditorKit;
74
import javax.swing.text.Element;
75
import javax.swing.text.Highlighter;
76
import javax.swing.text.JTextComponent;
77
import javax.swing.text.Keymap;
78
import javax.swing.text.Position;
79
import javax.swing.text.View;
80
import javax.swing.text.ViewFactory;
81
 
82
/**
83
 * The abstract base class from which the UI classes for Swings text
84
 * components are derived. This provides most of the functionality for
85
 * the UI classes.
86
 *
87
 * @author original author unknown
88
 * @author Roman Kennke (roman@kennke.org)
89
 */
90
public abstract class BasicTextUI extends TextUI
91
  implements ViewFactory
92
{
93
  /**
94
   * A {@link DefaultCaret} that implements {@link UIResource}.
95
   */
96
  public static class BasicCaret extends DefaultCaret implements UIResource
97
  {
98
    public BasicCaret()
99
    {
100
      // Nothing to do here.
101
    }
102
  }
103
 
104
  /**
105
   * A {@link DefaultHighlighter} that implements {@link UIResource}.
106
   */
107
  public static class BasicHighlighter extends DefaultHighlighter
108
    implements UIResource
109
  {
110
    public BasicHighlighter()
111
    {
112
      // Nothing to do here.
113
    }
114
  }
115
 
116
  /**
117
   * This view forms the root of the View hierarchy. However, it delegates
118
   * most calls to another View which is the real root of the hierarchy.
119
   * The purpose is to make sure that all Views in the hierarchy, including
120
   * the (real) root have a well-defined parent to which they can delegate
121
   * calls like {@link #preferenceChanged}, {@link #getViewFactory} and
122
   * {@link #getContainer}.
123
   */
124
  private class RootView extends View
125
  {
126
    /** The real root view. */
127
    private View view;
128
 
129
    /**
130
     * Creates a new RootView.
131
     */
132
    public RootView()
133
    {
134
      super(null);
135
    }
136
 
137
    /**
138
     * Returns the ViewFactory for this RootView. If the current EditorKit
139
     * provides a ViewFactory, this is used. Otherwise the TextUI itself
140
     * is returned as a ViewFactory.
141
     *
142
     * @return the ViewFactory for this RootView
143
     */
144
    public ViewFactory getViewFactory()
145
    {
146
      ViewFactory factory = null;
147
      EditorKit editorKit = BasicTextUI.this.getEditorKit(getComponent());
148
      factory = editorKit.getViewFactory();
149
      if (factory == null)
150
        factory = BasicTextUI.this;
151
      return factory;
152
    }
153
 
154
    /**
155
     * Indicates that the preferences of one of the child view has changed.
156
     * This calls revalidate on the text component.
157
     *
158
     * @param view the child view which's preference has changed
159
     * @param width <code>true</code> if the width preference has changed
160
     * @param height <code>true</code> if the height preference has changed
161
     */
162
    public void preferenceChanged(View view, boolean width, boolean height)
163
    {
164
      textComponent.revalidate();
165
    }
166
 
167
    /**
168
     * Sets the real root view.
169
     *
170
     * @param v the root view to set
171
     */
172
    public void setView(View v)
173
    {
174
      if (view != null)
175
        view.setParent(null);
176
 
177
      if (v != null)
178
        v.setParent(null);
179
 
180
      view = v;
181
    }
182
 
183
    /**
184
     * Returns the real root view, regardless of the index.
185
     *
186
     * @param index not used here
187
     *
188
     * @return the real root view, regardless of the index.
189
     */
190
    public View getView(int index)
191
    {
192
      return view;
193
    }
194
 
195
    /**
196
     * Returns <code>1</code> since the RootView always contains one
197
     * child, that is the real root of the View hierarchy.
198
     *
199
     * @return <code>1</code> since the RootView always contains one
200
     *         child, that is the real root of the View hierarchy
201
     */
202
    public int getViewCount()
203
    {
204
      if (view != null)
205
        return 1;
206
      else
207
        return 0;
208
    }
209
 
210
    /**
211
     * Returns the <code>Container</code> that contains this view. This
212
     * normally will be the text component that is managed by this TextUI.
213
     *
214
     * @return the <code>Container</code> that contains this view
215
     */
216
    public Container getContainer()
217
    {
218
      return textComponent;
219
    }
220
 
221
    /**
222
     * Returns the preferred span along the specified <code>axis</code>.
223
     * This is delegated to the real root view.
224
     *
225
     * @param axis the axis for which the preferred span is queried
226
     *
227
     * @return the preferred span along the axis
228
     */
229
    public float getPreferredSpan(int axis)
230
    {
231
      if (view != null)
232
        return view.getPreferredSpan(axis);
233
 
234
      return Integer.MAX_VALUE;
235
    }
236
 
237
    /**
238
     * Paints the view. This is delegated to the real root view.
239
     *
240
     * @param g the <code>Graphics</code> context to paint to
241
     * @param s the allocation for the View
242
     */
243
    public void paint(Graphics g, Shape s)
244
    {
245
      if (view != null)
246
        view.paint(g, s);
247
    }
248
 
249
 
250
    /**
251
     * Maps a position in the document into the coordinate space of the View.
252
     * The output rectangle usually reflects the font height but has a width
253
     * of zero.
254
     *
255
     * This is delegated to the real root view.
256
     *
257
     * @param position the position of the character in the model
258
     * @param a the area that is occupied by the view
259
     * @param bias either {@link Position.Bias#Forward} or
260
     *        {@link Position.Bias#Backward} depending on the preferred
261
     *        direction bias. If <code>null</code> this defaults to
262
     *        <code>Position.Bias.Forward</code>
263
     *
264
     * @return a rectangle that gives the location of the document position
265
     *         inside the view coordinate space
266
     *
267
     * @throws BadLocationException if <code>pos</code> is invalid
268
     * @throws IllegalArgumentException if b is not one of the above listed
269
     *         valid values
270
     */
271
    public Shape modelToView(int position, Shape a, Position.Bias bias)
272
      throws BadLocationException
273
    {
274
      return ((View) view).modelToView(position, a, bias);
275
    }
276
 
277
    /**
278
     * Maps coordinates from the <code>View</code>'s space into a position
279
     * in the document model.
280
     *
281
     * @param x the x coordinate in the view space
282
     * @param y the y coordinate in the view space
283
     * @param a the allocation of this <code>View</code>
284
     * @param b the bias to use
285
     *
286
     * @return the position in the document that corresponds to the screen
287
     *         coordinates <code>x, y</code>
288
     */
289
    public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
290
    {
291
      return view.viewToModel(x, y, a, b);
292
    }
293
 
294
    /**
295
     * Notification about text insertions. These are forwarded to the
296
     * real root view.
297
     *
298
     * @param ev the DocumentEvent describing the change
299
     * @param shape the current allocation of the view's display
300
     * @param vf the ViewFactory to use for creating new Views
301
     */
302
    public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
303
    {
304
      view.insertUpdate(ev, shape, vf);
305
    }
306
 
307
    /**
308
     * Notification about text removals. These are forwarded to the
309
     * real root view.
310
     *
311
     * @param ev the DocumentEvent describing the change
312
     * @param shape the current allocation of the view's display
313
     * @param vf the ViewFactory to use for creating new Views
314
     */
315
    public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
316
    {
317
      view.removeUpdate(ev, shape, vf);
318
    }
319
 
320
    /**
321
     * Notification about text changes. These are forwarded to the
322
     * real root view.
323
     *
324
     * @param ev the DocumentEvent describing the change
325
     * @param shape the current allocation of the view's display
326
     * @param vf the ViewFactory to use for creating new Views
327
     */
328
    public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
329
    {
330
      view.changedUpdate(ev, shape, vf);
331
    }
332
 
333
    /**
334
     * Returns the document position that is (visually) nearest to the given
335
     * document position <code>pos</code> in the given direction <code>d</code>.
336
     *
337
     * @param c the text component
338
     * @param pos the document position
339
     * @param b the bias for <code>pos</code>
340
     * @param d the direction, must be either {@link SwingConstants#NORTH},
341
     *        {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
342
     *        {@link SwingConstants#EAST}
343
     * @param biasRet an array of {@link Position.Bias} that can hold at least
344
     *        one element, which is filled with the bias of the return position
345
     *        on method exit
346
     *
347
     * @return the document position that is (visually) nearest to the given
348
     *         document position <code>pos</code> in the given direction
349
     *         <code>d</code>
350
     *
351
     * @throws BadLocationException if <code>pos</code> is not a valid offset in
352
     *         the document model
353
     */
354
    public int getNextVisualPositionFrom(JTextComponent c, int pos,
355
                                         Position.Bias b, int d,
356
                                         Position.Bias[] biasRet)
357
      throws BadLocationException
358
    {
359
      return view.getNextVisualPositionFrom(c, pos, b, d, biasRet);
360
    }
361
  }
362
 
363
  /**
364
   * Receives notifications when properties of the text component change.
365
   */
366
  class PropertyChangeHandler implements PropertyChangeListener
367
  {
368
    /**
369
     * Notifies when a property of the text component changes.
370
     *
371
     * @param event the PropertyChangeEvent describing the change
372
     */
373
    public void propertyChange(PropertyChangeEvent event)
374
    {
375
      if (event.getPropertyName().equals("document"))
376
        {
377
          // Document changed.
378
              modelChanged();
379
        }
380
 
381
      BasicTextUI.this.propertyChange(event);
382
    }
383
  }
384
 
385
  /**
386
   * Listens for changes on the underlying model and forwards notifications
387
   * to the View. This also updates the caret position of the text component.
388
   *
389
   * TODO: Maybe this should somehow be handled through EditorKits
390
   */
391
  class DocumentHandler implements DocumentListener
392
  {
393
    /**
394
     * Notification about a document change event.
395
     *
396
     * @param ev the DocumentEvent describing the change
397
     */
398
    public void changedUpdate(DocumentEvent ev)
399
    {
400
      rootView.changedUpdate(ev, getVisibleEditorRect(),
401
                             rootView.getViewFactory());
402
    }
403
 
404
    /**
405
     * Notification about a document insert event.
406
     *
407
     * @param ev the DocumentEvent describing the insertion
408
     */
409
    public void insertUpdate(DocumentEvent ev)
410
    {
411
      rootView.insertUpdate(ev, getVisibleEditorRect(),
412
                            rootView.getViewFactory());
413
    }
414
 
415
    /**
416
     * Notification about a document removal event.
417
     *
418
     * @param ev the DocumentEvent describing the removal
419
     */
420
    public void removeUpdate(DocumentEvent ev)
421
    {
422
      rootView.removeUpdate(ev, getVisibleEditorRect(),
423
                            rootView.getViewFactory());
424
    }
425
  }
426
 
427
  /**
428
   * The EditorKit used by this TextUI.
429
   */
430
  // FIXME: should probably be non-static.
431
  static EditorKit kit = new DefaultEditorKit();
432
 
433
  /**
434
   * The root view.
435
   */
436
  RootView rootView = new RootView();
437
 
438
  /**
439
   * The text component that we handle.
440
   */
441
  JTextComponent textComponent;
442
 
443
  /**
444
   * Receives notification when the model changes.
445
   */
446
  PropertyChangeHandler updateHandler = new PropertyChangeHandler();
447
 
448
  /** The DocumentEvent handler. */
449
  DocumentHandler documentHandler = new DocumentHandler();
450
 
451
  /**
452
   * The standard background color. This is the color which is used to paint
453
   * text in enabled text components.
454
   */
455
  Color background;
456
 
457
  /**
458
   * The inactive background color. This is the color which is used to paint
459
   * text in disabled text components.
460
   */
461
  Color inactiveBackground;
462
 
463
  /**
464
   * Creates a new <code>BasicTextUI</code> instance.
465
   */
466
  public BasicTextUI()
467
  {
468
    // Nothing to do here.
469
  }
470
 
471
  /**
472
   * Creates a {@link Caret} that should be installed into the text component.
473
   *
474
   * @return a caret that should be installed into the text component
475
   */
476
  protected Caret createCaret()
477
  {
478
    return new BasicCaret();
479
  }
480
 
481
  /**
482
   * Creates a {@link Highlighter} that should be installed into the text
483
   * component.
484
   *
485
   * @return a <code>Highlighter</code> for the text component
486
   */
487
  protected Highlighter createHighlighter()
488
  {
489
    return new BasicHighlighter();
490
  }
491
 
492
  /**
493
   * The text component that is managed by this UI.
494
   *
495
   * @return the text component that is managed by this UI
496
   */
497
  protected final JTextComponent getComponent()
498
  {
499
    return textComponent;
500
  }
501
 
502
  /**
503
   * Installs this UI on the text component.
504
   *
505
   * @param c the text component on which to install the UI
506
   */
507
  public void installUI(final JComponent c)
508
  {
509
    super.installUI(c);
510
    c.setOpaque(true);
511
 
512
    textComponent = (JTextComponent) c;
513
 
514
    Document doc = textComponent.getDocument();
515
    if (doc == null)
516
      {
517
        doc = getEditorKit(textComponent).createDefaultDocument();
518
        textComponent.setDocument(doc);
519
      }
520
 
521
    textComponent.addPropertyChangeListener(updateHandler);
522
    modelChanged();
523
 
524
    installDefaults();
525
    installListeners();
526
    installKeyboardActions();
527
  }
528
 
529
  /**
530
   * Installs UI defaults on the text components.
531
   */
532
  protected void installDefaults()
533
  {
534
    Caret caret = textComponent.getCaret();
535
    if (caret == null)
536
      {
537
        caret = createCaret();
538
        textComponent.setCaret(caret);
539
      }
540
 
541
    Highlighter highlighter = textComponent.getHighlighter();
542
    if (highlighter == null)
543
      textComponent.setHighlighter(createHighlighter());
544
 
545
    String prefix = getPropertyPrefix();
546
    LookAndFeel.installColorsAndFont(textComponent, prefix + ".background",
547
                                     prefix + ".foreground", prefix + ".font");
548
    LookAndFeel.installBorder(textComponent, prefix + ".border");
549
    textComponent.setMargin(UIManager.getInsets(prefix + ".margin"));
550
 
551
    caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate"));
552
 
553
    // Fetch the colors for enabled/disabled text components.
554
    background = UIManager.getColor(prefix + ".background");
555
    inactiveBackground = UIManager.getColor(prefix + ".inactiveBackground");
556
    textComponent.setDisabledTextColor
557
                         (UIManager.getColor(prefix + ".inactiveForeground"));
558
    textComponent.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground"));
559
    textComponent.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground"));
560
  }
561
 
562
  /**
563
   * This FocusListener triggers repaints on focus shift.
564
   */
565
  private FocusListener focuslistener = new FocusListener() {
566
      public void focusGained(FocusEvent e)
567
      {
568
        textComponent.repaint();
569
      }
570
      public void focusLost(FocusEvent e)
571
      {
572
        textComponent.repaint();
573
      }
574
    };
575
 
576
  /**
577
   * Install all listeners on the text component.
578
   */
579
  protected void installListeners()
580
  {
581
    textComponent.addFocusListener(focuslistener);
582
    installDocumentListeners();
583
  }
584
 
585
  /**
586
   * Installs the document listeners on the textComponent's model.
587
   */
588
  private void installDocumentListeners()
589
  {
590
    Document doc = textComponent.getDocument();
591
    if (doc != null)
592
      doc.addDocumentListener(documentHandler);
593
  }
594
 
595
  /**
596
   * Returns the name of the keymap for this type of TextUI.
597
   *
598
   * This is implemented so that the classname of this TextUI
599
   * without the package prefix is returned. This way subclasses
600
   * don't have to override this method.
601
   *
602
   * @return the name of the keymap for this TextUI
603
   */
604
  protected String getKeymapName()
605
  {
606
    String fullClassName = getClass().getName();
607
    int index = fullClassName.lastIndexOf('.');
608
    String className = fullClassName.substring(index + 1);
609
    return className;
610
  }
611
 
612
  /**
613
   * Creates the {@link Keymap} that is installed on the text component.
614
   *
615
   * @return the {@link Keymap} that is installed on the text component
616
   */
617
  protected Keymap createKeymap()
618
  {
619
    String prefix = getPropertyPrefix();
620
    JTextComponent.KeyBinding[] bindings =
621
      (JTextComponent.KeyBinding[]) UIManager.get(prefix + ".keyBindings");
622
    if (bindings == null)
623
      {
624
        bindings = new JTextComponent.KeyBinding[0];
625
        // FIXME: Putting something into the defaults map is certainly wrong.
626
        // Must be fixed somehow.
627
        UIManager.put(prefix + ".keyBindings", bindings);
628
      }
629
 
630
    Keymap km = JTextComponent.addKeymap(getKeymapName(),
631
                                         JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP));
632
    JTextComponent.loadKeymap(km, bindings, textComponent.getActions());
633
    return km;
634
  }
635
 
636
  /**
637
   * Installs the keyboard actions on the text components.
638
   */
639
  protected void installKeyboardActions()
640
  {
641
    // load any bindings for the older Keymap interface
642
    Keymap km = JTextComponent.getKeymap(getKeymapName());
643
    if (km == null)
644
      km = createKeymap();
645
    textComponent.setKeymap(km);
646
 
647
    // load any bindings for the newer InputMap / ActionMap interface
648
    SwingUtilities.replaceUIInputMap(textComponent,
649
                                     JComponent.WHEN_FOCUSED,
650
                                     getInputMap(JComponent.WHEN_FOCUSED));
651
    SwingUtilities.replaceUIActionMap(textComponent, getActionMap());
652
  }
653
 
654
  /**
655
   * Gets the input map for the specified <code>condition</code>.
656
   *
657
   * @param condition the condition for the InputMap
658
   *
659
   * @return the InputMap for the specified condition
660
   */
661
  InputMap getInputMap(int condition)
662
  {
663
    String prefix = getPropertyPrefix();
664
    switch (condition)
665
      {
666
      case JComponent.WHEN_IN_FOCUSED_WINDOW:
667
        // FIXME: is this the right string? nobody seems to use it.
668
        return (InputMap) UIManager.get(prefix + ".windowInputMap");
669
      case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
670
        return (InputMap) UIManager.get(prefix + ".ancestorInputMap");
671
      default:
672
      case JComponent.WHEN_FOCUSED:
673
        return (InputMap) UIManager.get(prefix + ".focusInputMap");
674
      }
675
  }
676
 
677
  /**
678
   * Returns the ActionMap to be installed on the text component.
679
   *
680
   * @return the ActionMap to be installed on the text component
681
   */
682
  // FIXME: The UIDefaults have no entries for .actionMap, so this should
683
  // be handled somehow different.
684
  ActionMap getActionMap()
685
  {
686
    String prefix = getPropertyPrefix();
687
    ActionMap am = (ActionMap) UIManager.get(prefix + ".actionMap");
688
    if (am == null)
689
      {
690
        am = createActionMap();
691
        // FIXME: Putting something in the UIDefaults map is certainly wrong.
692
        // However, the whole method seems wrong and must be replaced by
693
        // something that is less wrong.
694
        UIManager.put(prefix + ".actionMap", am);
695
      }
696
    return am;
697
  }
698
 
699
  /**
700
   * Creates an ActionMap to be installed on the text component.
701
   *
702
   * @return an ActionMap to be installed on the text component
703
   */
704
  ActionMap createActionMap()
705
  {
706
    Action[] actions = textComponent.getActions();
707
    ActionMap am = new ActionMapUIResource();
708
    for (int i = 0; i < actions.length; ++i)
709
      {
710
        String name = (String) actions[i].getValue(Action.NAME);
711
        if (name != null)
712
          am.put(name, actions[i]);
713
      }
714
    return am;
715
  }
716
 
717
  /**
718
   * Uninstalls this TextUI from the text component.
719
   *
720
   * @param component the text component to uninstall the UI from
721
   */
722
  public void uninstallUI(final JComponent component)
723
  {
724
    super.uninstallUI(component);
725
    rootView.setView(null);
726
 
727
    textComponent.removePropertyChangeListener(updateHandler);
728
 
729
    uninstallDefaults();
730
    uninstallListeners();
731
    uninstallKeyboardActions();
732
 
733
    textComponent = null;
734
  }
735
 
736
  /**
737
   * Uninstalls all default properties that have previously been installed by
738
   * this UI.
739
   */
740
  protected void uninstallDefaults()
741
  {
742
    // Do nothing here.
743
  }
744
 
745
  /**
746
   * Uninstalls all listeners that have previously been installed by
747
   * this UI.
748
   */
749
  protected void uninstallListeners()
750
  {
751
    textComponent.removeFocusListener(focuslistener);
752
    textComponent.getDocument().removeDocumentListener(documentHandler);
753
  }
754
 
755
  /**
756
   * Uninstalls all keyboard actions that have previously been installed by
757
   * this UI.
758
   */
759
  protected void uninstallKeyboardActions()
760
  {
761
    // FIXME: Uninstall keyboard actions here.
762
  }
763
 
764
  /**
765
   * Returns the property prefix by which the text component's UIDefaults
766
   * are looked up.
767
   *
768
   * @return the property prefix by which the text component's UIDefaults
769
   *     are looked up
770
   */
771
  protected abstract String getPropertyPrefix();
772
 
773
  /**
774
   * Returns the preferred size of the text component.
775
   *
776
   * @param c not used here
777
   *
778
   * @return the preferred size of the text component
779
   */
780
  public Dimension getPreferredSize(JComponent c)
781
  {
782
    View v = getRootView(textComponent);
783
 
784
    float w = v.getPreferredSpan(View.X_AXIS);
785
    float h = v.getPreferredSpan(View.Y_AXIS);
786
 
787
    return new Dimension((int) w, (int) h);
788
  }
789
 
790
  /**
791
   * Returns the maximum size for text components that use this UI.
792
   *
793
   * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE).
794
   *
795
   * @param c not used here
796
   *
797
   * @return the maximum size for text components that use this UI
798
   */
799
  public Dimension getMaximumSize(JComponent c)
800
  {
801
    // Sun's implementation returns Integer.MAX_VALUE here, so do we.
802
    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
803
  }
804
 
805
  /**
806
   * Returns the minimum size for text components. This returns the size
807
   * of the component's insets.
808
   *
809
   * @return the minimum size for text components
810
   */
811
  public Dimension getMinimumSize(JComponent c)
812
  {
813
    Insets i = c.getInsets();
814
    return new Dimension(i.left + i.right, i.top + i.bottom);
815
  }
816
 
817
  /**
818
   * Paints the text component.
819
   *
820
   * @param g the <code>Graphics</code> context to paint to
821
   * @param c not used here
822
   */
823
  public final void paint(Graphics g, JComponent c)
824
  {
825
    paintSafely(g);
826
  }
827
 
828
  /**
829
   * Actually performs the painting.
830
   *
831
   * @param g the <code>Graphics</code> context to paint to
832
   */
833
  protected void paintSafely(Graphics g)
834
  {
835
    Caret caret = textComponent.getCaret();
836
    Highlighter highlighter = textComponent.getHighlighter();
837
 
838
    if (textComponent.isOpaque())
839
      paintBackground(g);
840
 
841
    if (highlighter != null
842
        && textComponent.getSelectionStart() != textComponent.getSelectionEnd())
843
      highlighter.paint(g);
844
 
845
    rootView.paint(g, getVisibleEditorRect());
846
 
847
    if (caret != null && textComponent.hasFocus())
848
      caret.paint(g);
849
  }
850
 
851
  /**
852
   * Paints the background of the text component.
853
   *
854
   * @param g the <code>Graphics</code> context to paint to
855
   */
856
  protected void paintBackground(Graphics g)
857
  {
858
    // This method does nothing. All the background filling is done by the
859
    // ComponentUI update method. However, the method is called by paint
860
    // to provide a way for subclasses to draw something different (e.g.
861
    // background images etc) on the background.
862
  }
863
 
864
  /**
865
   * Marks the specified range inside the text component's model as
866
   * damaged and queues a repaint request.
867
   *
868
   * @param t the text component
869
   * @param p0 the start location inside the document model of the range that
870
   *        is damaged
871
   * @param p1 the end location inside the document model of the range that
872
   *        is damaged
873
   */
874
  public void damageRange(JTextComponent t, int p0, int p1)
875
  {
876
    damageRange(t, p0, p1, null, null);
877
  }
878
 
879
  /**
880
   * Marks the specified range inside the text component's model as
881
   * damaged and queues a repaint request. This variant of this method
882
   * allows a {@link Position.Bias} object to be specified for the start
883
   * and end location of the range.
884
   *
885
   * @param t the text component
886
   * @param p0 the start location inside the document model of the range that
887
   *        is damaged
888
   * @param p1 the end location inside the document model of the range that
889
   *        is damaged
890
   * @param firstBias the bias for the start location
891
   * @param secondBias the bias for the end location
892
   */
893
  public void damageRange(JTextComponent t, int p0, int p1,
894
                          Position.Bias firstBias, Position.Bias secondBias)
895
  {
896
    // TODO: Implement me.
897
  }
898
 
899
  /**
900
   * Returns the {@link EditorKit} used for the text component that is managed
901
   * by this UI.
902
   *
903
   * @param t the text component
904
   *
905
   * @return the {@link EditorKit} used for the text component that is managed
906
   *         by this UI
907
   */
908
  public EditorKit getEditorKit(JTextComponent t)
909
  {
910
    return kit;
911
  }
912
 
913
  /**
914
   * Gets the next position inside the document model that is visible on
915
   * screen, starting from <code>pos</code>.
916
   *
917
   * @param t the text component
918
   * @param pos the start positionn
919
   * @param b the bias for pos
920
   * @param direction the search direction
921
   * @param biasRet filled by the method to indicate the bias of the return
922
   *        value
923
   *
924
   * @return the next position inside the document model that is visible on
925
   *         screen
926
   */
927
  public int getNextVisualPositionFrom(JTextComponent t, int pos,
928
                                       Position.Bias b, int direction,
929
                                       Position.Bias[] biasRet)
930
    throws BadLocationException
931
  {
932
    return 0; // TODO: Implement me.
933
  }
934
 
935
  /**
936
   * Returns the root {@link View} of a text component.
937
   *
938
   * @return the root {@link View} of a text component
939
   */
940
  public View getRootView(JTextComponent t)
941
  {
942
    return rootView;
943
  }
944
 
945
  /**
946
   * Maps a position in the document into the coordinate space of the View.
947
   * The output rectangle usually reflects the font height but has a width
948
   * of zero. A bias of {@link Position.Bias#Forward} is used in this method.
949
   *
950
   * @param t the text component
951
   * @param pos the position of the character in the model
952
   *
953
   * @return a rectangle that gives the location of the document position
954
   *         inside the view coordinate space
955
   *
956
   * @throws BadLocationException if <code>pos</code> is invalid
957
   * @throws IllegalArgumentException if b is not one of the above listed
958
   *         valid values
959
   */
960
  public Rectangle modelToView(JTextComponent t, int pos)
961
    throws BadLocationException
962
  {
963
    return modelToView(t, pos, Position.Bias.Forward);
964
  }
965
 
966
  /**
967
   * Maps a position in the document into the coordinate space of the View.
968
   * The output rectangle usually reflects the font height but has a width
969
   * of zero.
970
   *
971
   * @param t the text component
972
   * @param pos the position of the character in the model
973
   * @param bias either {@link Position.Bias#Forward} or
974
   *        {@link Position.Bias#Backward} depending on the preferred
975
   *        direction bias. If <code>null</code> this defaults to
976
   *        <code>Position.Bias.Forward</code>
977
   *
978
   * @return a rectangle that gives the location of the document position
979
   *         inside the view coordinate space
980
   *
981
   * @throws BadLocationException if <code>pos</code> is invalid
982
   * @throws IllegalArgumentException if b is not one of the above listed
983
   *         valid values
984
   */
985
  public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
986
    throws BadLocationException
987
  {
988
    return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
989
  }
990
 
991
  /**
992
   * Maps a point in the <code>View</code> coordinate space to a position
993
   * inside a document model.
994
   *
995
   * @param t the text component
996
   * @param pt the point to be mapped
997
   *
998
   * @return the position inside the document model that corresponds to
999
   *     <code>pt</code>
1000
   */
1001
  public int viewToModel(JTextComponent t, Point pt)
1002
  {
1003
    return viewToModel(t, pt, null);
1004
  }
1005
 
1006
  /**
1007
   * Maps a point in the <code>View</code> coordinate space to a position
1008
   * inside a document model.
1009
   *
1010
   * @param t the text component
1011
   * @param pt the point to be mapped
1012
   * @param biasReturn filled in by the method to indicate the bias of the
1013
   *        return value
1014
   *
1015
   * @return the position inside the document model that corresponds to
1016
   *     <code>pt</code>
1017
   */
1018
  public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
1019
  {
1020
    return rootView.viewToModel(pt.x, pt.y, getVisibleEditorRect(), biasReturn);
1021
  }
1022
 
1023
  /**
1024
   * Creates a {@link View} for the specified {@link Element}.
1025
   *
1026
   * @param elem the <code>Element</code> to create a <code>View</code> for
1027
   *
1028
   * @see ViewFactory
1029
   */
1030
  public View create(Element elem)
1031
  {
1032
    // Subclasses have to implement this to get this functionality.
1033
    return null;
1034
  }
1035
 
1036
  /**
1037
   * Creates a {@link View} for the specified {@link Element}.
1038
   *
1039
   * @param elem the <code>Element</code> to create a <code>View</code> for
1040
   * @param p0 the start offset
1041
   * @param p1 the end offset
1042
   *
1043
   * @see ViewFactory
1044
   */
1045
  public View create(Element elem, int p0, int p1)
1046
  {
1047
    // Subclasses have to implement this to get this functionality.
1048
    return null;
1049
  }
1050
 
1051
  /**
1052
   * Returns the allocation to give the root view.
1053
   *
1054
   * @return the allocation to give the root view
1055
   *
1056
   * @specnote The allocation has nothing to do with visibility. According
1057
   *           to the specs the naming of this method is unfortunate and
1058
   *           has historical reasons
1059
   */
1060
  protected Rectangle getVisibleEditorRect()
1061
  {
1062
    JTextComponent textComponent = getComponent();
1063
    int width = textComponent.getWidth();
1064
    int height = textComponent.getHeight();
1065
 
1066
    if (width <= 0 || height <= 0)
1067
      return new Rectangle(0, 0, 0, 0);
1068
 
1069
    Insets insets = textComponent.getInsets();
1070
    return new Rectangle(insets.left, insets.top,
1071
                         width - insets.left - insets.right,
1072
                         height - insets.top - insets.bottom);
1073
  }
1074
 
1075
  /**
1076
   * Sets the root view for the text component.
1077
   *
1078
   * @param view the <code>View</code> to be set as root view
1079
   */
1080
  protected final void setView(View view)
1081
  {
1082
    rootView.setView(view);
1083
    view.setParent(rootView);
1084
    textComponent.revalidate();
1085
    textComponent.repaint();
1086
  }
1087
 
1088
  /**
1089
   * Indicates that the model of a text component has changed. This
1090
   * triggers a rebuild of the view hierarchy.
1091
   */
1092
  protected void modelChanged()
1093
  {
1094
    if (textComponent == null || rootView == null)
1095
      return;
1096
    ViewFactory factory = rootView.getViewFactory();
1097
    if (factory == null)
1098
      return;
1099
    Document doc = textComponent.getDocument();
1100
    if (doc == null)
1101
      return;
1102
    installDocumentListeners();
1103
    Element elem = doc.getDefaultRootElement();
1104
    if (elem == null)
1105
      return;
1106
    View view = factory.create(elem);
1107
    setView(view);
1108
  }
1109
 
1110
  /**
1111
   * Receives notification whenever one of the text component's bound
1112
   * properties changes. This default implementation does nothing.
1113
   * It is a hook that enables subclasses to react to property changes
1114
   * on the text component.
1115
   *
1116
   * @param ev the property change event
1117
   */
1118
  protected void propertyChange(PropertyChangeEvent ev)
1119
  {
1120
    // The default implementation does nothing.
1121
  }
1122
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.