46 |
import java.awt.Point; |
import java.awt.Point; |
47 |
import java.awt.Rectangle; |
import java.awt.Rectangle; |
48 |
import java.awt.event.InputMethodListener; |
import java.awt.event.InputMethodListener; |
49 |
|
import java.awt.event.KeyEvent; |
50 |
|
|
51 |
|
import java.util.Enumeration; |
52 |
|
import java.util.Hashtable; |
53 |
|
|
54 |
import javax.accessibility.Accessible; |
import javax.accessibility.Accessible; |
55 |
import javax.accessibility.AccessibleContext; |
import javax.accessibility.AccessibleContext; |
56 |
import javax.accessibility.AccessibleRole; |
import javax.accessibility.AccessibleRole; |
57 |
import javax.accessibility.AccessibleStateSet; |
import javax.accessibility.AccessibleStateSet; |
58 |
import javax.accessibility.AccessibleText; |
import javax.accessibility.AccessibleText; |
59 |
|
import javax.swing.Action; |
60 |
|
import javax.swing.ActionMap; |
61 |
import javax.swing.Icon; |
import javax.swing.Icon; |
62 |
|
import javax.swing.InputMap; |
63 |
import javax.swing.JComponent; |
import javax.swing.JComponent; |
64 |
import javax.swing.JViewport; |
import javax.swing.JViewport; |
65 |
import javax.swing.KeyStroke; |
import javax.swing.KeyStroke; |
69 |
import javax.swing.event.CaretListener; |
import javax.swing.event.CaretListener; |
70 |
import javax.swing.event.DocumentEvent; |
import javax.swing.event.DocumentEvent; |
71 |
import javax.swing.event.DocumentListener; |
import javax.swing.event.DocumentListener; |
72 |
|
import javax.swing.plaf.ActionMapUIResource; |
73 |
|
import javax.swing.plaf.InputMapUIResource; |
74 |
import javax.swing.plaf.TextUI; |
import javax.swing.plaf.TextUI; |
75 |
|
|
76 |
|
|
292 |
} |
} |
293 |
} |
} |
294 |
|
|
295 |
|
/** |
296 |
|
* According to <a |
297 |
|
* href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this |
298 |
|
* report</a>, a pair of private classes wraps a {@link |
299 |
|
* javax.swing.text.Keymap} in the new {@link InputMap} / {@link |
300 |
|
* ActionMap} interfaces, such that old Keymap-using code can make use of |
301 |
|
* the new framework.</p> |
302 |
|
* |
303 |
|
* <p>A little bit of experimentation with these classes reveals the following |
304 |
|
* structure: |
305 |
|
* |
306 |
|
* <ul> |
307 |
|
* |
308 |
|
* <li>KeymapWrapper extends {@link InputMap} and holds a reference to |
309 |
|
* the underlying {@link Keymap}.</li> |
310 |
|
* |
311 |
|
* <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action} |
312 |
|
* objects, by delegation to the underlying {@link Keymap}.</li> |
313 |
|
* |
314 |
|
* <li>KeymapActionMap extends {@link ActionMap} also holds a reference to |
315 |
|
* the underlying {@link Keymap} but only appears to use it for listing |
316 |
|
* its keys. </li> |
317 |
|
* |
318 |
|
* <li>KeymapActionMap maps all {@link Action} objects to |
319 |
|
* <em>themselves</em>, whether they exist in the underlying {@link |
320 |
|
* Keymap} or not, and passes other objects to the parent {@link |
321 |
|
* ActionMap} for resolving. |
322 |
|
* |
323 |
|
* </ul> |
324 |
|
*/ |
325 |
|
|
326 |
|
private class KeymapWrapper extends InputMap |
327 |
|
{ |
328 |
|
Keymap map; |
329 |
|
|
330 |
|
public KeymapWrapper(Keymap k) |
331 |
|
{ |
332 |
|
map = k; |
333 |
|
} |
334 |
|
|
335 |
|
public int size() |
336 |
|
{ |
337 |
|
return map.getBoundKeyStrokes().length + super.size(); |
338 |
|
} |
339 |
|
|
340 |
|
public Object get(KeyStroke ks) |
341 |
|
{ |
342 |
|
Action mapped = null; |
343 |
|
Keymap m = map; |
344 |
|
while(mapped == null && m != null) |
345 |
|
{ |
346 |
|
mapped = m.getAction(ks); |
347 |
|
if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED) |
348 |
|
mapped = m.getDefaultAction(); |
349 |
|
if (mapped == null) |
350 |
|
m = m.getResolveParent(); |
351 |
|
} |
352 |
|
|
353 |
|
if (mapped == null) |
354 |
|
return super.get(ks); |
355 |
|
else |
356 |
|
return mapped; |
357 |
|
} |
358 |
|
|
359 |
|
public KeyStroke[] keys() |
360 |
|
{ |
361 |
|
KeyStroke[] superKeys = super.keys(); |
362 |
|
KeyStroke[] mapKeys = map.getBoundKeyStrokes(); |
363 |
|
KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; |
364 |
|
for (int i = 0; i < superKeys.length; ++i) |
365 |
|
bothKeys[i] = superKeys[i]; |
366 |
|
for (int i = 0; i < mapKeys.length; ++i) |
367 |
|
bothKeys[i + superKeys.length] = mapKeys[i]; |
368 |
|
return bothKeys; |
369 |
|
} |
370 |
|
|
371 |
|
public KeyStroke[] allKeys() |
372 |
|
{ |
373 |
|
KeyStroke[] superKeys = super.allKeys(); |
374 |
|
KeyStroke[] mapKeys = map.getBoundKeyStrokes(); |
375 |
|
KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; |
376 |
|
for (int i = 0; i < superKeys.length; ++i) |
377 |
|
bothKeys[i] = superKeys[i]; |
378 |
|
for (int i = 0; i < mapKeys.length; ++i) |
379 |
|
bothKeys[i + superKeys.length] = mapKeys[i]; |
380 |
|
return bothKeys; |
381 |
|
} |
382 |
|
} |
383 |
|
|
384 |
|
private class KeymapActionMap extends ActionMap |
385 |
|
{ |
386 |
|
Keymap map; |
387 |
|
|
388 |
|
public KeymapActionMap(Keymap k) |
389 |
|
{ |
390 |
|
map = k; |
391 |
|
} |
392 |
|
|
393 |
|
public Action get(Object cmd) |
394 |
|
{ |
395 |
|
if (cmd instanceof Action) |
396 |
|
return (Action) cmd; |
397 |
|
else |
398 |
|
return super.get(cmd); |
399 |
|
} |
400 |
|
|
401 |
|
public int size() |
402 |
|
{ |
403 |
|
return map.getBoundKeyStrokes().length + super.size(); |
404 |
|
} |
405 |
|
|
406 |
|
public Object[] keys() |
407 |
|
{ |
408 |
|
Object[] superKeys = super.keys(); |
409 |
|
Object[] mapKeys = map.getBoundKeyStrokes(); |
410 |
|
Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; |
411 |
|
for (int i = 0; i < superKeys.length; ++i) |
412 |
|
bothKeys[i] = superKeys[i]; |
413 |
|
for (int i = 0; i < mapKeys.length; ++i) |
414 |
|
bothKeys[i + superKeys.length] = mapKeys[i]; |
415 |
|
return bothKeys; |
416 |
|
} |
417 |
|
|
418 |
|
public Object[] allKeys() |
419 |
|
{ |
420 |
|
Object[] superKeys = super.allKeys(); |
421 |
|
Object[] mapKeys = map.getBoundKeyStrokes(); |
422 |
|
Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; |
423 |
|
for (int i = 0; i < superKeys.length; ++i) |
424 |
|
bothKeys[i] = superKeys[i]; |
425 |
|
for (int i = 0; i < mapKeys.length; ++i) |
426 |
|
bothKeys[i + superKeys.length] = mapKeys[i]; |
427 |
|
return bothKeys; |
428 |
|
} |
429 |
|
|
430 |
|
} |
431 |
|
|
432 |
|
static class DefaultKeymap implements Keymap |
433 |
|
{ |
434 |
|
String name; |
435 |
|
Keymap parent; |
436 |
|
Hashtable map; |
437 |
|
Action defaultAction; |
438 |
|
|
439 |
|
public DefaultKeymap(String name) |
440 |
|
{ |
441 |
|
this.name = name; |
442 |
|
this.map = new Hashtable(); |
443 |
|
} |
444 |
|
|
445 |
|
public void addActionForKeyStroke(KeyStroke key, Action a) |
446 |
|
{ |
447 |
|
map.put(key, a); |
448 |
|
} |
449 |
|
|
450 |
|
/** |
451 |
|
* Looks up a KeyStroke either in the current map or the parent Keymap; |
452 |
|
* does <em>not</em> return the default action if lookup fails. |
453 |
|
* |
454 |
|
* @param key The KeyStroke to look up an Action for. |
455 |
|
* |
456 |
|
* @return The mapping for <code>key</code>, or <code>null</code> |
457 |
|
* if no mapping exists in this Keymap or any of its parents. |
458 |
|
*/ |
459 |
|
public Action getAction(KeyStroke key) |
460 |
|
{ |
461 |
|
if (map.containsKey(key)) |
462 |
|
return (Action) map.get(key); |
463 |
|
else if (parent != null) |
464 |
|
return parent.getAction(key); |
465 |
|
else |
466 |
|
return null; |
467 |
|
} |
468 |
|
|
469 |
|
public Action[] getBoundActions() |
470 |
|
{ |
471 |
|
Action [] ret = new Action[map.size()]; |
472 |
|
Enumeration e = map.elements(); |
473 |
|
int i = 0; |
474 |
|
while (e.hasMoreElements()) |
475 |
|
{ |
476 |
|
ret[i++] = (Action) e.nextElement(); |
477 |
|
} |
478 |
|
return ret; |
479 |
|
} |
480 |
|
|
481 |
|
public KeyStroke[] getBoundKeyStrokes() |
482 |
|
{ |
483 |
|
KeyStroke [] ret = new KeyStroke[map.size()]; |
484 |
|
Enumeration e = map.keys(); |
485 |
|
int i = 0; |
486 |
|
while (e.hasMoreElements()) |
487 |
|
{ |
488 |
|
ret[i++] = (KeyStroke) e.nextElement(); |
489 |
|
} |
490 |
|
return ret; |
491 |
|
} |
492 |
|
|
493 |
|
public Action getDefaultAction() |
494 |
|
{ |
495 |
|
return defaultAction; |
496 |
|
} |
497 |
|
|
498 |
|
public KeyStroke[] getKeyStrokesForAction(Action a) |
499 |
|
{ |
500 |
|
int i = 0; |
501 |
|
Enumeration e = map.keys(); |
502 |
|
while (e.hasMoreElements()) |
503 |
|
{ |
504 |
|
if (map.get(e.nextElement()).equals(a)) |
505 |
|
++i; |
506 |
|
} |
507 |
|
KeyStroke [] ret = new KeyStroke[i]; |
508 |
|
i = 0; |
509 |
|
e = map.keys(); |
510 |
|
while (e.hasMoreElements()) |
511 |
|
{ |
512 |
|
KeyStroke k = (KeyStroke) e.nextElement(); |
513 |
|
if (map.get(k).equals(a)) |
514 |
|
ret[i++] = k; |
515 |
|
} |
516 |
|
return ret; |
517 |
|
} |
518 |
|
|
519 |
|
public String getName() |
520 |
|
{ |
521 |
|
return name; |
522 |
|
} |
523 |
|
|
524 |
|
public Keymap getResolveParent() |
525 |
|
{ |
526 |
|
return parent; |
527 |
|
} |
528 |
|
|
529 |
|
public boolean isLocallyDefined(KeyStroke key) |
530 |
|
{ |
531 |
|
return map.containsKey(key); |
532 |
|
} |
533 |
|
|
534 |
|
public void removeBindings() |
535 |
|
{ |
536 |
|
map.clear(); |
537 |
|
} |
538 |
|
|
539 |
|
public void removeKeyStrokeBinding(KeyStroke key) |
540 |
|
{ |
541 |
|
map.remove(key); |
542 |
|
} |
543 |
|
|
544 |
|
public void setDefaultAction(Action a) |
545 |
|
{ |
546 |
|
defaultAction = a; |
547 |
|
} |
548 |
|
|
549 |
|
public void setResolveParent(Keymap p) |
550 |
|
{ |
551 |
|
parent = p; |
552 |
|
} |
553 |
|
|
554 |
|
} |
555 |
|
|
556 |
private static final long serialVersionUID = -8796518220218978795L; |
private static final long serialVersionUID = -8796518220218978795L; |
557 |
|
|
558 |
public static final String DEFAULT_KEYMAP = "default"; |
public static final String DEFAULT_KEYMAP = "default"; |
559 |
public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; |
public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; |
560 |
|
|
561 |
|
private static Hashtable keymaps = new Hashtable(); |
562 |
|
private Keymap keymap; |
563 |
|
|
564 |
|
/** |
565 |
|
* Get a Keymap from the global keymap table, by name. |
566 |
|
* |
567 |
|
* @param n The name of the Keymap to look up |
568 |
|
* |
569 |
|
* @return A Keymap associated with the provided name, or |
570 |
|
* <code>null</code> if no such Keymap exists |
571 |
|
* |
572 |
|
* @see #addKeymap() |
573 |
|
* @see #removeKeymap() |
574 |
|
* @see #keymaps |
575 |
|
*/ |
576 |
|
public static Keymap getKeymap(String n) |
577 |
|
{ |
578 |
|
return (Keymap) keymaps.get(n); |
579 |
|
} |
580 |
|
|
581 |
|
/** |
582 |
|
* Remove a Keymap from the global Keymap table, by name. |
583 |
|
* |
584 |
|
* @param n The name of the Keymap to remove |
585 |
|
* |
586 |
|
* @return The keymap removed from the global table |
587 |
|
* |
588 |
|
* @see #addKeymap() |
589 |
|
* @see #getKeymap() |
590 |
|
* @see #keymaps |
591 |
|
*/ |
592 |
|
public static Keymap removeKeymap(String n) |
593 |
|
{ |
594 |
|
Keymap km = (Keymap) keymaps.get(n); |
595 |
|
keymaps.remove(n); |
596 |
|
return km; |
597 |
|
} |
598 |
|
|
599 |
|
/** |
600 |
|
* Create a new Keymap with a specific name and parent, and add the new |
601 |
|
* Keymap to the global keymap table. The name may be <code>null</code>, |
602 |
|
* in which case the new Keymap will <em>not</em> be added to the global |
603 |
|
* Keymap table. The parent may also be <code>null</code>, which is |
604 |
|
* harmless. |
605 |
|
* |
606 |
|
* @param n The name of the new Keymap, or <code>null</code> |
607 |
|
* @param parent The parent of the new Keymap, or <code>null</code> |
608 |
|
* |
609 |
|
* @return The newly created Keymap |
610 |
|
* |
611 |
|
* @see #removeKeymap() |
612 |
|
* @see #getKeymap() |
613 |
|
* @see #keymaps |
614 |
|
*/ |
615 |
|
public static Keymap addKeymap(String n, Keymap parent) |
616 |
|
{ |
617 |
|
Keymap k = new DefaultKeymap(n); |
618 |
|
k.setResolveParent(parent); |
619 |
|
if (n != null) |
620 |
|
keymaps.put(n, k); |
621 |
|
return k; |
622 |
|
} |
623 |
|
|
624 |
|
/** |
625 |
|
* Get the current Keymap of this component. |
626 |
|
* |
627 |
|
* @return The component's current Keymap |
628 |
|
* |
629 |
|
* @see #setKeymap() |
630 |
|
* @see #keymap |
631 |
|
*/ |
632 |
|
Keymap getKeymap() |
633 |
|
{ |
634 |
|
return keymap; |
635 |
|
} |
636 |
|
|
637 |
|
/** |
638 |
|
* Set the current Keymap of this component, installing appropriate |
639 |
|
* {@link KeymapWrapper} and {@link KeymapActionMap} objects in the |
640 |
|
* {@link InputMap} and {@link ActionMap} parent chains, respectively, |
641 |
|
* and fire a property change event with name <code>"keymap"</code>. |
642 |
|
* |
643 |
|
* @see #getKeymap() |
644 |
|
* @see #keymap |
645 |
|
*/ |
646 |
|
public void setKeymap(Keymap k) |
647 |
|
{ |
648 |
|
|
649 |
|
// phase 1: replace the KeymapWrapper entry in the InputMap chain. |
650 |
|
// the goal here is to always maintain the following ordering: |
651 |
|
// |
652 |
|
// [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]* |
653 |
|
// |
654 |
|
// that is to say, component-specific InputMaps need to remain children |
655 |
|
// of Keymaps, and Keymaps need to remain children of UI-installed |
656 |
|
// InputMaps (and the order of each group needs to be preserved, of |
657 |
|
// course). |
658 |
|
|
659 |
|
KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k)); |
660 |
|
InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED); |
661 |
|
if (childInputMap == null) |
662 |
|
setInputMap(JComponent.WHEN_FOCUSED, kw); |
663 |
|
else |
664 |
|
{ |
665 |
|
while (childInputMap.getParent() != null |
666 |
|
&& !(childInputMap.getParent() instanceof KeymapWrapper) |
667 |
|
&& !(childInputMap.getParent() instanceof InputMapUIResource)) |
668 |
|
childInputMap = childInputMap.getParent(); |
669 |
|
|
670 |
|
// option 1: there is nobody to replace at the end of the chain |
671 |
|
if (childInputMap.getParent() == null) |
672 |
|
childInputMap.setParent(kw); |
673 |
|
|
674 |
|
// option 2: there is already a KeymapWrapper in the chain which |
675 |
|
// needs replacing (possibly with its own parents, possibly without) |
676 |
|
else if (childInputMap.getParent() instanceof KeymapWrapper) |
677 |
|
{ |
678 |
|
if (kw == null) |
679 |
|
childInputMap.setParent(childInputMap.getParent().getParent()); |
680 |
|
else |
681 |
|
{ |
682 |
|
kw.setParent(childInputMap.getParent().getParent()); |
683 |
|
childInputMap.setParent(kw); |
684 |
|
} |
685 |
|
} |
686 |
|
|
687 |
|
// option 3: there is an InputMapUIResource in the chain, which marks |
688 |
|
// the place where we need to stop and insert ourselves |
689 |
|
else if (childInputMap.getParent() instanceof InputMapUIResource) |
690 |
|
{ |
691 |
|
if (kw != null) |
692 |
|
{ |
693 |
|
kw.setParent(childInputMap.getParent()); |
694 |
|
childInputMap.setParent(kw); |
695 |
|
} |
696 |
|
} |
697 |
|
} |
698 |
|
|
699 |
|
// phase 2: replace the KeymapActionMap entry in the ActionMap chain |
700 |
|
|
701 |
|
KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k)); |
702 |
|
ActionMap childActionMap = getActionMap(); |
703 |
|
if (childActionMap == null) |
704 |
|
setActionMap(kam); |
705 |
|
else |
706 |
|
{ |
707 |
|
while (childActionMap.getParent() != null |
708 |
|
&& !(childActionMap.getParent() instanceof KeymapActionMap) |
709 |
|
&& !(childActionMap.getParent() instanceof ActionMapUIResource)) |
710 |
|
childActionMap = childActionMap.getParent(); |
711 |
|
|
712 |
|
// option 1: there is nobody to replace at the end of the chain |
713 |
|
if (childActionMap.getParent() == null) |
714 |
|
childActionMap.setParent(kam); |
715 |
|
|
716 |
|
// option 2: there is already a KeymapActionMap in the chain which |
717 |
|
// needs replacing (possibly with its own parents, possibly without) |
718 |
|
else if (childActionMap.getParent() instanceof KeymapActionMap) |
719 |
|
{ |
720 |
|
if (kam == null) |
721 |
|
childActionMap.setParent(childActionMap.getParent().getParent()); |
722 |
|
else |
723 |
|
{ |
724 |
|
kam.setParent(childActionMap.getParent().getParent()); |
725 |
|
childActionMap.setParent(kam); |
726 |
|
} |
727 |
|
} |
728 |
|
|
729 |
|
// option 3: there is an ActionMapUIResource in the chain, which marks |
730 |
|
// the place where we need to stop and insert ourselves |
731 |
|
else if (childActionMap.getParent() instanceof ActionMapUIResource) |
732 |
|
{ |
733 |
|
if (kam != null) |
734 |
|
{ |
735 |
|
kam.setParent(childActionMap.getParent()); |
736 |
|
childActionMap.setParent(kam); |
737 |
|
} |
738 |
|
} |
739 |
|
} |
740 |
|
|
741 |
|
// phase 3: update the explicit keymap field |
742 |
|
|
743 |
|
Keymap old = keymap; |
744 |
|
keymap = k; |
745 |
|
firePropertyChange("keymap", old, k); |
746 |
|
} |
747 |
|
|
748 |
|
/** |
749 |
|
* Resolves a set of bindings against a set of actions and inserts the |
750 |
|
* results into a {@link Keymap}. Specifically, for each provided binding |
751 |
|
* <code>b</code>, if there exists a provided action <code>a</code> such |
752 |
|
* that <code>a.getValue(Action.NAME) == b.ActionName</code> then an |
753 |
|
* entry is added to the Keymap mapping <code>b</code> to |
754 |
|
* </code>a</code>. |
755 |
|
* |
756 |
|
* @param map The Keymap to add new mappings to |
757 |
|
* @param bindings The set of bindings to add to the Keymap |
758 |
|
* @param actions The set of actions to resolve binding names against |
759 |
|
* |
760 |
|
* @see Action#NAME |
761 |
|
* @see Action#getValue() |
762 |
|
* @see KeyBinding#ActionName |
763 |
|
*/ |
764 |
|
public static void loadKeymap(Keymap map, |
765 |
|
JTextComponent.KeyBinding[] bindings, |
766 |
|
Action[] actions) |
767 |
|
{ |
768 |
|
Hashtable acts = new Hashtable(actions.length); |
769 |
|
for (int i = 0; i < actions.length; ++i) |
770 |
|
acts.put(actions[i].getValue(Action.NAME), actions[i]); |
771 |
|
for (int i = 0; i < bindings.length; ++i) |
772 |
|
if (acts.containsKey(bindings[i].actionName)) |
773 |
|
map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName)); |
774 |
|
} |
775 |
|
|
776 |
|
/** |
777 |
|
* Returns the set of available Actions this component's associated |
778 |
|
* editor can run. Equivalent to calling |
779 |
|
* <code>getUI().getEditorKit().getActions()</code>. This set of Actions |
780 |
|
* is a reasonable value to provide as a parameter to {@link |
781 |
|
* #loadKeymap()}, when resolving a set of {@link #KeyBinding} objects |
782 |
|
* against this component. |
783 |
|
* |
784 |
|
* @return The set of available Actions on this component's {@link EditorKit} |
785 |
|
* |
786 |
|
* @see TextUI#getEditorKit() |
787 |
|
* @see EditorKit#getActions() |
788 |
|
*/ |
789 |
|
public Action[] getActions() |
790 |
|
{ |
791 |
|
return getUI().getEditorKit(this).getActions(); |
792 |
|
} |
793 |
|
|
794 |
private Document doc; |
private Document doc; |
795 |
private Caret caret; |
private Caret caret; |
796 |
private Highlighter highlighter; |
private Highlighter highlighter; |
799 |
private Color selectedTextColor; |
private Color selectedTextColor; |
800 |
private Color selectionColor; |
private Color selectionColor; |
801 |
private boolean editable; |
private boolean editable; |
802 |
|
private Insets margin; |
803 |
|
|
804 |
/** |
/** |
805 |
* Creates a new <code>JTextComponent</code> instance. |
* Creates a new <code>JTextComponent</code> instance. |
806 |
*/ |
*/ |
807 |
public JTextComponent() |
public JTextComponent() |
808 |
{ |
{ |
809 |
|
Keymap defkeymap = getKeymap(DEFAULT_KEYMAP); |
810 |
|
boolean creatingKeymap = false; |
811 |
|
if (defkeymap == null) |
812 |
|
{ |
813 |
|
defkeymap = addKeymap(DEFAULT_KEYMAP, null); |
814 |
|
defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction()); |
815 |
|
creatingKeymap = true; |
816 |
|
} |
817 |
|
|
818 |
|
setFocusable(true); |
819 |
enableEvents(AWTEvent.KEY_EVENT_MASK); |
enableEvents(AWTEvent.KEY_EVENT_MASK); |
820 |
updateUI(); |
updateUI(); |
821 |
} |
|
822 |
|
// need to do this after updateUI() |
823 |
public void setDocument(Document s) |
if (creatingKeymap) |
824 |
{ |
loadKeymap(defkeymap, |
825 |
doc = s; |
new KeyBinding[] { |
826 |
|
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), |
827 |
|
DefaultEditorKit.backwardAction), |
828 |
|
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), |
829 |
|
DefaultEditorKit.forwardAction), |
830 |
|
new KeyBinding(KeyStroke.getKeyStroke("typed \b"), |
831 |
|
DefaultEditorKit.deletePrevCharAction), |
832 |
|
new KeyBinding(KeyStroke.getKeyStroke("typed \u007f"), |
833 |
|
DefaultEditorKit.deleteNextCharAction) |
834 |
|
}, |
835 |
|
getActions()); |
836 |
|
} |
837 |
|
|
838 |
|
public void setDocument(Document newDoc) |
839 |
|
{ |
840 |
|
Document oldDoc = doc; |
841 |
|
doc = newDoc; |
842 |
|
firePropertyChange("document", oldDoc, newDoc); |
843 |
revalidate(); |
revalidate(); |
844 |
repaint(); |
repaint(); |
845 |
} |
} |
859 |
return null; |
return null; |
860 |
} |
} |
861 |
|
|
862 |
|
public void setMargin(Insets m) |
863 |
|
{ |
864 |
|
margin = m; |
865 |
|
} |
866 |
|
|
867 |
public Insets getMargin() |
public Insets getMargin() |
868 |
{ |
{ |
869 |
// FIXME: Not implemented. |
return margin; |
|
return null; |
|
870 |
} |
} |
871 |
|
|
872 |
public void setText(String text) |
public void setText(String text) |
873 |
{ |
{ |
874 |
try |
try |
875 |
{ |
{ |
876 |
getDocument().remove(0, doc.getLength()); |
doc.remove(0, doc.getLength()); |
877 |
getDocument().insertString(0, text, null); |
doc.insertString(0, text, null); |
878 |
} |
} |
879 |
catch (BadLocationException e) |
catch (BadLocationException e) |
880 |
{ |
{ |
1023 |
*/ |
*/ |
1024 |
public void setCaret(Caret newCaret) |
public void setCaret(Caret newCaret) |
1025 |
{ |
{ |
1026 |
firePropertyChange("caret", caret, newCaret); |
if (caret != null) |
1027 |
|
caret.deinstall(this); |
1028 |
|
|
1029 |
|
Caret oldCaret = caret; |
1030 |
caret = newCaret; |
caret = newCaret; |
1031 |
|
|
1032 |
|
if (caret != null) |
1033 |
|
caret.install(this); |
1034 |
|
|
1035 |
|
firePropertyChange("caret", oldCaret, newCaret); |
1036 |
} |
} |
1037 |
|
|
1038 |
public Color getCaretColor() |
public Color getCaretColor() |
1042 |
|
|
1043 |
public void setCaretColor(Color newColor) |
public void setCaretColor(Color newColor) |
1044 |
{ |
{ |
1045 |
firePropertyChange("caretColor", caretColor, newColor); |
Color oldCaretColor = caretColor; |
1046 |
caretColor = newColor; |
caretColor = newColor; |
1047 |
|
firePropertyChange("caretColor", oldCaretColor, newColor); |
1048 |
} |
} |
1049 |
|
|
1050 |
public Color getDisabledTextColor() |
public Color getDisabledTextColor() |
1054 |
|
|
1055 |
public void setDisabledTextColor(Color newColor) |
public void setDisabledTextColor(Color newColor) |
1056 |
{ |
{ |
1057 |
firePropertyChange("disabledTextColor", caretColor, newColor); |
Color oldColor = disabledTextColor; |
1058 |
disabledTextColor = newColor; |
disabledTextColor = newColor; |
1059 |
|
firePropertyChange("disabledTextColor", oldColor, newColor); |
1060 |
} |
} |
1061 |
|
|
1062 |
public Color getSelectedTextColor() |
public Color getSelectedTextColor() |
1066 |
|
|
1067 |
public void setSelectedTextColor(Color newColor) |
public void setSelectedTextColor(Color newColor) |
1068 |
{ |
{ |
1069 |
firePropertyChange("selectedTextColor", caretColor, newColor); |
Color oldColor = selectedTextColor; |
1070 |
selectedTextColor = newColor; |
selectedTextColor = newColor; |
1071 |
|
firePropertyChange("selectedTextColor", oldColor, newColor); |
1072 |
} |
} |
1073 |
|
|
1074 |
public Color getSelectionColor() |
public Color getSelectionColor() |
1078 |
|
|
1079 |
public void setSelectionColor(Color newColor) |
public void setSelectionColor(Color newColor) |
1080 |
{ |
{ |
1081 |
firePropertyChange("selectionColor", caretColor, newColor); |
Color oldColor = selectionColor; |
1082 |
selectionColor = newColor; |
selectionColor = newColor; |
1083 |
|
firePropertyChange("selectionColor", oldColor, newColor); |
1084 |
} |
} |
1085 |
|
|
1086 |
/** |
/** |
1131 |
|
|
1132 |
public void setHighlighter(Highlighter newHighlighter) |
public void setHighlighter(Highlighter newHighlighter) |
1133 |
{ |
{ |
1134 |
firePropertyChange("highlighter", highlighter, newHighlighter); |
if (highlighter != null) |
1135 |
|
highlighter.deinstall(this); |
1136 |
|
|
1137 |
|
Highlighter oldHighlighter = highlighter; |
1138 |
highlighter = newHighlighter; |
highlighter = newHighlighter; |
1139 |
|
|
1140 |
|
if (highlighter != null) |
1141 |
|
highlighter.install(this); |
1142 |
|
|
1143 |
|
firePropertyChange("highlighter", oldHighlighter, newHighlighter); |
1144 |
} |
} |
1145 |
|
|
1146 |
/** |
/** |
1328 |
{ |
{ |
1329 |
return (InputMethodListener[]) getListeners(InputMethodListener.class); |
return (InputMethodListener[]) getListeners(InputMethodListener.class); |
1330 |
} |
} |
1331 |
|
|
1332 |
|
public Rectangle modelToView(int position) throws BadLocationException |
1333 |
|
{ |
1334 |
|
return getUI().modelToView(this, position); |
1335 |
|
} |
1336 |
} |
} |