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)
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
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
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
;
83 * The abstract base class from which the UI classes for Swings text
84 * components are derived. This provides most of the functionality for
87 * @author original author unknown
88 * @author Roman Kennke (roman@kennke.org)
90 public abstract class BasicTextUI
extends TextUI
91 implements ViewFactory
94 * A {@link DefaultCaret} that implements {@link UIResource}.
96 public static class BasicCaret
extends DefaultCaret
implements UIResource
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. */
130 * Creates a new RootView.
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();
150 factory
= BasicTextUI
.this;
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
)
175 view
.setParent(null);
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
)
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()
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
)
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
)
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
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
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
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
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
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
347 * @return the document position that is (visually) nearest to the given
348 * document position <code>pos</code> in the given direction
351 * @throws BadLocationException if <code>pos</code> is not a valid offset in
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"))
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();
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.
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.
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
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
)
512 textComponent
= (JTextComponent
) c
;
514 Document doc
= textComponent
.getDocument();
517 doc
= getEditorKit(textComponent
).createDefaultDocument();
518 textComponent
.setDocument(doc
);
521 textComponent
.addPropertyChangeListener(updateHandler
);
526 installKeyboardActions();
530 * Installs UI defaults on the text components.
532 protected void installDefaults()
534 Caret caret
= textComponent
.getCaret();
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();
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);
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());
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());
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();
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");
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");
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
);
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
);
712 am
.put(name
, actions
[i
]);
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
);
730 uninstallListeners();
731 uninstallKeyboardActions();
733 textComponent
= null;
737 * Uninstalls all default properties that have previously been installed by
740 protected void uninstallDefaults()
746 * Uninstalls all listeners that have previously been installed by
749 protected void uninstallListeners()
751 textComponent
.removeFocusListener(focuslistener
);
752 textComponent
.getDocument().removeDocumentListener(documentHandler
);
756 * Uninstalls all keyboard actions that have previously been installed by
759 protected void uninstallKeyboardActions()
761 // FIXME: Uninstall keyboard actions here.
765 * Returns the property prefix by which the text component's UIDefaults
768 * @return the property prefix by which the text component's UIDefaults
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
)
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())
841 if (highlighter
!= null
842 && textComponent
.getSelectionStart() != textComponent
.getSelectionEnd())
843 highlighter
.paint(g
);
845 rootView
.paint(g
, getVisibleEditorRect());
847 if (caret
!= null && textComponent
.hasFocus())
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
871 * @param p1 the end location inside the document model of the range that
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
888 * @param p1 the end location inside the document model of the range that
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
903 * @param t the text component
905 * @return the {@link EditorKit} used for the text component that is managed
908 public EditorKit
getEditorKit(JTextComponent t
)
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
924 * @return the next position inside the document model that is visible on
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
)
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
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
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
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
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
1015 * @return the position inside the document model that corresponds to
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
1030 public View
create(Element elem
)
1032 // Subclasses have to implement this to get this functionality.
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
1045 public View
create(Element elem
, int p0
, int p1
)
1047 // Subclasses have to implement this to get this functionality.
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)
1096 ViewFactory factory
= rootView
.getViewFactory();
1097 if (factory
== null)
1099 Document doc
= textComponent
.getDocument();
1102 installDocumentListeners();
1103 Element elem
= doc
.getDefaultRootElement();
1106 View view
= factory
.create(elem
);
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.