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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicTextUI.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* BasicTextUI.java --
2
   Copyright (C) 2002, 2003, 2004, 2005, 2006  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 gnu.classpath.SystemProperties;
42
 
43
import java.awt.Color;
44
import java.awt.Container;
45
import java.awt.Dimension;
46
import java.awt.Graphics;
47
import java.awt.HeadlessException;
48
import java.awt.Insets;
49
import java.awt.Point;
50
import java.awt.Rectangle;
51
import java.awt.Shape;
52
import java.awt.Toolkit;
53
import java.awt.datatransfer.Clipboard;
54
import java.awt.datatransfer.StringSelection;
55
import java.awt.event.FocusEvent;
56
import java.awt.event.FocusListener;
57
import java.beans.PropertyChangeEvent;
58
import java.beans.PropertyChangeListener;
59
 
60
import javax.swing.Action;
61
import javax.swing.ActionMap;
62
import javax.swing.InputMap;
63
import javax.swing.JComponent;
64
import javax.swing.LookAndFeel;
65
import javax.swing.SwingConstants;
66
import javax.swing.SwingUtilities;
67
import javax.swing.TransferHandler;
68
import javax.swing.UIManager;
69
import javax.swing.event.DocumentEvent;
70
import javax.swing.event.DocumentListener;
71
import javax.swing.plaf.ActionMapUIResource;
72
import javax.swing.plaf.InputMapUIResource;
73
import javax.swing.plaf.TextUI;
74
import javax.swing.plaf.UIResource;
75
import javax.swing.text.AbstractDocument;
76
import javax.swing.text.AttributeSet;
77
import javax.swing.text.BadLocationException;
78
import javax.swing.text.Caret;
79
import javax.swing.text.DefaultCaret;
80
import javax.swing.text.DefaultEditorKit;
81
import javax.swing.text.DefaultHighlighter;
82
import javax.swing.text.Document;
83
import javax.swing.text.EditorKit;
84
import javax.swing.text.Element;
85
import javax.swing.text.Highlighter;
86
import javax.swing.text.JTextComponent;
87
import javax.swing.text.Keymap;
88
import javax.swing.text.Position;
89
import javax.swing.text.View;
90
import javax.swing.text.ViewFactory;
91
 
92
/**
93
 * The abstract base class from which the UI classes for Swings text
94
 * components are derived. This provides most of the functionality for
95
 * the UI classes.
96
 *
97
 * @author original author unknown
98
 * @author Roman Kennke (roman@kennke.org)
99
 */
100
public abstract class BasicTextUI extends TextUI
101
  implements ViewFactory
102
{
103
  /**
104
   * A {@link DefaultCaret} that implements {@link UIResource}.
105
   */
106
  public static class BasicCaret extends DefaultCaret implements UIResource
107
  {
108
    public BasicCaret()
109
    {
110
      // Nothing to do here.
111
    }
112
  }
113
 
114
  /**
115
   * A {@link DefaultHighlighter} that implements {@link UIResource}.
116
   */
117
  public static class BasicHighlighter extends DefaultHighlighter
118
    implements UIResource
119
  {
120
    public BasicHighlighter()
121
    {
122
      // Nothing to do here.
123
    }
124
  }
125
 
126
  private static class FocusHandler
127
    implements FocusListener
128
  {
129
    public void focusGained(FocusEvent e)
130
    {
131
      // Nothing to do here.
132
    }
133
    public void focusLost(FocusEvent e)
134
    {
135
      JTextComponent textComponent = (JTextComponent) e.getComponent();
136
      // Integrates Swing text components with the system clipboard:
137
      // The idea is that if one wants to copy text around X11-style
138
      // (select text and middle-click in the target component) the focus
139
      // will move to the new component which gives the old focus owner the
140
      // possibility to paste its selection into the clipboard.
141
      if (!e.isTemporary()
142
          && textComponent.getSelectionStart()
143
             != textComponent.getSelectionEnd())
144
        {
145
          SecurityManager sm = System.getSecurityManager();
146
          try
147
            {
148
              if (sm != null)
149
                sm.checkSystemClipboardAccess();
150
 
151
              Clipboard cb = Toolkit.getDefaultToolkit().getSystemSelection();
152
              if (cb != null)
153
                {
154
                  StringSelection selection = new StringSelection(
155
                      textComponent.getSelectedText());
156
                  cb.setContents(selection, selection);
157
                }
158
            }
159
          catch (SecurityException se)
160
            {
161
              // Not allowed to access the clipboard: Ignore and
162
              // do not access it.
163
            }
164
          catch (HeadlessException he)
165
            {
166
              // There is no AWT: Ignore and do not access the
167
              // clipboard.
168
            }
169
          catch (IllegalStateException ise)
170
          {
171
              // Clipboard is currently unavaible.
172
          }
173
        }
174
    }
175
  }
176
 
177
  /**
178
   * This FocusListener triggers repaints on focus shift.
179
   */
180
  private static FocusListener focusListener;
181
 
182
  /**
183
   * Receives notifications when properties of the text component change.
184
   */
185
  private class Handler
186
    implements PropertyChangeListener, DocumentListener
187
  {
188
    /**
189
     * Notifies when a property of the text component changes.
190
     *
191
     * @param event the PropertyChangeEvent describing the change
192
     */
193
    public void propertyChange(PropertyChangeEvent event)
194
    {
195
      if (event.getPropertyName().equals("document"))
196
        {
197
          // Document changed.
198
          Object oldValue = event.getOldValue();
199
          if (oldValue != null)
200
            {
201
              Document oldDoc = (Document) oldValue;
202
              oldDoc.removeDocumentListener(handler);
203
            }
204
          Object newValue = event.getNewValue();
205
          if (newValue != null)
206
            {
207
              Document newDoc = (Document) newValue;
208
              newDoc.addDocumentListener(handler);
209
            }
210
          modelChanged();
211
        }
212
 
213
      BasicTextUI.this.propertyChange(event);
214
    }
215
 
216
    /**
217
     * Notification about a document change event.
218
     *
219
     * @param ev the DocumentEvent describing the change
220
     */
221
    public void changedUpdate(DocumentEvent ev)
222
    {
223
      // Updates are forwarded to the View even if 'getVisibleEditorRect'
224
      // method returns null. This means the View classes have to be
225
      // aware of that possibility.
226
      rootView.changedUpdate(ev, getVisibleEditorRect(),
227
                             rootView.getViewFactory());
228
    }
229
 
230
    /**
231
     * Notification about a document insert event.
232
     *
233
     * @param ev the DocumentEvent describing the insertion
234
     */
235
    public void insertUpdate(DocumentEvent ev)
236
    {
237
      // Updates are forwarded to the View even if 'getVisibleEditorRect'
238
      // method returns null. This means the View classes have to be
239
      // aware of that possibility.
240
      rootView.insertUpdate(ev, getVisibleEditorRect(),
241
                            rootView.getViewFactory());
242
    }
243
 
244
    /**
245
     * Notification about a document removal event.
246
     *
247
     * @param ev the DocumentEvent describing the removal
248
     */
249
    public void removeUpdate(DocumentEvent ev)
250
    {
251
      // Updates are forwarded to the View even if 'getVisibleEditorRect'
252
      // method returns null. This means the View classes have to be
253
      // aware of that possibility.
254
      rootView.removeUpdate(ev, getVisibleEditorRect(),
255
                            rootView.getViewFactory());
256
    }
257
 
258
  }
259
 
260
  /**
261
   * This view forms the root of the View hierarchy. However, it delegates
262
   * most calls to another View which is the real root of the hierarchy.
263
   * The purpose is to make sure that all Views in the hierarchy, including
264
   * the (real) root have a well-defined parent to which they can delegate
265
   * calls like {@link #preferenceChanged}, {@link #getViewFactory} and
266
   * {@link #getContainer}.
267
   */
268
  private class RootView extends View
269
  {
270
    /** The real root view. */
271
    private View view;
272
 
273
    /**
274
     * Creates a new RootView.
275
     */
276
    public RootView()
277
    {
278
      super(null);
279
    }
280
 
281
    /**
282
     * Returns the ViewFactory for this RootView. If the current EditorKit
283
     * provides a ViewFactory, this is used. Otherwise the TextUI itself
284
     * is returned as a ViewFactory.
285
     *
286
     * @return the ViewFactory for this RootView
287
     */
288
    public ViewFactory getViewFactory()
289
    {
290
      ViewFactory factory = null;
291
      EditorKit editorKit = BasicTextUI.this.getEditorKit(getComponent());
292
      factory = editorKit.getViewFactory();
293
      if (factory == null)
294
        factory = BasicTextUI.this;
295
      return factory;
296
    }
297
 
298
    /**
299
     * Indicates that the preferences of one of the child view has changed.
300
     * This calls revalidate on the text component.
301
     *
302
     * @param v the child view which's preference has changed
303
     * @param width <code>true</code> if the width preference has changed
304
     * @param height <code>true</code> if the height preference has changed
305
     */
306
    public void preferenceChanged(View v, boolean width, boolean height)
307
    {
308
      textComponent.revalidate();
309
    }
310
 
311
    /**
312
     * Sets the real root view.
313
     *
314
     * @param v the root view to set
315
     */
316
    public void setView(View v)
317
    {
318
      if (view != null)
319
        view.setParent(null);
320
 
321
      if (v != null)
322
        v.setParent(this);
323
 
324
      view = v;
325
    }
326
 
327
    /**
328
     * Returns the real root view, regardless of the index.
329
     *
330
     * @param index not used here
331
     *
332
     * @return the real root view, regardless of the index.
333
     */
334
    public View getView(int index)
335
    {
336
      return view;
337
    }
338
 
339
    /**
340
     * Returns <code>1</code> since the RootView always contains one
341
     * child, that is the real root of the View hierarchy.
342
     *
343
     * @return <code>1</code> since the RootView always contains one
344
     *         child, that is the real root of the View hierarchy
345
     */
346
    public int getViewCount()
347
    {
348
      int count = 0;
349
      if (view != null)
350
        count = 1;
351
      return count;
352
    }
353
 
354
    /**
355
     * Returns the <code>Container</code> that contains this view. This
356
     * normally will be the text component that is managed by this TextUI.
357
     *
358
     * @return the <code>Container</code> that contains this view
359
     */
360
    public Container getContainer()
361
    {
362
      return textComponent;
363
    }
364
 
365
    /**
366
     * Sets the size of the renderer. This is synchronized because that
367
     * potentially triggers layout and we don't want more than one thread
368
     * playing with the layout information.
369
     */
370
    public synchronized void setSize(float w, float h)
371
    {
372
      if (view != null)
373
        view.setSize(w, h);
374
    }
375
 
376
    /**
377
     * Paints the view. This is delegated to the real root view.
378
     *
379
     * @param g the <code>Graphics</code> context to paint to
380
     * @param s the allocation for the View
381
     */
382
    public void paint(Graphics g, Shape s)
383
    {
384
      if (view != null)
385
        {
386
          Rectangle b = s instanceof Rectangle ? (Rectangle) s : s.getBounds();
387
          setSize(b.width, b.height);
388
          view.paint(g, s);
389
        }
390
    }
391
 
392
 
393
    /**
394
     * Maps a position in the document into the coordinate space of the View.
395
     * The output rectangle usually reflects the font height but has a width
396
     * of zero.
397
     *
398
     * This is delegated to the real root view.
399
     *
400
     * @param position the position of the character in the model
401
     * @param a the area that is occupied by the view
402
     * @param bias either {@link Position.Bias#Forward} or
403
     *        {@link Position.Bias#Backward} depending on the preferred
404
     *        direction bias. If <code>null</code> this defaults to
405
     *        <code>Position.Bias.Forward</code>
406
     *
407
     * @return a rectangle that gives the location of the document position
408
     *         inside the view coordinate space
409
     *
410
     * @throws BadLocationException if <code>pos</code> is invalid
411
     * @throws IllegalArgumentException if b is not one of the above listed
412
     *         valid values
413
     */
414
    public Shape modelToView(int position, Shape a, Position.Bias bias)
415
      throws BadLocationException
416
    {
417
      return view.modelToView(position, a, bias);
418
    }
419
 
420
    /**
421
     * Maps coordinates from the <code>View</code>'s space into a position
422
     * in the document model.
423
     *
424
     * @param x the x coordinate in the view space
425
     * @param y the y coordinate in the view space
426
     * @param a the allocation of this <code>View</code>
427
     * @param b the bias to use
428
     *
429
     * @return the position in the document that corresponds to the screen
430
     *         coordinates <code>x, y</code>
431
     */
432
    public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
433
    {
434
      return view.viewToModel(x, y, a, b);
435
    }
436
 
437
    /**
438
     * Notification about text insertions. These are forwarded to the
439
     * real root view.
440
     *
441
     * @param ev the DocumentEvent describing the change
442
     * @param shape the current allocation of the view's display
443
     * @param vf the ViewFactory to use for creating new Views
444
     */
445
    public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
446
    {
447
      if (view != null)
448
        view.insertUpdate(ev, shape, vf);
449
    }
450
 
451
    /**
452
     * Notification about text removals. These are forwarded to the
453
     * real root view.
454
     *
455
     * @param ev the DocumentEvent describing the change
456
     * @param shape the current allocation of the view's display
457
     * @param vf the ViewFactory to use for creating new Views
458
     */
459
    public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
460
    {
461
      if (view != null)
462
        view.removeUpdate(ev, shape, vf);
463
    }
464
 
465
    /**
466
     * Notification about text changes. These are forwarded to the
467
     * real root view.
468
     *
469
     * @param ev the DocumentEvent describing the change
470
     * @param shape the current allocation of the view's display
471
     * @param vf the ViewFactory to use for creating new Views
472
     */
473
    public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
474
    {
475
      if (view != null)
476
        view.changedUpdate(ev, shape, vf);
477
    }
478
 
479
    /**
480
     * Returns the document position that is (visually) nearest to the given
481
     * document position <code>pos</code> in the given direction <code>d</code>.
482
     *
483
     * @param pos the document position
484
     * @param b the bias for <code>pos</code>
485
     * @param a the allocation for the view
486
     * @param d the direction, must be either {@link SwingConstants#NORTH},
487
     *        {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or
488
     *        {@link SwingConstants#EAST}
489
     * @param biasRet an array of {@link Position.Bias} that can hold at least
490
     *        one element, which is filled with the bias of the return position
491
     *        on method exit
492
     *
493
     * @return the document position that is (visually) nearest to the given
494
     *         document position <code>pos</code> in the given direction
495
     *         <code>d</code>
496
     *
497
     * @throws BadLocationException if <code>pos</code> is not a valid offset in
498
     *         the document model
499
     */
500
    public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
501
                                         int d, Position.Bias[] biasRet)
502
      throws BadLocationException
503
    {
504
      return view.getNextVisualPositionFrom(pos, b, a, d, biasRet);
505
    }
506
 
507
    /**
508
     * Returns the startOffset of this view, which is always the beginning
509
     * of the document.
510
     *
511
     * @return the startOffset of this view
512
     */
513
    public int getStartOffset()
514
    {
515
      return 0;
516
    }
517
 
518
    /**
519
     * Returns the endOffset of this view, which is always the end
520
     * of the document.
521
     *
522
     * @return the endOffset of this view
523
     */
524
    public int getEndOffset()
525
    {
526
      return getDocument().getLength();
527
    }
528
 
529
    /**
530
     * Returns the document associated with this view.
531
     *
532
     * @return the document associated with this view
533
     */
534
    public Document getDocument()
535
    {
536
      return textComponent.getDocument();
537
    }
538
 
539
    /**
540
     * Returns the attributes, which is null for the RootView.
541
     */
542
    public AttributeSet getAttributes()
543
    {
544
      return null;
545
    }
546
 
547
    /**
548
     * Overridden to forward to the view.
549
     */
550
    public float getPreferredSpan(int axis)
551
    {
552
      // The RI returns 10 in the degenerate case.
553
      float span = 10;
554
      if (view != null)
555
        span = view.getPreferredSpan(axis);
556
      return span;
557
    }
558
 
559
    /**
560
     * Overridden to forward to the real view.
561
     */
562
    public float getMinimumSpan(int axis)
563
    {
564
      // The RI returns 10 in the degenerate case.
565
      float span = 10;
566
      if (view != null)
567
        span = view.getMinimumSpan(axis);
568
      return span;
569
    }
570
 
571
    /**
572
     * Overridden to return Integer.MAX_VALUE.
573
     */
574
    public float getMaximumSpan(int axis)
575
    {
576
      // The RI returns Integer.MAX_VALUE here, regardless of the real view's
577
      // maximum size.
578
      return Integer.MAX_VALUE;
579
    }
580
  }
581
 
582
  /**
583
   * The EditorKit used by this TextUI.
584
   */
585
  private static EditorKit kit;
586
 
587
  /**
588
   * The combined event handler for text components.
589
   *
590
   * This is package private to avoid accessor methods.
591
   */
592
  Handler handler;
593
 
594
  /**
595
   * The root view.
596
   *
597
   * This is package private to avoid accessor methods.
598
   */
599
  RootView rootView;
600
 
601
  /**
602
   * The text component that we handle.
603
   */
604
  JTextComponent textComponent;
605
 
606
  /**
607
   * Creates a new <code>BasicTextUI</code> instance.
608
   */
609
  public BasicTextUI()
610
  {
611
    // Nothing to do here.
612
  }
613
 
614
  /**
615
   * Creates a {@link Caret} that should be installed into the text component.
616
   *
617
   * @return a caret that should be installed into the text component
618
   */
619
  protected Caret createCaret()
620
  {
621
    return new BasicCaret();
622
  }
623
 
624
  /**
625
   * Creates a {@link Highlighter} that should be installed into the text
626
   * component.
627
   *
628
   * @return a <code>Highlighter</code> for the text component
629
   */
630
  protected Highlighter createHighlighter()
631
  {
632
    return new BasicHighlighter();
633
  }
634
 
635
  /**
636
   * The text component that is managed by this UI.
637
   *
638
   * @return the text component that is managed by this UI
639
   */
640
  protected final JTextComponent getComponent()
641
  {
642
    return textComponent;
643
  }
644
 
645
  /**
646
   * Installs this UI on the text component.
647
   *
648
   * @param c the text component on which to install the UI
649
   */
650
  public void installUI(final JComponent c)
651
  {
652
    textComponent = (JTextComponent) c;
653
 
654
    if (rootView == null)
655
      rootView = new RootView();
656
 
657
    installDefaults();
658
    installFixedDefaults();
659
 
660
    // These listeners must be installed outside of installListeners(),
661
    // because overriding installListeners() doesn't prevent installing
662
    // these in the RI, but overriding isntallUI() does.
663
    if (handler == null)
664
      handler = new Handler();
665
    textComponent.addPropertyChangeListener(handler);
666
    Document doc = textComponent.getDocument();
667
    if (doc == null)
668
      {
669
        // The Handler takes care of installing the necessary listeners
670
        // on the document here.
671
        doc = getEditorKit(textComponent).createDefaultDocument();
672
        textComponent.setDocument(doc);
673
      }
674
    else
675
      {
676
        // Must install the document listener.
677
        doc.addDocumentListener(handler);
678
        modelChanged();
679
      }
680
 
681
    installListeners();
682
    installKeyboardActions();
683
  }
684
 
685
  /**
686
   * Installs UI defaults on the text components.
687
   */
688
  protected void installDefaults()
689
  {
690
    String prefix = getPropertyPrefix();
691
    // Install the standard properties.
692
    LookAndFeel.installColorsAndFont(textComponent, prefix + ".background",
693
                                     prefix + ".foreground", prefix + ".font");
694
    LookAndFeel.installBorder(textComponent, prefix + ".border");
695
 
696
    // Some additional text component only properties.
697
    Color color = textComponent.getCaretColor();
698
    if (color == null || color instanceof UIResource)
699
      {
700
        color = UIManager.getColor(prefix + ".caretForeground");
701
        textComponent.setCaretColor(color);
702
      }
703
 
704
    // Fetch the colors for enabled/disabled text components.
705
    color = textComponent.getDisabledTextColor();
706
    if (color == null || color instanceof UIResource)
707
      {
708
        color = UIManager.getColor(prefix + ".inactiveForeground");
709
        textComponent.setDisabledTextColor(color);
710
      }
711
    color = textComponent.getSelectedTextColor();
712
    if (color == null || color instanceof UIResource)
713
      {
714
        color = UIManager.getColor(prefix  + ".selectionForeground");
715
        textComponent.setSelectedTextColor(color);
716
      }
717
    color = textComponent.getSelectionColor();
718
    if (color == null || color instanceof UIResource)
719
      {
720
        color = UIManager.getColor(prefix  + ".selectionBackground");
721
        textComponent.setSelectionColor(color);
722
      }
723
 
724
    Insets margin = textComponent.getMargin();
725
    if (margin == null || margin instanceof UIResource)
726
      {
727
        margin = UIManager.getInsets(prefix + ".margin");
728
        textComponent.setMargin(margin);
729
      }
730
 
731
  }
732
 
733
  /**
734
   * Installs defaults that can't be overridden by overriding
735
   * installDefaults().
736
   */
737
  private void installFixedDefaults()
738
  {
739
    String prefix = getPropertyPrefix();
740
    Caret caret = textComponent.getCaret();
741
    if (caret == null || caret instanceof UIResource)
742
      {
743
        caret = createCaret();
744
        textComponent.setCaret(caret);
745
        caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate"));
746
      }
747
 
748
    Highlighter highlighter = textComponent.getHighlighter();
749
    if (highlighter == null || highlighter instanceof UIResource)
750
      textComponent.setHighlighter(createHighlighter());
751
 
752
  }
753
 
754
  /**
755
   * Install all listeners on the text component.
756
   */
757
  protected void installListeners()
758
  {
759
    //
760
    if (SystemProperties.getProperty("gnu.swing.text.no-xlike-clipboard")
761
        == null)
762
      {
763
        if (focusListener == null)
764
          focusListener = new FocusHandler();
765
        textComponent.addFocusListener(focusListener);
766
      }
767
  }
768
 
769
  /**
770
   * Returns the name of the keymap for this type of TextUI.
771
   *
772
   * This is implemented so that the classname of this TextUI
773
   * without the package prefix is returned. This way subclasses
774
   * don't have to override this method.
775
   *
776
   * @return the name of the keymap for this TextUI
777
   */
778
  protected String getKeymapName()
779
  {
780
    String fullClassName = getClass().getName();
781
    int index = fullClassName.lastIndexOf('.');
782
    String className = fullClassName.substring(index + 1);
783
    return className;
784
  }
785
 
786
  /**
787
   * Creates the {@link Keymap} that is installed on the text component.
788
   *
789
   * @return the {@link Keymap} that is installed on the text component
790
   */
791
  protected Keymap createKeymap()
792
  {
793
    String keymapName = getKeymapName();
794
    Keymap keymap = JTextComponent.getKeymap(keymapName);
795
    if (keymap == null)
796
      {
797
        Keymap parentMap =
798
          JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
799
        keymap = JTextComponent.addKeymap(keymapName, parentMap);
800
        Object val = UIManager.get(getPropertyPrefix() + ".keyBindings");
801
        if (val != null && val instanceof JTextComponent.KeyBinding[])
802
          {
803
            JTextComponent.KeyBinding[] bindings =
804
              (JTextComponent.KeyBinding[]) val;
805
            JTextComponent.loadKeymap(keymap, bindings,
806
                                      getComponent().getActions());
807
          }
808
      }
809
    return keymap;
810
  }
811
 
812
  /**
813
   * Installs the keyboard actions on the text components.
814
   */
815
  protected void installKeyboardActions()
816
  {
817
    // This is only there for backwards compatibility.
818
    textComponent.setKeymap(createKeymap());
819
 
820
    // load any bindings for the newer InputMap / ActionMap interface
821
    SwingUtilities.replaceUIInputMap(textComponent, JComponent.WHEN_FOCUSED,
822
                                     getInputMap());
823
    SwingUtilities.replaceUIActionMap(textComponent, getActionMap());
824
  }
825
 
826
  /**
827
   * Creates an ActionMap to be installed on the text component.
828
   *
829
   * @return an ActionMap to be installed on the text component
830
   */
831
  private ActionMap getActionMap()
832
  {
833
    // Note: There are no .actionMap entries in the standard L&Fs. However,
834
    // with the RI it is possible to install action maps via such keys, so
835
    // we must load them too. It can be observed that when there is no
836
    // .actionMap entry in the UIManager, one gets installed after a text
837
    // component of that type has been loaded.
838
    String prefix = getPropertyPrefix();
839
    String amName = prefix + ".actionMap";
840
    ActionMap am = (ActionMap) UIManager.get(amName);
841
    if (am == null)
842
      {
843
        am = createActionMap();
844
        UIManager.put(amName, am);
845
      }
846
 
847
    ActionMap map = new ActionMapUIResource();
848
    map.setParent(am);
849
 
850
    return map;
851
  }
852
 
853
  /**
854
   * Creates a default ActionMap for text components that have no UI default
855
   * for this (the standard for the built-in L&Fs). The ActionMap is copied
856
   * from the text component's getActions() method.
857
   *
858
   * @returna default ActionMap
859
   */
860
  private ActionMap createActionMap()
861
  {
862
    ActionMap am = new ActionMapUIResource();
863
    Action[] actions = textComponent.getActions();
864
    for (int i = actions.length - 1; i >= 0; i--)
865
      {
866
        Action action = actions[i];
867
        am.put(action.getValue(Action.NAME), action);
868
      }
869
    // Add TransferHandler's actions here. They don't seem to be in the
870
    // JTextComponent's default actions, and I can't make up a better place
871
    // to add them.
872
    Action copyAction = TransferHandler.getCopyAction();
873
    am.put(copyAction.getValue(Action.NAME), copyAction);
874
    Action cutAction = TransferHandler.getCutAction();
875
    am.put(cutAction.getValue(Action.NAME), cutAction);
876
    Action pasteAction = TransferHandler.getPasteAction();
877
    am.put(pasteAction.getValue(Action.NAME), pasteAction);
878
 
879
    return am;
880
  }
881
 
882
  /**
883
   * Gets the input map for the specified <code>condition</code>.
884
   *
885
   * @return the InputMap for the specified condition
886
   */
887
  private InputMap getInputMap()
888
  {
889
    InputMap im = new InputMapUIResource();
890
    String prefix = getPropertyPrefix();
891
    InputMap shared =
892
      (InputMap) SharedUIDefaults.get(prefix + ".focusInputMap");
893
    if (shared != null)
894
      im.setParent(shared);
895
    return im;
896
  }
897
 
898
  /**
899
   * Uninstalls this TextUI from the text component.
900
   *
901
   * @param component the text component to uninstall the UI from
902
   */
903
  public void uninstallUI(final JComponent component)
904
  {
905
    textComponent.removePropertyChangeListener(handler);
906
    textComponent.getDocument().removeDocumentListener(handler);
907
    rootView.setView(null);
908
 
909
    uninstallDefaults();
910
    uninstallFixedDefaults();
911
    uninstallListeners();
912
    uninstallKeyboardActions();
913
 
914
    textComponent = null;
915
  }
916
 
917
  /**
918
   * Uninstalls all default properties that have previously been installed by
919
   * this UI.
920
   */
921
  protected void uninstallDefaults()
922
  {
923
    if (textComponent.getCaretColor() instanceof UIResource)
924
      textComponent.setCaretColor(null);
925
    if (textComponent.getSelectionColor() instanceof UIResource)
926
      textComponent.setSelectionColor(null);
927
    if (textComponent.getDisabledTextColor() instanceof UIResource)
928
      textComponent.setDisabledTextColor(null);
929
    if (textComponent.getSelectedTextColor() instanceof UIResource)
930
      textComponent.setSelectedTextColor(null);
931
    LookAndFeel.uninstallBorder(textComponent);
932
    if (textComponent.getMargin() instanceof UIResource)
933
      textComponent.setMargin(null);
934
  }
935
 
936
  /**
937
   * Uninstalls additional fixed defaults that were installed
938
   * by installFixedDefaults().
939
   */
940
  private void uninstallFixedDefaults()
941
  {
942
    if (textComponent.getCaret() instanceof UIResource)
943
      textComponent.setCaret(null);
944
    if (textComponent.getHighlighter() instanceof UIResource)
945
      textComponent.setHighlighter(null);
946
  }
947
 
948
  /**
949
   * Uninstalls all listeners that have previously been installed by
950
   * this UI.
951
   */
952
  protected void uninstallListeners()
953
  {
954
    // Don't nullify the focusListener field, as it is static and shared
955
    // between components.
956
    if (focusListener != null)
957
      textComponent.removeFocusListener(focusListener);
958
  }
959
 
960
  /**
961
   * Uninstalls all keyboard actions that have previously been installed by
962
   * this UI.
963
   */
964
  protected void uninstallKeyboardActions()
965
  {
966
    SwingUtilities.replaceUIInputMap(textComponent, JComponent.WHEN_FOCUSED,
967
                                     null);
968
    SwingUtilities.replaceUIActionMap(textComponent, null);
969
  }
970
 
971
  /**
972
   * Returns the property prefix by which the text component's UIDefaults
973
   * are looked up.
974
   *
975
   * @return the property prefix by which the text component's UIDefaults
976
   *     are looked up
977
   */
978
  protected abstract String getPropertyPrefix();
979
 
980
  /**
981
   * Returns the preferred size of the text component.
982
   *
983
   * @param c not used here
984
   *
985
   * @return the preferred size of the text component
986
   */
987
  public Dimension getPreferredSize(JComponent c)
988
  {
989
    Dimension d = c.getSize();
990
    Insets i = c.getInsets();
991
    // We need to lock here, since we require the view hierarchy to _not_
992
    // change in between.
993
    float w;
994
    float h;
995
    Document doc = textComponent.getDocument();
996
    if (doc instanceof AbstractDocument)
997
      ((AbstractDocument) doc).readLock();
998
    try
999
      {
1000
        if (d.width > (i.left + i.right) && d.height > (i.top + i.bottom))
1001
          {
1002
            rootView.setSize(d.width - i.left - i.right,
1003
                             d.height - i.top - i.bottom);
1004
          }
1005
        else
1006
          {
1007
            // Not laid out yet. Force some pseudo size.
1008
            rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
1009
          }
1010
        w = rootView.getPreferredSpan(View.X_AXIS);
1011
        h = rootView.getPreferredSpan(View.Y_AXIS);
1012
      }
1013
    finally
1014
      {
1015
        if (doc instanceof AbstractDocument)
1016
          ((AbstractDocument) doc).readUnlock();
1017
      }
1018
    Dimension size =  new Dimension((int) w + i.left + i.right,
1019
                         (int) h + i.top + i.bottom);
1020
    return size;
1021
  }
1022
 
1023
  /**
1024
   * Returns the maximum size for text components that use this UI.
1025
   *
1026
   * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE).
1027
   *
1028
   * @param c not used here
1029
   *
1030
   * @return the maximum size for text components that use this UI
1031
   */
1032
  public Dimension getMaximumSize(JComponent c)
1033
  {
1034
    Dimension d = new Dimension();
1035
    Insets i = c.getInsets();
1036
    Document doc = textComponent.getDocument();
1037
    // We need to lock here, since we require the view hierarchy to _not_
1038
    // change in between.
1039
    if (doc instanceof AbstractDocument)
1040
      ((AbstractDocument) doc).readLock();
1041
    try
1042
      {
1043
        // Check for overflow here.
1044
        d.width = (int) Math.min((long) rootView.getMaximumSpan(View.X_AXIS)
1045
                                 + i.left + i.right, Integer.MAX_VALUE);
1046
        d.height = (int) Math.min((long) rootView.getMaximumSpan(View.Y_AXIS)
1047
                                  + i.top + i.bottom, Integer.MAX_VALUE);
1048
      }
1049
    finally
1050
      {
1051
        if (doc instanceof AbstractDocument)
1052
          ((AbstractDocument) doc).readUnlock();
1053
      }
1054
    return d;
1055
  }
1056
 
1057
  /**
1058
   * Returns the minimum size for text components. This returns the size
1059
   * of the component's insets.
1060
   *
1061
   * @return the minimum size for text components
1062
   */
1063
  public Dimension getMinimumSize(JComponent c)
1064
  {
1065
    Dimension d = new Dimension();
1066
    Document doc = textComponent.getDocument();
1067
    // We need to lock here, since we require the view hierarchy to _not_
1068
    // change in between.
1069
    if (doc instanceof AbstractDocument)
1070
      ((AbstractDocument) doc).readLock();
1071
    try
1072
      {
1073
        d.width = (int) rootView.getMinimumSpan(View.X_AXIS);
1074
        d.height = (int) rootView.getMinimumSpan(View.Y_AXIS);
1075
      }
1076
    finally
1077
      {
1078
        if (doc instanceof AbstractDocument)
1079
          ((AbstractDocument) doc).readUnlock();
1080
      }
1081
    Insets i = c.getInsets();
1082
    d.width += i.left + i.right;
1083
    d.height += i.top + i.bottom;
1084
    return d;
1085
  }
1086
 
1087
  /**
1088
   * Paints the text component. This acquires a read lock on the model and then
1089
   * calls {@link #paintSafely(Graphics)} in order to actually perform the
1090
   * painting.
1091
   *
1092
   * @param g the <code>Graphics</code> context to paint to
1093
   * @param c not used here
1094
   */
1095
  public final void paint(Graphics g, JComponent c)
1096
  {
1097
    try
1098
      {
1099
        Document doc = textComponent.getDocument();
1100
        if (doc instanceof AbstractDocument)
1101
          {
1102
            AbstractDocument aDoc = (AbstractDocument) doc;
1103
            aDoc.readLock();
1104
          }
1105
        paintSafely(g);
1106
      }
1107
    finally
1108
      {
1109
        Document doc = textComponent.getDocument();
1110
        if (doc instanceof AbstractDocument)
1111
          {
1112
            AbstractDocument aDoc = (AbstractDocument) doc;
1113
            aDoc.readUnlock();
1114
          }
1115
      }
1116
  }
1117
 
1118
  /**
1119
   * This paints the text component while beeing sure that the model is not
1120
   * modified while painting.
1121
   *
1122
   * The following is performed in this order:
1123
   * <ol>
1124
   * <li>If the text component is opaque, the background is painted by
1125
   * calling {@link #paintBackground(Graphics)}.</li>
1126
   * <li>If there is a highlighter, the highlighter is painted.</li>
1127
   * <li>The view hierarchy is painted.</li>
1128
   * <li>The Caret is painter.</li>
1129
   * </ol>
1130
   *
1131
   * @param g the <code>Graphics</code> context to paint to
1132
   */
1133
  protected void paintSafely(Graphics g)
1134
  {
1135
    Caret caret = textComponent.getCaret();
1136
    Highlighter highlighter = textComponent.getHighlighter();
1137
 
1138
    if (textComponent.isOpaque())
1139
      paintBackground(g);
1140
 
1141
    // Try painting with the highlighter without checking whether there
1142
    // is a selection because a highlighter can be used to do more than
1143
    // marking selected text.
1144
    if (highlighter != null)
1145
      {
1146
        // Handle restoring of the color here to prevent
1147
        // drawing problems when the Highlighter implementor
1148
        // forgets to restore it.
1149
        Color oldColor = g.getColor();
1150
        highlighter.paint(g);
1151
        g.setColor(oldColor);
1152
      }
1153
 
1154
    rootView.paint(g, getVisibleEditorRect());
1155
 
1156
    if (caret != null && textComponent.hasFocus())
1157
      caret.paint(g);
1158
  }
1159
 
1160
  /**
1161
   * Paints the background of the text component.
1162
   *
1163
   * @param g the <code>Graphics</code> context to paint to
1164
   */
1165
  protected void paintBackground(Graphics g)
1166
  {
1167
    Color old = g.getColor();
1168
    g.setColor(textComponent.getBackground());
1169
    g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight());
1170
    g.setColor(old);
1171
  }
1172
 
1173
  /**
1174
   * Overridden for better control over background painting. This now simply
1175
   * calls {@link #paint} and this delegates the background painting to
1176
   * {@link #paintBackground}.
1177
   *
1178
   * @param g the graphics to use
1179
   * @param c the component to be painted
1180
   */
1181
  public void update(Graphics g, JComponent c)
1182
  {
1183
    paint(g, c);
1184
  }
1185
 
1186
  /**
1187
   * Marks the specified range inside the text component's model as
1188
   * damaged and queues a repaint request.
1189
   *
1190
   * @param t the text component
1191
   * @param p0 the start location inside the document model of the range that
1192
   *        is damaged
1193
   * @param p1 the end location inside the document model of the range that
1194
   *        is damaged
1195
   */
1196
  public void damageRange(JTextComponent t, int p0, int p1)
1197
  {
1198
    damageRange(t, p0, p1, Position.Bias.Forward, Position.Bias.Backward);
1199
  }
1200
 
1201
  /**
1202
   * Marks the specified range inside the text component's model as
1203
   * damaged and queues a repaint request. This variant of this method
1204
   * allows a {@link Position.Bias} object to be specified for the start
1205
   * and end location of the range.
1206
   *
1207
   * @param t the text component
1208
   * @param p0 the start location inside the document model of the range that
1209
   *        is damaged
1210
   * @param p1 the end location inside the document model of the range that
1211
   *        is damaged
1212
   * @param firstBias the bias for the start location
1213
   * @param secondBias the bias for the end location
1214
   */
1215
  public void damageRange(JTextComponent t, int p0, int p1,
1216
                          Position.Bias firstBias, Position.Bias secondBias)
1217
  {
1218
    Rectangle alloc = getVisibleEditorRect();
1219
    if (alloc != null)
1220
      {
1221
        Document doc = t.getDocument();
1222
 
1223
        // Acquire lock here to avoid structural changes in between.
1224
        if (doc instanceof AbstractDocument)
1225
          ((AbstractDocument) doc).readLock();
1226
        try
1227
          {
1228
            rootView.setSize(alloc.width, alloc.height);
1229
            Shape damage = rootView.modelToView(p0, firstBias, p1, secondBias,
1230
                                                alloc);
1231
            Rectangle r = damage instanceof Rectangle ? (Rectangle) damage
1232
                                                      : damage.getBounds();
1233
            textComponent.repaint(r.x, r.y, r.width, r.height);
1234
          }
1235
        catch (BadLocationException ex)
1236
          {
1237
            // Lets ignore this as it causes no serious problems.
1238
            // For debugging, comment this out.
1239
            // ex.printStackTrace();
1240
          }
1241
        finally
1242
          {
1243
            // Release lock.
1244
            if (doc instanceof AbstractDocument)
1245
              ((AbstractDocument) doc).readUnlock();
1246
          }
1247
      }
1248
  }
1249
 
1250
  /**
1251
   * Returns the {@link EditorKit} used for the text component that is managed
1252
   * by this UI.
1253
   *
1254
   * @param t the text component
1255
   *
1256
   * @return the {@link EditorKit} used for the text component that is managed
1257
   *         by this UI
1258
   */
1259
  public EditorKit getEditorKit(JTextComponent t)
1260
  {
1261
    if (kit == null)
1262
      kit = new DefaultEditorKit();
1263
    return kit;
1264
  }
1265
 
1266
  /**
1267
   * Gets the next position inside the document model that is visible on
1268
   * screen, starting from <code>pos</code>.
1269
   *
1270
   * @param t the text component
1271
   * @param pos the start positionn
1272
   * @param b the bias for pos
1273
   * @param direction the search direction
1274
   * @param biasRet filled by the method to indicate the bias of the return
1275
   *        value
1276
   *
1277
   * @return the next position inside the document model that is visible on
1278
   *         screen
1279
   */
1280
  public int getNextVisualPositionFrom(JTextComponent t, int pos,
1281
                                       Position.Bias b, int direction,
1282
                                       Position.Bias[] biasRet)
1283
    throws BadLocationException
1284
  {
1285
    int offset = -1;
1286
    Document doc = textComponent.getDocument();
1287
    if (doc instanceof AbstractDocument)
1288
      ((AbstractDocument) doc).readLock();
1289
    try
1290
      {
1291
        Rectangle alloc = getVisibleEditorRect();
1292
        if (alloc != null)
1293
          {
1294
            rootView.setSize(alloc.width, alloc.height);
1295
            offset = rootView.getNextVisualPositionFrom(pos, b, alloc,
1296
                                                        direction, biasRet);
1297
          }
1298
      }
1299
    finally
1300
      {
1301
        if (doc instanceof AbstractDocument)
1302
          ((AbstractDocument) doc).readUnlock();
1303
      }
1304
    return offset;
1305
  }
1306
 
1307
  /**
1308
   * Returns the root {@link View} of a text component.
1309
   *
1310
   * @return the root {@link View} of a text component
1311
   */
1312
  public View getRootView(JTextComponent t)
1313
  {
1314
    return rootView;
1315
  }
1316
 
1317
  /**
1318
   * Maps a position in the document into the coordinate space of the View.
1319
   * The output rectangle usually reflects the font height but has a width
1320
   * of zero. A bias of {@link Position.Bias#Forward} is used in this method.
1321
   *
1322
   * @param t the text component
1323
   * @param pos the position of the character in the model
1324
   *
1325
   * @return a rectangle that gives the location of the document position
1326
   *         inside the view coordinate space
1327
   *
1328
   * @throws BadLocationException if <code>pos</code> is invalid
1329
   * @throws IllegalArgumentException if b is not one of the above listed
1330
   *         valid values
1331
   */
1332
  public Rectangle modelToView(JTextComponent t, int pos)
1333
    throws BadLocationException
1334
  {
1335
    return modelToView(t, pos, Position.Bias.Forward);
1336
  }
1337
 
1338
  /**
1339
   * Maps a position in the document into the coordinate space of the View.
1340
   * The output rectangle usually reflects the font height but has a width
1341
   * of zero.
1342
   *
1343
   * @param t the text component
1344
   * @param pos the position of the character in the model
1345
   * @param bias either {@link Position.Bias#Forward} or
1346
   *        {@link Position.Bias#Backward} depending on the preferred
1347
   *        direction bias. If <code>null</code> this defaults to
1348
   *        <code>Position.Bias.Forward</code>
1349
   *
1350
   * @return a rectangle that gives the location of the document position
1351
   *         inside the view coordinate space
1352
   *
1353
   * @throws BadLocationException if <code>pos</code> is invalid
1354
   * @throws IllegalArgumentException if b is not one of the above listed
1355
   *         valid values
1356
   */
1357
  public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
1358
    throws BadLocationException
1359
  {
1360
    // We need to read-lock here because we depend on the document
1361
    // structure not beeing changed in between.
1362
    Document doc = textComponent.getDocument();
1363
    if (doc instanceof AbstractDocument)
1364
      ((AbstractDocument) doc).readLock();
1365
    Rectangle rect = null;
1366
    try
1367
      {
1368
        Rectangle r = getVisibleEditorRect();
1369
        if (r != null)
1370
          {
1371
            rootView.setSize(r.width, r.height);
1372
            Shape s = rootView.modelToView(pos, r, bias);
1373
            if (s != null)
1374
              rect = s.getBounds();
1375
          }
1376
      }
1377
    finally
1378
      {
1379
        if (doc instanceof AbstractDocument)
1380
          ((AbstractDocument) doc).readUnlock();
1381
      }
1382
    return rect;
1383
  }
1384
 
1385
  /**
1386
   * Maps a point in the <code>View</code> coordinate space to a position
1387
   * inside a document model.
1388
   *
1389
   * @param t the text component
1390
   * @param pt the point to be mapped
1391
   *
1392
   * @return the position inside the document model that corresponds to
1393
   *     <code>pt</code>
1394
   */
1395
  public int viewToModel(JTextComponent t, Point pt)
1396
  {
1397
    return viewToModel(t, pt, new Position.Bias[1]);
1398
  }
1399
 
1400
  /**
1401
   * Maps a point in the <code>View</code> coordinate space to a position
1402
   * inside a document model.
1403
   *
1404
   * @param t the text component
1405
   * @param pt the point to be mapped
1406
   * @param biasReturn filled in by the method to indicate the bias of the
1407
   *        return value
1408
   *
1409
   * @return the position inside the document model that corresponds to
1410
   *     <code>pt</code>
1411
   */
1412
  public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
1413
  {
1414
    int offset = -1;
1415
    Document doc = textComponent.getDocument();
1416
    if (doc instanceof AbstractDocument)
1417
      ((AbstractDocument) doc).readLock();
1418
    try
1419
      {
1420
        Rectangle alloc = getVisibleEditorRect();
1421
        if (alloc != null)
1422
          {
1423
            rootView.setSize(alloc.width, alloc.height);
1424
            offset = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn);
1425
          }
1426
      }
1427
    finally
1428
      {
1429
        if (doc instanceof AbstractDocument)
1430
          ((AbstractDocument) doc).readUnlock();
1431
      }
1432
    return offset;
1433
  }
1434
 
1435
  /**
1436
   * Creates a {@link View} for the specified {@link Element}.
1437
   *
1438
   * @param elem the <code>Element</code> to create a <code>View</code> for
1439
   *
1440
   * @see ViewFactory
1441
   */
1442
  public View create(Element elem)
1443
  {
1444
    // Subclasses have to implement this to get this functionality.
1445
    return null;
1446
  }
1447
 
1448
  /**
1449
   * Creates a {@link View} for the specified {@link Element}.
1450
   *
1451
   * @param elem the <code>Element</code> to create a <code>View</code> for
1452
   * @param p0 the start offset
1453
   * @param p1 the end offset
1454
   *
1455
   * @see ViewFactory
1456
   */
1457
  public View create(Element elem, int p0, int p1)
1458
  {
1459
    // Subclasses have to implement this to get this functionality.
1460
    return null;
1461
  }
1462
 
1463
  /**
1464
   * A cached Insets instance to be reused below.
1465
   */
1466
  private Insets cachedInsets;
1467
 
1468
  /**
1469
   * Returns the allocation to give the root view.
1470
   *
1471
   * @return the allocation to give the root view
1472
   *
1473
   * @specnote The allocation has nothing to do with visibility. According
1474
   *           to the specs the naming of this method is unfortunate and
1475
   *           has historical reasons
1476
   */
1477
  protected Rectangle getVisibleEditorRect()
1478
  {
1479
    int width = textComponent.getWidth();
1480
    int height = textComponent.getHeight();
1481
 
1482
    // Return null if the component has no valid size.
1483
    if (width <= 0 || height <= 0)
1484
      return null;
1485
 
1486
    Insets insets = textComponent.getInsets(cachedInsets);
1487
    return new Rectangle(insets.left, insets.top,
1488
                         width - insets.left - insets.right,
1489
                         height - insets.top - insets.bottom);
1490
  }
1491
 
1492
  /**
1493
   * Sets the root view for the text component.
1494
   *
1495
   * @param view the <code>View</code> to be set as root view
1496
   */
1497
  protected final void setView(View view)
1498
  {
1499
    rootView.setView(view);
1500
    textComponent.revalidate();
1501
    textComponent.repaint();
1502
  }
1503
 
1504
  /**
1505
   * Indicates that the model of a text component has changed. This
1506
   * triggers a rebuild of the view hierarchy.
1507
   */
1508
  protected void modelChanged()
1509
  {
1510
    if (textComponent == null || rootView == null)
1511
      return;
1512
    ViewFactory factory = rootView.getViewFactory();
1513
    if (factory == null)
1514
      return;
1515
    Document doc = textComponent.getDocument();
1516
    if (doc == null)
1517
      return;
1518
    Element elem = doc.getDefaultRootElement();
1519
    if (elem == null)
1520
      return;
1521
    View view = factory.create(elem);
1522
    setView(view);
1523
  }
1524
 
1525
  /**
1526
   * Receives notification whenever one of the text component's bound
1527
   * properties changes. This default implementation does nothing.
1528
   * It is a hook that enables subclasses to react to property changes
1529
   * on the text component.
1530
   *
1531
   * @param ev the property change event
1532
   */
1533
  protected void propertyChange(PropertyChangeEvent ev)
1534
  {
1535
    // The default implementation does nothing.
1536
  }
1537
 
1538
}

powered by: WebSVN 2.1.0

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