1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80:
81:
82: public abstract class BasicTextUI extends TextUI
83: implements ViewFactory
84: {
85: public static class BasicCaret extends DefaultCaret
86: implements UIResource
87: {
88: public BasicCaret()
89: {
90: }
91: }
92:
93: public static class BasicHighlighter extends DefaultHighlighter
94: implements UIResource
95: {
96: public BasicHighlighter()
97: {
98: }
99: }
100:
101: private class RootView extends View
102: {
103: private View view;
104:
105: public RootView()
106: {
107: super(null);
108: }
109:
110:
111:
112: public ViewFactory getViewFactory()
113: {
114:
115: return BasicTextUI.this;
116: }
117:
118: public void setView(View v)
119: {
120: if (view != null)
121: view.setParent(null);
122:
123: if (v != null)
124: v.setParent(null);
125:
126: view = v;
127: }
128:
129: public Container getContainer()
130: {
131: return textComponent;
132: }
133:
134: public float getPreferredSpan(int axis)
135: {
136: if (view != null)
137: return view.getPreferredSpan(axis);
138:
139: return Integer.MAX_VALUE;
140: }
141:
142: public void paint(Graphics g, Shape s)
143: {
144: if (view != null)
145: view.paint(g, s);
146: }
147:
148: public Shape modelToView(int position, Shape a, Position.Bias bias)
149: throws BadLocationException
150: {
151: if (view == null)
152: return null;
153:
154: return ((PlainView) view).modelToView(position, a, bias).getBounds();
155: }
156:
157:
165: public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
166: {
167: view.insertUpdate(ev, shape, vf);
168: }
169:
170:
178: public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
179: {
180: view.removeUpdate(ev, shape, vf);
181: }
182:
183:
191: public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
192: {
193: view.changedUpdate(ev, shape, vf);
194: }
195: }
196:
197: class UpdateHandler implements PropertyChangeListener
198: {
199: public void propertyChange(PropertyChangeEvent event)
200: {
201: if (event.getPropertyName().equals("document"))
202: {
203:
204: modelChanged();
205: }
206: }
207: }
208:
209:
215: class DocumentHandler implements DocumentListener
216: {
217:
222: public void changedUpdate(DocumentEvent ev)
223: {
224: Dimension size = textComponent.getSize();
225: rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height),
226: BasicTextUI.this);
227: }
228:
229:
234: public void insertUpdate(DocumentEvent ev)
235: {
236: Dimension size = textComponent.getSize();
237: rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height),
238: BasicTextUI.this);
239: int caretPos = textComponent.getCaretPosition();
240: if (caretPos >= ev.getOffset())
241: textComponent.setCaretPosition(caretPos + ev.getLength());
242: }
243:
244:
249: public void removeUpdate(DocumentEvent ev)
250: {
251: Dimension size = textComponent.getSize();
252: rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height),
253: BasicTextUI.this);
254: int caretPos = textComponent.getCaretPosition();
255: if (caretPos >= ev.getOffset())
256: textComponent.setCaretPosition(caretPos - ev.getLength());
257: }
258: }
259:
260: static EditorKit kit = new DefaultEditorKit();
261:
262: RootView rootView = new RootView();
263: JTextComponent textComponent;
264: UpdateHandler updateHandler = new UpdateHandler();
265:
266:
267: DocumentHandler documentHandler = new DocumentHandler();
268:
269: public BasicTextUI()
270: {
271: }
272:
273: protected Caret createCaret()
274: {
275: return new BasicCaret();
276: }
277:
278: protected Highlighter createHighlighter()
279: {
280: return new BasicHighlighter();
281: }
282:
283: protected final JTextComponent getComponent()
284: {
285: return textComponent;
286: }
287:
288: public void installUI(final JComponent c)
289: {
290: super.installUI(c);
291: c.setOpaque(true);
292:
293: textComponent = (JTextComponent) c;
294:
295: Document doc = textComponent.getDocument();
296: if (doc == null)
297: {
298: doc = getEditorKit(textComponent).createDefaultDocument();
299: textComponent.setDocument(doc);
300: }
301:
302: textComponent.addPropertyChangeListener(updateHandler);
303: modelChanged();
304:
305: installDefaults();
306: installListeners();
307: installKeyboardActions();
308: }
309:
310: protected void installDefaults()
311: {
312: Caret caret = textComponent.getCaret();
313: if (caret == null)
314: {
315: caret = createCaret();
316: textComponent.setCaret(caret);
317: }
318:
319: Highlighter highlighter = textComponent.getHighlighter();
320: if (highlighter == null)
321: textComponent.setHighlighter(createHighlighter());
322:
323: String prefix = getPropertyPrefix();
324: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
325: textComponent.setBackground(defaults.getColor(prefix + ".background"));
326: textComponent.setForeground(defaults.getColor(prefix + ".foreground"));
327: textComponent.setMargin(defaults.getInsets(prefix + ".margin"));
328: textComponent.setBorder(defaults.getBorder(prefix + ".border"));
329: textComponent.setFont(defaults.getFont(prefix + ".font"));
330:
331: caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate"));
332: }
333:
334: private FocusListener focuslistener = new FocusListener() {
335: public void focusGained(FocusEvent e)
336: {
337: textComponent.repaint();
338: }
339: public void focusLost(FocusEvent e)
340: {
341: textComponent.repaint();
342: }
343: };
344:
345: protected void installListeners()
346: {
347: textComponent.addFocusListener(focuslistener);
348: installDocumentListeners();
349: }
350:
351:
354: private void installDocumentListeners()
355: {
356: Document doc = textComponent.getDocument();
357: if (doc != null)
358: doc.addDocumentListener(documentHandler);
359: }
360:
361:
370: protected String getKeymapName()
371: {
372: String fullClassName = getClass().getName();
373: int index = fullClassName.lastIndexOf('.');
374: String className = fullClassName.substring(index + 1);
375: return className;
376: }
377:
378: protected Keymap createKeymap()
379: {
380: String prefix = getPropertyPrefix();
381: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
382: JTextComponent.KeyBinding[] bindings =
383: (JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings");
384: if (bindings == null)
385: {
386: bindings = new JTextComponent.KeyBinding[0];
387: defaults.put(prefix + ".keyBindings", bindings);
388: }
389:
390: Keymap km = JTextComponent.addKeymap(getKeymapName(),
391: JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP));
392: JTextComponent.loadKeymap(km, bindings, textComponent.getActions());
393: return km;
394: }
395:
396: protected void installKeyboardActions()
397: {
398:
399: Keymap km = JTextComponent.getKeymap(getKeymapName());
400: if (km == null)
401: km = createKeymap();
402: textComponent.setKeymap(km);
403:
404:
405: SwingUtilities.replaceUIInputMap(textComponent,
406: JComponent.WHEN_FOCUSED,
407: getInputMap(JComponent.WHEN_FOCUSED));
408: SwingUtilities.replaceUIActionMap(textComponent, getActionMap());
409: }
410:
411: InputMap getInputMap(int condition)
412: {
413: String prefix = getPropertyPrefix();
414: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
415: switch (condition)
416: {
417: case JComponent.WHEN_IN_FOCUSED_WINDOW:
418:
419: return (InputMap) defaults.get(prefix + ".windowInputMap");
420: case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
421: return (InputMap) defaults.get(prefix + ".ancestorInputMap");
422: default:
423: case JComponent.WHEN_FOCUSED:
424: return (InputMap) defaults.get(prefix + ".focusInputMap");
425: }
426: }
427:
428: ActionMap getActionMap()
429: {
430: String prefix = getPropertyPrefix();
431: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
432: ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap");
433: if (am == null)
434: {
435: am = createActionMap();
436: defaults.put(prefix + ".actionMap", am);
437: }
438: return am;
439: }
440:
441: ActionMap createActionMap()
442: {
443: Action[] actions = textComponent.getActions();
444: ActionMap am = new ActionMapUIResource();
445: for (int i = 0; i < actions.length; ++i)
446: {
447: String name = (String) actions[i].getValue(Action.NAME);
448: if (name != null)
449: am.put(name, actions[i]);
450: }
451: return am;
452: }
453:
454: public void uninstallUI(final JComponent component)
455: {
456: super.uninstallUI(component);
457: rootView.setView(null);
458:
459: textComponent.removePropertyChangeListener(updateHandler);
460:
461: uninstallDefaults();
462: uninstallListeners();
463: uninstallKeyboardActions();
464:
465: textComponent = null;
466: }
467:
468: protected void uninstallDefaults()
469: {
470:
471: }
472:
473: protected void uninstallListeners()
474: {
475: textComponent.removeFocusListener(focuslistener);
476: }
477:
478: protected void uninstallKeyboardActions()
479: {
480:
481: }
482:
483: protected abstract String getPropertyPrefix();
484:
485: public Dimension getPreferredSize(JComponent c)
486: {
487: View v = getRootView(textComponent);
488:
489: float w = v.getPreferredSpan(View.X_AXIS);
490: float h = v.getPreferredSpan(View.Y_AXIS);
491:
492: return new Dimension((int) w, (int) h);
493: }
494:
495:
502: public Dimension getMaximumSize(JComponent c)
503: {
504:
505: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
506: }
507:
508: public final void paint(Graphics g, JComponent c)
509: {
510: paintSafely(g);
511: }
512:
513: protected void paintSafely(Graphics g)
514: {
515: Caret caret = textComponent.getCaret();
516: Highlighter highlighter = textComponent.getHighlighter();
517:
518: if (textComponent.isOpaque())
519: paintBackground(g);
520:
521: if (highlighter != null
522: && textComponent.getSelectionStart() != textComponent.getSelectionEnd())
523: highlighter.paint(g);
524:
525: rootView.paint(g, getVisibleEditorRect());
526:
527: if (caret != null && textComponent.hasFocus())
528: caret.paint(g);
529: }
530:
531: protected void paintBackground(Graphics g)
532: {
533: g.setColor(textComponent.getBackground());
534: g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight());
535: }
536:
537: public void damageRange(JTextComponent t, int p0, int p1)
538: {
539: damageRange(t, p0, p1, null, null);
540: }
541:
542: public void damageRange(JTextComponent t, int p0, int p1,
543: Position.Bias firstBias, Position.Bias secondBias)
544: {
545: }
546:
547: public EditorKit getEditorKit(JTextComponent t)
548: {
549: return kit;
550: }
551:
552: public int getNextVisualPositionFrom(JTextComponent t, int pos,
553: Position.Bias b, int direction,
554: Position.Bias[] biasRet)
555: throws BadLocationException
556: {
557: return 0;
558: }
559:
560: public View getRootView(JTextComponent t)
561: {
562: return rootView;
563: }
564:
565: public Rectangle modelToView(JTextComponent t, int pos)
566: throws BadLocationException
567: {
568: return modelToView(t, pos, Position.Bias.Forward);
569: }
570:
571: public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
572: throws BadLocationException
573: {
574: return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds();
575: }
576:
577: public int viewToModel(JTextComponent t, Point pt)
578: {
579: return viewToModel(t, pt, null);
580: }
581:
582: public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn)
583: {
584: return 0;
585: }
586:
587: public View create(Element elem)
588: {
589:
590: return null;
591: }
592:
593: public View create(Element elem, int p0, int p1)
594: {
595:
596: return null;
597: }
598:
599: protected Rectangle getVisibleEditorRect()
600: {
601: int width = textComponent.getWidth();
602: int height = textComponent.getHeight();
603:
604: if (width <= 0 || height <= 0)
605: return null;
606:
607: Insets insets = textComponent.getInsets();
608: return new Rectangle(insets.left, insets.top,
609: width - insets.left + insets.right,
610: height - insets.top + insets.bottom);
611: }
612:
613: protected final void setView(View view)
614: {
615: rootView.setView(view);
616: view.setParent(rootView);
617: }
618:
619: protected void modelChanged()
620: {
621: if (textComponent == null || rootView == null)
622: return;
623: ViewFactory factory = rootView.getViewFactory();
624: if (factory == null)
625: return;
626: Document doc = textComponent.getDocument();
627: if (doc == null)
628: return;
629: installDocumentListeners();
630: Element elem = doc.getDefaultRootElement();
631: if (elem == null)
632: return;
633: setView(factory.create(elem));
634: }
635: }