2 Copyright (C) 2002, 2003, 2004 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., 59 Temple Place, Suite 330, 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.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
90 public static class BasicHighlighter extends DefaultHighlighter
93 public BasicHighlighter()
98 private class RootView extends View
107 public ViewFactory getViewFactory()
109 // FIXME: Handle EditorKit somehow.
110 return BasicTextUI.this;
113 public void setView(View v)
116 view.setParent(null);
124 public Container getContainer()
126 return textComponent;
129 public float getPreferredSpan(int axis)
132 return view.getPreferredSpan(axis);
134 return Integer.MAX_VALUE;
137 public void paint(Graphics g, Shape s)
143 protected Rectangle modelToView(int position, Shape a, Position.Bias bias)
144 throws BadLocationException
146 return ((PlainView) view).modelToView(position, a, bias).getBounds();
150 class UpdateHandler implements PropertyChangeListener
152 public void propertyChange(PropertyChangeEvent event)
154 if (event.getPropertyName().equals("document"))
162 static EditorKit kit = new DefaultEditorKit();
164 RootView rootView = new RootView();
165 JTextComponent textComponent;
166 UpdateHandler updateHandler = new UpdateHandler();
172 protected Caret createCaret()
174 return new BasicCaret();
177 protected Highlighter createHighlighter()
179 return new BasicHighlighter();
182 protected final JTextComponent getComponent()
184 return textComponent;
187 public void installUI(final JComponent c)
192 textComponent = (JTextComponent) c;
194 Document doc = textComponent.getDocument();
197 doc = getEditorKit(textComponent).createDefaultDocument();
198 textComponent.setDocument(doc);
201 textComponent.addPropertyChangeListener(updateHandler);
206 installKeyboardActions();
209 protected void installDefaults()
211 Caret caret = textComponent.getCaret();
214 caret = createCaret();
215 textComponent.setCaret(caret);
218 Highlighter highlighter = textComponent.getHighlighter();
219 if (highlighter == null)
220 textComponent.setHighlighter(createHighlighter());
222 String prefix = getPropertyPrefix();
223 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
224 textComponent.setBackground(defaults.getColor(prefix + ".background"));
225 textComponent.setForeground(defaults.getColor(prefix + ".foreground"));
226 textComponent.setMargin(defaults.getInsets(prefix + ".margin"));
227 textComponent.setBorder(defaults.getBorder(prefix + ".border"));
228 textComponent.setFont(defaults.getFont(prefix + ".font"));
230 caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate"));
233 private FocusListener focuslistener = new FocusListener() {
234 public void focusGained(FocusEvent e)
236 textComponent.repaint();
238 public void focusLost(FocusEvent e)
240 textComponent.repaint();
244 protected void installListeners()
246 textComponent.addFocusListener(focuslistener);
249 protected String getKeymapName()
251 return "BasicTextUI";
254 protected Keymap createKeymap()
256 String prefix = getPropertyPrefix();
257 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
258 JTextComponent.KeyBinding[] bindings =
259 (JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings");
260 Keymap km = JTextComponent.addKeymap(getKeymapName(),
261 JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP));
262 JTextComponent.loadKeymap(km, bindings, textComponent.getActions());
266 protected void installKeyboardActions()
268 // load any bindings for the older Keymap interface
269 Keymap km = JTextComponent.getKeymap(getKeymapName());
272 textComponent.setKeymap(km);
274 // load any bindings for the newer InputMap / ActionMap interface
275 SwingUtilities.replaceUIInputMap(textComponent,
276 JComponent.WHEN_FOCUSED,
277 getInputMap(JComponent.WHEN_FOCUSED));
278 SwingUtilities.replaceUIActionMap(textComponent, getActionMap());
281 InputMap getInputMap(int condition)
283 String prefix = getPropertyPrefix();
284 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
287 case JComponent.WHEN_IN_FOCUSED_WINDOW:
288 // FIXME: is this the right string? nobody seems to use it.
289 return (InputMap) defaults.get(prefix + ".windowInputMap");
290 case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
291 return (InputMap) defaults.get(prefix + ".ancestorInputMap");
293 case JComponent.WHEN_FOCUSED:
294 return (InputMap) defaults.get(prefix + ".focusInputMap");
298 ActionMap getActionMap()
300 String prefix = getPropertyPrefix();
301 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
302 ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap");
305 am = createActionMap();
306 defaults.put(prefix + ".actionMap", am);
311 ActionMap createActionMap()
313 Action[] actions = textComponent.getActions();
314 ActionMap am = new ActionMap();
315 for (int i = 0; i < actions.length; ++i)
317 String name = (String) actions[i].getValue(Action.NAME);
319 am.put(name, actions[i]);
324 public void uninstallUI(final JComponent component)
326 super.uninstallUI(component);
327 rootView.setView(null);
329 textComponent.removePropertyChangeListener(updateHandler);
330 textComponent = null;
333 uninstallListeners();
334 uninstallKeyboardActions();
337 protected void uninstallDefaults()
342 protected void uninstallListeners()
344 textComponent.removeFocusListener(focuslistener);
347 protected void uninstallKeyboardActions()
352 protected abstract String getPropertyPrefix();
354 public Dimension getPreferredSize(JComponent c)
356 View v = getRootView(textComponent);
358 float w = v.getPreferredSpan(View.X_AXIS);
359 float h = v.getPreferredSpan(View.Y_AXIS);
361 return new Dimension((int) w, (int) h);
364 public final void paint(Graphics g, JComponent c)
369 protected void paintSafely(Graphics g)
371 Caret caret = textComponent.getCaret();
372 Highlighter highlighter = textComponent.getHighlighter();
374 if (textComponent.isOpaque())
377 if (highlighter != null
378 && textComponent.getSelectionStart() != textComponent.getSelectionEnd())
379 highlighter.paint(g);
381 rootView.paint(g, getVisibleEditorRect());
383 if (caret != null && textComponent.hasFocus())
387 protected void paintBackground(Graphics g)
389 g.setColor(textComponent.getBackground());
390 g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight());
393 public void damageRange(JTextComponent t, int p0, int p1)
395 damageRange(t, p0, p1, null, null);
398 public void damageRange(JTextComponent t, int p0, int p1,
399 Position.Bias firstBias, Position.Bias secondBias)
403 public EditorKit getEditorKit(JTextComponent t)
408 public int getNextVisualPositionFrom(JTextComponent t, int pos,
409 Position.Bias b, int direction,
410 Position.Bias[] biasRet)
411 throws BadLocationException
416 public View getRootView(JTextComponent t)
421 public Rectangle modelToView(JTextComponent t, int pos)
422 throws BadLocationException
424 return modelToView(t, pos, Position.Bias.Forward);
427 public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
428 throws BadLocationException
430 return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
433 public int viewToModel(JTextComponent t, Point pt)
435 return viewToModel(t, pt, null);
438 public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
443 public View create(Element elem)
445 // subclasses have to implement this to get this functionality
449 public View create(Element elem, int p0, int p1)
451 // subclasses have to implement this to get this functionality
455 protected Rectangle getVisibleEditorRect()
457 int width = textComponent.getWidth();
458 int height = textComponent.getHeight();
460 if (width <= 0 || height <= 0)
463 Insets insets = textComponent.getInsets();
464 return new Rectangle(insets.left, insets.top,
465 width - insets.left + insets.right,
466 height - insets.top + insets.bottom);
469 protected final void setView(View view)
471 rootView.setView(view);
472 view.setParent(rootView);
475 protected void modelChanged()
477 if (textComponent == null || rootView == null)
479 ViewFactory factory = rootView.getViewFactory();
482 Document doc = textComponent.getDocument();
485 Element elem = doc.getDefaultRootElement();
488 setView(factory.create(elem));