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: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64:
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: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85: import ;
86: import ;
87: import ;
88: import ;
89: import ;
90:
91: public abstract class JTextComponent extends JComponent
92: implements Scrollable, Accessible
93: {
94:
100: public class AccessibleJTextComponent extends AccessibleJComponent implements
101: AccessibleText, CaretListener, DocumentListener, AccessibleAction,
102: AccessibleEditableText
103: {
104: private static final long serialVersionUID = 7664188944091413696L;
105:
106:
109: private int caretDot;
110:
111:
114: public AccessibleJTextComponent()
115: {
116: super();
117: JTextComponent.this.addCaretListener(this);
118: caretDot = getCaretPosition();
119: }
120:
121:
127: public int getCaretPosition()
128: {
129: return JTextComponent.this.getCaretPosition();
130: }
131:
132:
138: public String getSelectedText()
139: {
140: return JTextComponent.this.getSelectedText();
141: }
142:
143:
153: public int getSelectionStart()
154: {
155: if (getSelectedText() == null
156: || (JTextComponent.this.getText().equals("")))
157: return 0;
158: return JTextComponent.this.getSelectionStart();
159: }
160:
161:
171: public int getSelectionEnd()
172: {
173: return JTextComponent.this.getSelectionEnd();
174: }
175:
176:
182: public void caretUpdate(CaretEvent e)
183: {
184: int dot = e.getDot();
185: int mark = e.getMark();
186: if (caretDot != dot)
187: {
188: firePropertyChange(ACCESSIBLE_CARET_PROPERTY, new Integer(caretDot),
189: new Integer(dot));
190: caretDot = dot;
191: }
192: if (mark != dot)
193: {
194: firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null,
195: getSelectedText());
196: }
197: }
198:
199:
204: public AccessibleStateSet getAccessibleStateSet()
205: {
206: AccessibleStateSet state = super.getAccessibleStateSet();
207: if (isEditable())
208: state.add(AccessibleState.EDITABLE);
209: return state;
210: }
211:
212:
219: public AccessibleRole getAccessibleRole()
220: {
221: return AccessibleRole.TEXT;
222: }
223:
224:
230: public AccessibleEditableText getAccessibleEditableText()
231: {
232: return this;
233: }
234:
235:
243: public AccessibleText getAccessibleText()
244: {
245: return this;
246: }
247:
248:
255: public void insertUpdate(DocumentEvent e)
256: {
257: firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
258: new Integer(e.getOffset()));
259: }
260:
261:
268: public void removeUpdate(DocumentEvent e)
269: {
270: firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
271: new Integer(e.getOffset()));
272: }
273:
274:
281: public void changedUpdate(DocumentEvent e)
282: {
283: firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
284: new Integer(e.getOffset()));
285: }
286:
287:
296: public int getIndexAtPoint(Point p)
297: {
298: return viewToModel(p);
299: }
300:
301:
311: public Rectangle getCharacterBounds(int index)
312: {
313:
314:
315: Rectangle bounds = null;
316: if (index >= 0 && index < doc.getLength() - 1)
317: {
318: if (doc instanceof AbstractDocument)
319: ((AbstractDocument) doc).readLock();
320: try
321: {
322: TextUI ui = getUI();
323: if (ui != null)
324: {
325:
326: Rectangle rect = new Rectangle();
327: Insets insets = getInsets();
328: rect.x = insets.left;
329: rect.y = insets.top;
330: rect.width = getWidth() - insets.left - insets.right;
331: rect.height = getHeight() - insets.top - insets.bottom;
332: View rootView = ui.getRootView(JTextComponent.this);
333: if (rootView != null)
334: {
335: rootView.setSize(rect.width, rect.height);
336: Shape s = rootView.modelToView(index,
337: Position.Bias.Forward,
338: index + 1,
339: Position.Bias.Backward,
340: rect);
341: if (s != null)
342: bounds = s.getBounds();
343: }
344: }
345: }
346: catch (BadLocationException ex)
347: {
348:
349: }
350: finally
351: {
352: if (doc instanceof AbstractDocument)
353: ((AbstractDocument) doc).readUnlock();
354: }
355: }
356: return bounds;
357: }
358:
359:
364: public int getCharCount()
365: {
366: return JTextComponent.this.getText().length();
367: }
368:
369:
377: public AttributeSet getCharacterAttribute(int index)
378: {
379: AttributeSet atts;
380: if (doc instanceof AbstractDocument)
381: ((AbstractDocument) doc).readLock();
382: try
383: {
384: Element el = doc.getDefaultRootElement();
385: while (! el.isLeaf())
386: {
387: int i = el.getElementIndex(index);
388: el = el.getElement(i);
389: }
390: atts = el.getAttributes();
391: }
392: finally
393: {
394: if (doc instanceof AbstractDocument)
395: ((AbstractDocument) doc).readUnlock();
396: }
397: return atts;
398: }
399:
400:
409: public String getAtIndex(int part, int index)
410: {
411: return getAtIndexImpl(part, index, 0);
412: }
413:
414:
423: public String getAfterIndex(int part, int index)
424: {
425: return getAtIndexImpl(part, index, 1);
426: }
427:
428:
437: public String getBeforeIndex(int part, int index)
438: {
439: return getAtIndexImpl(part, index, -1);
440: }
441:
442:
451: private String getAtIndexImpl(int part, int index, int dir)
452: {
453: String ret = null;
454: if (doc instanceof AbstractDocument)
455: ((AbstractDocument) doc).readLock();
456: try
457: {
458: BreakIterator iter = null;
459: switch (part)
460: {
461: case CHARACTER:
462: iter = BreakIterator.getCharacterInstance(getLocale());
463: break;
464: case WORD:
465: iter = BreakIterator.getWordInstance(getLocale());
466: break;
467: case SENTENCE:
468: iter = BreakIterator.getSentenceInstance(getLocale());
469: break;
470: default:
471: break;
472: }
473: String text = doc.getText(0, doc.getLength() - 1);
474: iter.setText(text);
475: int start = index;
476: int end = index;
477: switch (dir)
478: {
479: case 0:
480: if (iter.isBoundary(index))
481: {
482: start = index;
483: end = iter.following(index);
484: }
485: else
486: {
487: start = iter.preceding(index);
488: end = iter.next();
489: }
490: break;
491: case 1:
492: start = iter.following(index);
493: end = iter.next();
494: break;
495: case -1:
496: end = iter.preceding(index);
497: start = iter.previous();
498: break;
499: default:
500: assert false;
501: }
502: ret = text.substring(start, end);
503: }
504: catch (BadLocationException ex)
505: {
506:
507: }
508: finally
509: {
510: if (doc instanceof AbstractDocument)
511: ((AbstractDocument) doc).readUnlock();
512: }
513: return ret;
514: }
515:
516:
522: public int getAccessibleActionCount()
523: {
524: return getActions().length;
525: }
526:
527:
535: public String getAccessibleActionDescription(int i)
536: {
537: String desc = null;
538: Action[] actions = getActions();
539: if (i >= 0 && i < actions.length)
540: desc = (String) actions[i].getValue(Action.NAME);
541: return desc;
542: }
543:
544:
552: public boolean doAccessibleAction(int i)
553: {
554: boolean ret = false;
555: Action[] actions = getActions();
556: if (i >= 0 && i < actions.length)
557: {
558: ActionEvent ev = new ActionEvent(JTextComponent.this,
559: ActionEvent.ACTION_PERFORMED, null);
560: actions[i].actionPerformed(ev);
561: ret = true;
562: }
563: return ret;
564: }
565:
566:
571: public void setTextContents(String s)
572: {
573: setText(s);
574: }
575:
576:
582: public void insertTextAtIndex(int index, String s)
583: {
584: try
585: {
586: doc.insertString(index, s, null);
587: }
588: catch (BadLocationException ex)
589: {
590:
591: ex.printStackTrace();
592: }
593: }
594:
595:
601: public String getTextRange(int start, int end)
602: {
603: try
604: {
605: return JTextComponent.this.getText(start, end - start);
606: }
607: catch (BadLocationException ble)
608: {
609: return "";
610: }
611: }
612:
613:
619: public void delete(int start, int end)
620: {
621: replaceText(start, end, "");
622: }
623:
624:
631: public void cut(int start, int end)
632: {
633: JTextComponent.this.select(start, end);
634: JTextComponent.this.cut();
635: }
636:
637:
642: public void paste(int start)
643: {
644: JTextComponent.this.setCaretPosition(start);
645: JTextComponent.this.paste();
646: }
647:
648:
656: public void replaceText(int start, int end, String s)
657: {
658: JTextComponent.this.select(start, end);
659: JTextComponent.this.replaceSelection(s);
660: }
661:
662:
668: public void selectText(int start, int end)
669: {
670: JTextComponent.this.select(start, end);
671: }
672:
673:
680: public void setAttributes(int start, int end, AttributeSet s)
681: {
682: if (doc instanceof StyledDocument)
683: {
684: StyledDocument sdoc = (StyledDocument) doc;
685: sdoc.setCharacterAttributes(start, end - start, s, true);
686: }
687: }
688: }
689:
690: public static class KeyBinding
691: {
692: public KeyStroke key;
693: public String actionName;
694:
695:
701: public KeyBinding(KeyStroke key, String actionName)
702: {
703: this.key = key;
704: this.actionName = actionName;
705: }
706: }
707:
708:
738:
739: private class KeymapWrapper extends InputMap
740: {
741: Keymap map;
742:
743: public KeymapWrapper(Keymap k)
744: {
745: map = k;
746: }
747:
748: public int size()
749: {
750: return map.getBoundKeyStrokes().length + super.size();
751: }
752:
753: public Object get(KeyStroke ks)
754: {
755: Action mapped = null;
756: Keymap m = map;
757: while(mapped == null && m != null)
758: {
759: mapped = m.getAction(ks);
760: if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED)
761: mapped = m.getDefaultAction();
762: if (mapped == null)
763: m = m.getResolveParent();
764: }
765:
766: if (mapped == null)
767: return super.get(ks);
768: else
769: return mapped;
770: }
771:
772: public KeyStroke[] keys()
773: {
774: KeyStroke[] superKeys = super.keys();
775: KeyStroke[] mapKeys = map.getBoundKeyStrokes();
776: KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length];
777: for (int i = 0; i < superKeys.length; ++i)
778: bothKeys[i] = superKeys[i];
779: for (int i = 0; i < mapKeys.length; ++i)
780: bothKeys[i + superKeys.length] = mapKeys[i];
781: return bothKeys;
782: }
783:
784: public KeyStroke[] allKeys()
785: {
786: KeyStroke[] superKeys = super.allKeys();
787: KeyStroke[] mapKeys = map.getBoundKeyStrokes();
788: int skl = 0;
789: int mkl = 0;
790: if (superKeys != null)
791: skl = superKeys.length;
792: if (mapKeys != null)
793: mkl = mapKeys.length;
794: KeyStroke[] bothKeys = new KeyStroke[skl + mkl];
795: for (int i = 0; i < skl; ++i)
796: bothKeys[i] = superKeys[i];
797: for (int i = 0; i < mkl; ++i)
798: bothKeys[i + skl] = mapKeys[i];
799: return bothKeys;
800: }
801: }
802:
803: private class KeymapActionMap extends ActionMap
804: {
805: Keymap map;
806:
807: public KeymapActionMap(Keymap k)
808: {
809: map = k;
810: }
811:
812: public Action get(Object cmd)
813: {
814: if (cmd instanceof Action)
815: return (Action) cmd;
816: else
817: return super.get(cmd);
818: }
819:
820: public int size()
821: {
822: return map.getBoundKeyStrokes().length + super.size();
823: }
824:
825: public Object[] keys()
826: {
827: Object[] superKeys = super.keys();
828: Object[] mapKeys = map.getBoundKeyStrokes();
829: Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
830: for (int i = 0; i < superKeys.length; ++i)
831: bothKeys[i] = superKeys[i];
832: for (int i = 0; i < mapKeys.length; ++i)
833: bothKeys[i + superKeys.length] = mapKeys[i];
834: return bothKeys;
835: }
836:
837: public Object[] allKeys()
838: {
839: Object[] superKeys = super.allKeys();
840: Object[] mapKeys = map.getBoundKeyStrokes();
841: Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
842: for (int i = 0; i < superKeys.length; ++i)
843: bothKeys[i] = superKeys[i];
844: for (int i = 0; i < mapKeys.length; ++i)
845: bothKeys[i + superKeys.length] = mapKeys[i];
846: return bothKeys;
847: }
848:
849: }
850:
851: static class DefaultKeymap implements Keymap
852: {
853: String name;
854: Keymap parent;
855: Hashtable map;
856: Action defaultAction;
857:
858: public DefaultKeymap(String name)
859: {
860: this.name = name;
861: this.map = new Hashtable();
862: }
863:
864: public void addActionForKeyStroke(KeyStroke key, Action a)
865: {
866: map.put(key, a);
867: }
868:
869:
878: public Action getAction(KeyStroke key)
879: {
880: if (map.containsKey(key))
881: return (Action) map.get(key);
882: else if (p