Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / javax / swing / plaf / basic / BasicTextUI.java
blobe8eeece3b328d52c7b5ea490793b293b83b3e94e
1 /* BasicTextUI.java --
2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package javax.swing.plaf.basic;
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;
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;
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.
87 * @author original author unknown
88 * @author Roman Kennke (roman@kennke.org)
90 public abstract class BasicTextUI extends TextUI
91 implements ViewFactory
93 /**
94 * A {@link DefaultCaret} that implements {@link UIResource}.
96 public static class BasicCaret extends DefaultCaret implements UIResource
98 public BasicCaret()
100 // Nothing to do here.
105 * A {@link DefaultHighlighter} that implements {@link UIResource}.
107 public static class BasicHighlighter extends DefaultHighlighter
108 implements UIResource
110 public BasicHighlighter()
112 // Nothing to do here.
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}.
124 private class RootView extends View
126 /** The real root view. */
127 private View view;
130 * Creates a new RootView.
132 public RootView()
134 super(null);
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.
142 * @return the ViewFactory for this RootView
144 public ViewFactory getViewFactory()
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;
155 * Indicates that the preferences of one of the child view has changed.
156 * This calls revalidate on the text component.
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
162 public void preferenceChanged(View view, boolean width, boolean height)
164 textComponent.revalidate();
168 * Sets the real root view.
170 * @param v the root view to set
172 public void setView(View v)
174 if (view != null)
175 view.setParent(null);
177 if (v != null)
178 v.setParent(null);
180 view = v;
184 * Returns the real root view, regardless of the index.
186 * @param index not used here
188 * @return the real root view, regardless of the index.
190 public View getView(int index)
192 return view;
196 * Returns <code>1</code> since the RootView always contains one
197 * child, that is the real root of the View hierarchy.
199 * @return <code>1</code> since the RootView always contains one
200 * child, that is the real root of the View hierarchy
202 public int getViewCount()
204 if (view != null)
205 return 1;
206 else
207 return 0;
211 * Returns the <code>Container</code> that contains this view. This
212 * normally will be the text component that is managed by this TextUI.
214 * @return the <code>Container</code> that contains this view
216 public Container getContainer()
218 return textComponent;
222 * Returns the preferred span along the specified <code>axis</code>.
223 * This is delegated to the real root view.
225 * @param axis the axis for which the preferred span is queried
227 * @return the preferred span along the axis
229 public float getPreferredSpan(int axis)
231 if (view != null)
232 return view.getPreferredSpan(axis);
234 return Integer.MAX_VALUE;
238 * Paints the view. This is delegated to the real root view.
240 * @param g the <code>Graphics</code> context to paint to
241 * @param s the allocation for the View
243 public void paint(Graphics g, Shape s)
245 if (view != null)
246 view.paint(g, s);
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.
255 * This is delegated to the real root view.
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>
264 * @return a rectangle that gives the location of the document position
265 * inside the view coordinate space
267 * @throws BadLocationException if <code>pos</code> is invalid
268 * @throws IllegalArgumentException if b is not one of the above listed
269 * valid values
271 public Shape modelToView(int position, Shape a, Position.Bias bias)
272 throws BadLocationException
274 return ((View) view).modelToView(position, a, bias);
278 * Maps coordinates from the <code>View</code>'s space into a position
279 * in the document model.
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
286 * @return the position in the document that corresponds to the screen
287 * coordinates <code>x, y</code>
289 public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
291 return view.viewToModel(x, y, a, b);
295 * Notification about text insertions. These are forwarded to the
296 * real root view.
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
302 public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
304 view.insertUpdate(ev, shape, vf);
308 * Notification about text removals. These are forwarded to the
309 * real root view.
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
315 public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
317 view.removeUpdate(ev, shape, vf);
321 * Notification about text changes. These are forwarded to the
322 * real root view.
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
328 public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
330 view.changedUpdate(ev, shape, vf);
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>.
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
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>
351 * @throws BadLocationException if <code>pos</code> is not a valid offset in
352 * the document model
354 public int getNextVisualPositionFrom(JTextComponent c, int pos,
355 Position.Bias b, int d,
356 Position.Bias[] biasRet)
357 throws BadLocationException
359 return view.getNextVisualPositionFrom(c, pos, b, d, biasRet);
364 * Receives notifications when properties of the text component change.
366 class PropertyChangeHandler implements PropertyChangeListener
369 * Notifies when a property of the text component changes.
371 * @param event the PropertyChangeEvent describing the change
373 public void propertyChange(PropertyChangeEvent event)
375 if (event.getPropertyName().equals("document"))
377 // Document changed.
378 modelChanged();
381 BasicTextUI.this.propertyChange(event);
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.
389 * TODO: Maybe this should somehow be handled through EditorKits
391 class DocumentHandler implements DocumentListener
394 * Notification about a document change event.
396 * @param ev the DocumentEvent describing the change
398 public void changedUpdate(DocumentEvent ev)
400 rootView.changedUpdate(ev, getVisibleEditorRect(),
401 rootView.getViewFactory());
405 * Notification about a document insert event.
407 * @param ev the DocumentEvent describing the insertion
409 public void insertUpdate(DocumentEvent ev)
411 rootView.insertUpdate(ev, getVisibleEditorRect(),
412 rootView.getViewFactory());
416 * Notification about a document removal event.
418 * @param ev the DocumentEvent describing the removal
420 public void removeUpdate(DocumentEvent ev)
422 rootView.removeUpdate(ev, getVisibleEditorRect(),
423 rootView.getViewFactory());
428 * The EditorKit used by this TextUI.
430 // FIXME: should probably be non-static.
431 static EditorKit kit = new DefaultEditorKit();
434 * The root view.
436 RootView rootView = new RootView();
439 * The text component that we handle.
441 JTextComponent textComponent;
444 * Receives notification when the model changes.
446 PropertyChangeHandler updateHandler = new PropertyChangeHandler();
448 /** The DocumentEvent handler. */
449 DocumentHandler documentHandler = new DocumentHandler();
452 * The standard background color. This is the color which is used to paint
453 * text in enabled text components.
455 Color background;
458 * The inactive background color. This is the color which is used to paint
459 * text in disabled text components.
461 Color inactiveBackground;
464 * Creates a new <code>BasicTextUI</code> instance.
466 public BasicTextUI()
468 // Nothing to do here.
472 * Creates a {@link Caret} that should be installed into the text component.
474 * @return a caret that should be installed into the text component
476 protected Caret createCaret()
478 return new BasicCaret();
482 * Creates a {@link Highlighter} that should be installed into the text
483 * component.
485 * @return a <code>Highlighter</code> for the text component
487 protected Highlighter createHighlighter()
489 return new BasicHighlighter();
493 * The text component that is managed by this UI.
495 * @return the text component that is managed by this UI
497 protected final JTextComponent getComponent()
499 return textComponent;
503 * Installs this UI on the text component.
505 * @param c the text component on which to install the UI
507 public void installUI(final JComponent c)
509 super.installUI(c);
510 c.setOpaque(true);
512 textComponent = (JTextComponent) c;
514 Document doc = textComponent.getDocument();
515 if (doc == null)
517 doc = getEditorKit(textComponent).createDefaultDocument();
518 textComponent.setDocument(doc);
521 textComponent.addPropertyChangeListener(updateHandler);
522 modelChanged();
524 installDefaults();
525 installListeners();
526 installKeyboardActions();
530 * Installs UI defaults on the text components.
532 protected void installDefaults()
534 Caret caret = textComponent.getCaret();
535 if (caret == null)
537 caret = createCaret();
538 textComponent.setCaret(caret);
541 Highlighter highlighter = textComponent.getHighlighter();
542 if (highlighter == null)
543 textComponent.setHighlighter(createHighlighter());
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"));
551 caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate"));
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"));
563 * This FocusListener triggers repaints on focus shift.
565 private FocusListener focuslistener = new FocusListener() {
566 public void focusGained(FocusEvent e)
568 textComponent.repaint();
570 public void focusLost(FocusEvent e)
572 textComponent.repaint();
577 * Install all listeners on the text component.
579 protected void installListeners()
581 textComponent.addFocusListener(focuslistener);
582 installDocumentListeners();
586 * Installs the document listeners on the textComponent's model.
588 private void installDocumentListeners()
590 Document doc = textComponent.getDocument();
591 if (doc != null)
592 doc.addDocumentListener(documentHandler);
596 * Returns the name of the keymap for this type of TextUI.
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.
602 * @return the name of the keymap for this TextUI
604 protected String getKeymapName()
606 String fullClassName = getClass().getName();
607 int index = fullClassName.lastIndexOf('.');
608 String className = fullClassName.substring(index + 1);
609 return className;
613 * Creates the {@link Keymap} that is installed on the text component.
615 * @return the {@link Keymap} that is installed on the text component
617 protected Keymap createKeymap()
619 String prefix = getPropertyPrefix();
620 JTextComponent.KeyBinding[] bindings =
621 (JTextComponent.KeyBinding[]) UIManager.get(prefix + ".keyBindings");
622 if (bindings == null)
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);
630 Keymap km = JTextComponent.addKeymap(getKeymapName(),
631 JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP));
632 JTextComponent.loadKeymap(km, bindings, textComponent.getActions());
633 return km;
637 * Installs the keyboard actions on the text components.
639 protected void installKeyboardActions()
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);
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());
655 * Gets the input map for the specified <code>condition</code>.
657 * @param condition the condition for the InputMap
659 * @return the InputMap for the specified condition
661 InputMap getInputMap(int condition)
663 String prefix = getPropertyPrefix();
664 switch (condition)
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");
678 * Returns the ActionMap to be installed on the text component.
680 * @return the ActionMap to be installed on the text component
682 // FIXME: The UIDefaults have no entries for .actionMap, so this should
683 // be handled somehow different.
684 ActionMap getActionMap()
686 String prefix = getPropertyPrefix();
687 ActionMap am = (ActionMap) UIManager.get(prefix + ".actionMap");
688 if (am == null)
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);
696 return am;
700 * Creates an ActionMap to be installed on the text component.
702 * @return an ActionMap to be installed on the text component
704 ActionMap createActionMap()
706 Action[] actions = textComponent.getActions();
707 ActionMap am = new ActionMapUIResource();
708 for (int i = 0; i < actions.length; ++i)
710 String name = (String) actions[i].getValue(Action.NAME);
711 if (name != null)
712 am.put(name, actions[i]);
714 return am;
718 * Uninstalls this TextUI from the text component.
720 * @param component the text component to uninstall the UI from
722 public void uninstallUI(final JComponent component)
724 super.uninstallUI(component);
725 rootView.setView(null);
727 textComponent.removePropertyChangeListener(updateHandler);
729 uninstallDefaults();
730 uninstallListeners();
731 uninstallKeyboardActions();
733 textComponent = null;
737 * Uninstalls all default properties that have previously been installed by
738 * this UI.
740 protected void uninstallDefaults()
742 // Do nothing here.
746 * Uninstalls all listeners that have previously been installed by
747 * this UI.
749 protected void uninstallListeners()
751 textComponent.removeFocusListener(focuslistener);
752 textComponent.getDocument().removeDocumentListener(documentHandler);
756 * Uninstalls all keyboard actions that have previously been installed by
757 * this UI.
759 protected void uninstallKeyboardActions()
761 // FIXME: Uninstall keyboard actions here.
765 * Returns the property prefix by which the text component's UIDefaults
766 * are looked up.
768 * @return the property prefix by which the text component's UIDefaults
769 * are looked up
771 protected abstract String getPropertyPrefix();
774 * Returns the preferred size of the text component.
776 * @param c not used here
778 * @return the preferred size of the text component
780 public Dimension getPreferredSize(JComponent c)
782 View v = getRootView(textComponent);
784 float w = v.getPreferredSpan(View.X_AXIS);
785 float h = v.getPreferredSpan(View.Y_AXIS);
787 return new Dimension((int) w, (int) h);
791 * Returns the maximum size for text components that use this UI.
793 * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE).
795 * @param c not used here
797 * @return the maximum size for text components that use this UI
799 public Dimension getMaximumSize(JComponent c)
801 // Sun's implementation returns Integer.MAX_VALUE here, so do we.
802 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
806 * Returns the minimum size for text components. This returns the size
807 * of the component's insets.
809 * @return the minimum size for text components
811 public Dimension getMinimumSize(JComponent c)
813 Insets i = c.getInsets();
814 return new Dimension(i.left + i.right, i.top + i.bottom);
818 * Paints the text component.
820 * @param g the <code>Graphics</code> context to paint to
821 * @param c not used here
823 public final void paint(Graphics g, JComponent c)
825 paintSafely(g);
829 * Actually performs the painting.
831 * @param g the <code>Graphics</code> context to paint to
833 protected void paintSafely(Graphics g)
835 Caret caret = textComponent.getCaret();
836 Highlighter highlighter = textComponent.getHighlighter();
838 if (textComponent.isOpaque())
839 paintBackground(g);
841 if (highlighter != null
842 && textComponent.getSelectionStart() != textComponent.getSelectionEnd())
843 highlighter.paint(g);
845 rootView.paint(g, getVisibleEditorRect());
847 if (caret != null && textComponent.hasFocus())
848 caret.paint(g);
852 * Paints the background of the text component.
854 * @param g the <code>Graphics</code> context to paint to
856 protected void paintBackground(Graphics g)
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.
865 * Marks the specified range inside the text component's model as
866 * damaged and queues a repaint request.
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
874 public void damageRange(JTextComponent t, int p0, int p1)
876 damageRange(t, p0, p1, null, null);
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.
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
893 public void damageRange(JTextComponent t, int p0, int p1,
894 Position.Bias firstBias, Position.Bias secondBias)
896 // TODO: Implement me.
900 * Returns the {@link EditorKit} used for the text component that is managed
901 * by this UI.
903 * @param t the text component
905 * @return the {@link EditorKit} used for the text component that is managed
906 * by this UI
908 public EditorKit getEditorKit(JTextComponent t)
910 return kit;
914 * Gets the next position inside the document model that is visible on
915 * screen, starting from <code>pos</code>.
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
924 * @return the next position inside the document model that is visible on
925 * screen
927 public int getNextVisualPositionFrom(JTextComponent t, int pos,
928 Position.Bias b, int direction,
929 Position.Bias[] biasRet)
930 throws BadLocationException
932 return 0; // TODO: Implement me.
936 * Returns the root {@link View} of a text component.
938 * @return the root {@link View} of a text component
940 public View getRootView(JTextComponent t)
942 return rootView;
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.
950 * @param t the text component
951 * @param pos the position of the character in the model
953 * @return a rectangle that gives the location of the document position
954 * inside the view coordinate space
956 * @throws BadLocationException if <code>pos</code> is invalid
957 * @throws IllegalArgumentException if b is not one of the above listed
958 * valid values
960 public Rectangle modelToView(JTextComponent t, int pos)
961 throws BadLocationException
963 return modelToView(t, pos, Position.Bias.Forward);
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.
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>
978 * @return a rectangle that gives the location of the document position
979 * inside the view coordinate space
981 * @throws BadLocationException if <code>pos</code> is invalid
982 * @throws IllegalArgumentException if b is not one of the above listed
983 * valid values
985 public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
986 throws BadLocationException
988 return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
992 * Maps a point in the <code>View</code> coordinate space to a position
993 * inside a document model.
995 * @param t the text component
996 * @param pt the point to be mapped
998 * @return the position inside the document model that corresponds to
999 * <code>pt</code>
1001 public int viewToModel(JTextComponent t, Point pt)
1003 return viewToModel(t, pt, null);
1007 * Maps a point in the <code>View</code> coordinate space to a position
1008 * inside a document model.
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
1015 * @return the position inside the document model that corresponds to
1016 * <code>pt</code>
1018 public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
1020 return rootView.viewToModel(pt.x, pt.y, getVisibleEditorRect(), biasReturn);
1024 * Creates a {@link View} for the specified {@link Element}.
1026 * @param elem the <code>Element</code> to create a <code>View</code> for
1028 * @see ViewFactory
1030 public View create(Element elem)
1032 // Subclasses have to implement this to get this functionality.
1033 return null;
1037 * Creates a {@link View} for the specified {@link Element}.
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
1043 * @see ViewFactory
1045 public View create(Element elem, int p0, int p1)
1047 // Subclasses have to implement this to get this functionality.
1048 return null;
1052 * Returns the allocation to give the root view.
1054 * @return the allocation to give the root view
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
1060 protected Rectangle getVisibleEditorRect()
1062 JTextComponent textComponent = getComponent();
1063 int width = textComponent.getWidth();
1064 int height = textComponent.getHeight();
1066 if (width <= 0 || height <= 0)
1067 return new Rectangle(0, 0, 0, 0);
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);
1076 * Sets the root view for the text component.
1078 * @param view the <code>View</code> to be set as root view
1080 protected final void setView(View view)
1082 rootView.setView(view);
1083 view.setParent(rootView);
1084 textComponent.revalidate();
1085 textComponent.repaint();
1089 * Indicates that the model of a text component has changed. This
1090 * triggers a rebuild of the view hierarchy.
1092 protected void modelChanged()
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);
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.
1116 * @param ev the property change event
1118 protected void propertyChange(PropertyChangeEvent ev)
1120 // The default implementation does nothing.