Merge from the pain train
[official-gcc.git] / libjava / javax / swing / plaf / basic / BasicTextUI.java
bloba94ca2bb420a8dbc30c3566c79c7b2bfc81accb6
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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.Container;
42 import java.awt.Dimension;
43 import java.awt.Graphics;
44 import java.awt.Insets;
45 import java.awt.Point;
46 import java.awt.Rectangle;
47 import java.awt.Shape;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.beans.PropertyChangeEvent;
51 import java.beans.PropertyChangeListener;
53 import javax.swing.Action;
54 import javax.swing.ActionMap;
55 import javax.swing.InputMap;
56 import javax.swing.JComponent;
57 import javax.swing.SwingUtilities;
58 import javax.swing.UIDefaults;
59 import javax.swing.UIManager;
60 import javax.swing.plaf.TextUI;
61 import javax.swing.plaf.UIResource;
62 import javax.swing.text.BadLocationException;
63 import javax.swing.text.Caret;
64 import javax.swing.text.DefaultCaret;
65 import javax.swing.text.DefaultEditorKit;
66 import javax.swing.text.DefaultHighlighter;
67 import javax.swing.text.Document;
68 import javax.swing.text.EditorKit;
69 import javax.swing.text.Element;
70 import javax.swing.text.Highlighter;
71 import javax.swing.text.JTextComponent;
72 import javax.swing.text.Keymap;
73 import javax.swing.text.PlainView;
74 import javax.swing.text.Position;
75 import javax.swing.text.View;
76 import javax.swing.text.ViewFactory;
79 public abstract class BasicTextUI extends TextUI
80 implements ViewFactory
82 public static class BasicCaret extends DefaultCaret
83 implements UIResource
85 public BasicCaret()
90 public static class BasicHighlighter extends DefaultHighlighter
91 implements UIResource
93 public BasicHighlighter()
98 private class RootView extends View
100 private View view;
102 public RootView()
104 super(null);
107 // View methods.
109 public ViewFactory getViewFactory()
111 // FIXME: Handle EditorKit somehow.
112 return BasicTextUI.this;
115 public void setView(View v)
117 if (view != null)
118 view.setParent(null);
120 if (v != null)
121 v.setParent(null);
123 view = v;
126 public Container getContainer()
128 return textComponent;
131 public float getPreferredSpan(int axis)
133 if (view != null)
134 return view.getPreferredSpan(axis);
136 return Integer.MAX_VALUE;
139 public void paint(Graphics g, Shape s)
141 if (view != null)
142 view.paint(g, s);
145 public Shape modelToView(int position, Shape a, Position.Bias bias)
146 throws BadLocationException
148 if (view == null)
149 return null;
151 return ((PlainView) view).modelToView(position, a, bias).getBounds();
155 class UpdateHandler implements PropertyChangeListener
157 public void propertyChange(PropertyChangeEvent event)
159 if (event.getPropertyName().equals("document"))
161 // Document changed.
162 modelChanged();
167 static EditorKit kit = new DefaultEditorKit();
169 RootView rootView = new RootView();
170 JTextComponent textComponent;
171 UpdateHandler updateHandler = new UpdateHandler();
173 public BasicTextUI()
177 protected Caret createCaret()
179 return new BasicCaret();
182 protected Highlighter createHighlighter()
184 return new BasicHighlighter();
187 protected final JTextComponent getComponent()
189 return textComponent;
192 public void installUI(final JComponent c)
194 super.installUI(c);
195 c.setOpaque(true);
197 textComponent = (JTextComponent) c;
199 Document doc = textComponent.getDocument();
200 if (doc == null)
202 doc = getEditorKit(textComponent).createDefaultDocument();
203 textComponent.setDocument(doc);
206 textComponent.addPropertyChangeListener(updateHandler);
207 modelChanged();
209 installDefaults();
210 installListeners();
211 installKeyboardActions();
214 protected void installDefaults()
216 Caret caret = textComponent.getCaret();
217 if (caret == null)
219 caret = createCaret();
220 textComponent.setCaret(caret);
223 Highlighter highlighter = textComponent.getHighlighter();
224 if (highlighter == null)
225 textComponent.setHighlighter(createHighlighter());
227 String prefix = getPropertyPrefix();
228 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
229 textComponent.setBackground(defaults.getColor(prefix + ".background"));
230 textComponent.setForeground(defaults.getColor(prefix + ".foreground"));
231 textComponent.setMargin(defaults.getInsets(prefix + ".margin"));
232 textComponent.setBorder(defaults.getBorder(prefix + ".border"));
233 textComponent.setFont(defaults.getFont(prefix + ".font"));
235 caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate"));
238 private FocusListener focuslistener = new FocusListener() {
239 public void focusGained(FocusEvent e)
241 textComponent.repaint();
243 public void focusLost(FocusEvent e)
245 textComponent.repaint();
249 protected void installListeners()
251 textComponent.addFocusListener(focuslistener);
254 protected String getKeymapName()
256 return "BasicTextUI";
259 protected Keymap createKeymap()
261 String prefix = getPropertyPrefix();
262 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
263 JTextComponent.KeyBinding[] bindings =
264 (JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings");
265 Keymap km = JTextComponent.addKeymap(getKeymapName(),
266 JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP));
267 JTextComponent.loadKeymap(km, bindings, textComponent.getActions());
268 return km;
271 protected void installKeyboardActions()
273 // load any bindings for the older Keymap interface
274 Keymap km = JTextComponent.getKeymap(getKeymapName());
275 if (km == null)
276 km = createKeymap();
277 textComponent.setKeymap(km);
279 // load any bindings for the newer InputMap / ActionMap interface
280 SwingUtilities.replaceUIInputMap(textComponent,
281 JComponent.WHEN_FOCUSED,
282 getInputMap(JComponent.WHEN_FOCUSED));
283 SwingUtilities.replaceUIActionMap(textComponent, getActionMap());
286 InputMap getInputMap(int condition)
288 String prefix = getPropertyPrefix();
289 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
290 switch (condition)
292 case JComponent.WHEN_IN_FOCUSED_WINDOW:
293 // FIXME: is this the right string? nobody seems to use it.
294 return (InputMap) defaults.get(prefix + ".windowInputMap");
295 case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
296 return (InputMap) defaults.get(prefix + ".ancestorInputMap");
297 default:
298 case JComponent.WHEN_FOCUSED:
299 return (InputMap) defaults.get(prefix + ".focusInputMap");
303 ActionMap getActionMap()
305 String prefix = getPropertyPrefix();
306 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
307 ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap");
308 if (am == null)
310 am = createActionMap();
311 defaults.put(prefix + ".actionMap", am);
313 return am;
316 ActionMap createActionMap()
318 Action[] actions = textComponent.getActions();
319 ActionMap am = new ActionMap();
320 for (int i = 0; i < actions.length; ++i)
322 String name = (String) actions[i].getValue(Action.NAME);
323 if (name != null)
324 am.put(name, actions[i]);
326 return am;
329 public void uninstallUI(final JComponent component)
331 super.uninstallUI(component);
332 rootView.setView(null);
334 textComponent.removePropertyChangeListener(updateHandler);
336 uninstallDefaults();
337 uninstallListeners();
338 uninstallKeyboardActions();
340 textComponent = null;
343 protected void uninstallDefaults()
345 // Do nothing here.
348 protected void uninstallListeners()
350 textComponent.removeFocusListener(focuslistener);
353 protected void uninstallKeyboardActions()
355 // Do nothing here.
358 protected abstract String getPropertyPrefix();
360 public Dimension getPreferredSize(JComponent c)
362 View v = getRootView(textComponent);
364 float w = v.getPreferredSpan(View.X_AXIS);
365 float h = v.getPreferredSpan(View.Y_AXIS);
367 return new Dimension((int) w, (int) h);
370 public final void paint(Graphics g, JComponent c)
372 paintSafely(g);
375 protected void paintSafely(Graphics g)
377 Caret caret = textComponent.getCaret();
378 Highlighter highlighter = textComponent.getHighlighter();
380 if (textComponent.isOpaque())
381 paintBackground(g);
383 if (highlighter != null
384 && textComponent.getSelectionStart() != textComponent.getSelectionEnd())
385 highlighter.paint(g);
387 rootView.paint(g, getVisibleEditorRect());
389 if (caret != null && textComponent.hasFocus())
390 caret.paint(g);
393 protected void paintBackground(Graphics g)
395 g.setColor(textComponent.getBackground());
396 g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight());
399 public void damageRange(JTextComponent t, int p0, int p1)
401 damageRange(t, p0, p1, null, null);
404 public void damageRange(JTextComponent t, int p0, int p1,
405 Position.Bias firstBias, Position.Bias secondBias)
409 public EditorKit getEditorKit(JTextComponent t)
411 return kit;
414 public int getNextVisualPositionFrom(JTextComponent t, int pos,
415 Position.Bias b, int direction,
416 Position.Bias[] biasRet)
417 throws BadLocationException
419 return 0;
422 public View getRootView(JTextComponent t)
424 return rootView;
427 public Rectangle modelToView(JTextComponent t, int pos)
428 throws BadLocationException
430 return modelToView(t, pos, Position.Bias.Forward);
433 public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
434 throws BadLocationException
436 return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
439 public int viewToModel(JTextComponent t, Point pt)
441 return viewToModel(t, pt, null);
444 public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
446 return 0;
449 public View create(Element elem)
451 // Subclasses have to implement this to get this functionality.
452 return null;
455 public View create(Element elem, int p0, int p1)
457 // Subclasses have to implement this to get this functionality.
458 return null;
461 protected Rectangle getVisibleEditorRect()
463 int width = textComponent.getWidth();
464 int height = textComponent.getHeight();
466 if (width <= 0 || height <= 0)
467 return null;
469 Insets insets = textComponent.getInsets();
470 return new Rectangle(insets.left, insets.top,
471 width - insets.left + insets.right,
472 height - insets.top + insets.bottom);
475 protected final void setView(View view)
477 rootView.setView(view);
478 view.setParent(rootView);
481 protected void modelChanged()
483 if (textComponent == null || rootView == null)
484 return;
485 ViewFactory factory = rootView.getViewFactory();
486 if (factory == null)
487 return;
488 Document doc = textComponent.getDocument();
489 if (doc == null)
490 return;
491 Element elem = doc.getDefaultRootElement();
492 if (elem == null)
493 return;
494 setView(factory.create(elem));