KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > text > DefaultEditorKit


1 /*
2  * @(#)DefaultEditorKit.java 1.67 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.text;
8
9 import java.io.*;
10 import java.awt.*;
11 import java.awt.event.ActionEvent JavaDoc;
12 import java.text.*;
13 import javax.swing.Action JavaDoc;
14 import javax.swing.KeyStroke JavaDoc;
15 import javax.swing.SwingConstants JavaDoc;
16 import javax.swing.UIManager JavaDoc;
17
18 /**
19  * This is the set of things needed by a text component
20  * to be a reasonably functioning editor for some <em>type</em>
21  * of text document. This implementation provides a default
22  * implementation which treats text as plain text and
23  * provides a minimal set of actions for a simple editor.
24  * <p>
25  * <dl>
26  * <dt><b><font size=+1>Newlines</font></b>
27  * <dd>
28  * There are two properties which deal with newlines. The
29  * system property, <code>line.separator</code>, is defined to be
30  * platform-dependent, either "\n", "\r", or "\r\n". There is also
31  * a property defined in <code>DefaultEditorKit</code>, called
32  * <a HREF=#EndOfLineStringProperty><code>EndOfLineStringProperty</code></a>,
33  * which is defined automatically when a document is loaded, to be
34  * the first occurrence of any of the newline characters.
35  * When a document is loaded, <code>EndOfLineStringProperty</code>
36  * is set appropriately, and when the document is written back out, the
37  * <code>EndOfLineStringProperty</code> is used. But while the document
38  * is in memory, the "\n" character is used to define a
39  * newline, regardless of how the newline is defined when
40  * the document is on disk. Therefore, for searching purposes,
41  * "\n" should always be used. When a new document is created,
42  * and the <code>EndOfLineStringProperty</code> has not been defined,
43  * it will use the System property when writing out the
44  * document.
45  * <p>Note that <code>EndOfLineStringProperty</code> is set
46  * on the <code>Document</code> using the <code>get/setProperty</code>
47  * methods. Subclasses may override this behavior.
48  *
49  * </dl>
50  *
51  * @author Timothy Prinzing
52  * @version 1.67 12/19/03
53  */

54 public class DefaultEditorKit extends EditorKit JavaDoc {
55     
56     /**
57      * default constructor for DefaultEditorKit
58      */

59     public DefaultEditorKit() {
60     }
61
62     /**
63      * Gets the MIME type of the data that this
64      * kit represents support for. The default
65      * is <code>text/plain</code>.
66      *
67      * @return the type
68      */

69     public String JavaDoc getContentType() {
70         return "text/plain";
71     }
72
73     /**
74      * Fetches a factory that is suitable for producing
75      * views of any models that are produced by this
76      * kit. The default is to have the UI produce the
77      * factory, so this method has no implementation.
78      *
79      * @return the view factory
80      */

81     public ViewFactory JavaDoc getViewFactory() {
82         return null;
83     }
84
85     /**
86      * Fetches the set of commands that can be used
87      * on a text component that is using a model and
88      * view produced by this kit.
89      *
90      * @return the command list
91      */

92     public Action JavaDoc[] getActions() {
93         return defaultActions;
94     }
95
96     /**
97      * Fetches a caret that can navigate through views
98      * produced by the associated ViewFactory.
99      *
100      * @return the caret
101      */

102     public Caret JavaDoc createCaret() {
103         return null;
104     }
105
106     /**
107      * Creates an uninitialized text storage model (PlainDocument)
108      * that is appropriate for this type of editor.
109      *
110      * @return the model
111      */

112     public Document JavaDoc createDefaultDocument() {
113         return new PlainDocument JavaDoc();
114     }
115
116     /**
117      * Inserts content from the given stream which is expected
118      * to be in a format appropriate for this kind of content
119      * handler.
120      *
121      * @param in The stream to read from
122      * @param doc The destination for the insertion.
123      * @param pos The location in the document to place the
124      * content >= 0.
125      * @exception IOException on any I/O error
126      * @exception BadLocationException if pos represents an invalid
127      * location within the document.
128      */

129     public void read(InputStream in, Document JavaDoc doc, int pos)
130         throws IOException, BadLocationException JavaDoc {
131
132         read(new InputStreamReader(in), doc, pos);
133     }
134
135     /**
136      * Writes content from a document to the given stream
137      * in a format appropriate for this kind of content handler.
138      *
139      * @param out The stream to write to
140      * @param doc The source for the write.
141      * @param pos The location in the document to fetch the
142      * content >= 0.
143      * @param len The amount to write out >= 0.
144      * @exception IOException on any I/O error
145      * @exception BadLocationException if pos represents an invalid
146      * location within the document.
147      */

148     public void write(OutputStream out, Document JavaDoc doc, int pos, int len)
149         throws IOException, BadLocationException JavaDoc {
150     OutputStreamWriter osw = new OutputStreamWriter(out);
151
152         write(osw, doc, pos, len);
153     osw.flush();
154     }
155
156     /**
157      * Gets the input attributes for the pane. This method exists for
158      * the benefit of StyledEditorKit so that the read method will
159      * pick up the correct attributes to apply to inserted text.
160      * This class's implementation simply returns null.
161      *
162      * @return null
163      */

164     MutableAttributeSet JavaDoc getInputAttributes() {
165         return null;
166     }
167
168     /**
169      * Inserts content from the given stream, which will be
170      * treated as plain text.
171      *
172      * @param in The stream to read from
173      * @param doc The destination for the insertion.
174      * @param pos The location in the document to place the
175      * content >= 0.
176      * @exception IOException on any I/O error
177      * @exception BadLocationException if pos represents an invalid
178      * location within the document.
179      */

180     public void read(Reader in, Document JavaDoc doc, int pos)
181         throws IOException, BadLocationException JavaDoc {
182
183         char[] buff = new char[4096];
184         int nch;
185     boolean lastWasCR = false;
186     boolean isCRLF = false;
187     boolean isCR = false;
188     int last;
189     boolean wasEmpty = (doc.getLength() == 0);
190         AttributeSet JavaDoc attr = getInputAttributes();
191
192     // Read in a block at a time, mapping \r\n to \n, as well as single
193
// \r's to \n's. If a \r\n is encountered, \r\n will be set as the
194
// newline string for the document, if \r is encountered it will
195
// be set as the newline character, otherwise the newline property
196
// for the document will be removed.
197
while ((nch = in.read(buff, 0, buff.length)) != -1) {
198         last = 0;
199         for(int counter = 0; counter < nch; counter++) {
200         switch(buff[counter]) {
201         case '\r':
202             if (lastWasCR) {
203             isCR = true;
204             if (counter == 0) {
205                             doc.insertString(pos, "\n", attr);
206                 pos++;
207             }
208             else {
209                 buff[counter - 1] = '\n';
210             }
211             }
212             else {
213             lastWasCR = true;
214             }
215             break;
216         case '\n':
217             if (lastWasCR) {
218             if (counter > (last + 1)) {
219                 doc.insertString(pos, new String JavaDoc(buff, last,
220                                             counter - last - 1), attr);
221                 pos += (counter - last - 1);
222             }
223             // else nothing to do, can skip \r, next write will
224
// write \n
225
lastWasCR = false;
226             last = counter;
227             isCRLF = true;
228             }
229             break;
230         default:
231             if (lastWasCR) {
232             isCR = true;
233             if (counter == 0) {
234                             doc.insertString(pos, "\n", attr);
235                 pos++;
236             }
237             else {
238                 buff[counter - 1] = '\n';
239             }
240             lastWasCR = false;
241             }
242             break;
243         }
244         }
245         if (last < nch) {
246         if(lastWasCR) {
247             if (last < (nch - 1)) {
248             doc.insertString(pos, new String JavaDoc(buff, last,
249                                          nch - last - 1), attr);
250             pos += (nch - last - 1);
251             }
252         }
253         else {
254             doc.insertString(pos, new String JavaDoc(buff, last,
255                                      nch - last), attr);
256             pos += (nch - last);
257         }
258         }
259         }
260     if (lastWasCR) {
261             doc.insertString(pos, "\n", attr);
262         isCR = true;
263     }
264     if (wasEmpty) {
265         if (isCRLF) {
266         doc.putProperty(EndOfLineStringProperty, "\r\n");
267         }
268         else if (isCR) {
269         doc.putProperty(EndOfLineStringProperty, "\r");
270         }
271         else {
272         doc.putProperty(EndOfLineStringProperty, "\n");
273         }
274     }
275     }
276
277     /**
278      * Writes content from a document to the given stream
279      * as plain text.
280      *
281      * @param out The stream to write to
282      * @param doc The source for the write.
283      * @param pos The location in the document to fetch the
284      * content from >= 0.
285      * @param len The amount to write out >= 0.
286      * @exception IOException on any I/O error
287      * @exception BadLocationException if pos is not within 0 and
288      * the length of the document.
289      */

290     public void write(Writer out, Document JavaDoc doc, int pos, int len)
291         throws IOException, BadLocationException JavaDoc {
292
293     if ((pos < 0) || ((pos + len) > doc.getLength())) {
294         throw new BadLocationException JavaDoc("DefaultEditorKit.write", pos);
295     }
296         Segment JavaDoc data = new Segment JavaDoc();
297         int nleft = len;
298         int offs = pos;
299     Object JavaDoc endOfLineProperty = doc.getProperty(EndOfLineStringProperty);
300     if (endOfLineProperty == null) {
301         try {
302         endOfLineProperty = System.getProperty("line.separator");
303         } catch (SecurityException JavaDoc se) { }
304     }
305     String JavaDoc endOfLine;
306     if (endOfLineProperty instanceof String JavaDoc) {
307         endOfLine = (String JavaDoc)endOfLineProperty;
308     }
309     else {
310         endOfLine = null;
311     }
312     if (endOfLineProperty != null && !endOfLine.equals("\n")) {
313         // There is an end of line string that isn't \n, have to iterate
314
// through and find all \n's and translate to end of line string.
315
while (nleft > 0) {
316         int n = Math.min(nleft, 4096);
317         doc.getText(offs, n, data);
318         int last = data.offset;
319         char[] array = data.array;
320         int maxCounter = last + data.count;
321         for (int counter = last; counter < maxCounter; counter++) {
322             if (array[counter] == '\n') {
323             if (counter > last) {
324                 out.write(array, last, counter - last);
325             }
326             out.write(endOfLine);
327             last = counter + 1;
328             }
329         }
330         if (maxCounter > last) {
331             out.write(array, last, maxCounter - last);
332         }
333         offs += n;
334         nleft -= n;
335         }
336     }
337     else {
338         // Just write out text, will already have \n, no mapping to
339
// do.
340
while (nleft > 0) {
341         int n = Math.min(nleft, 4096);
342         doc.getText(offs, n, data);
343         out.write(data.array, data.offset, data.count);
344         offs += n;
345         nleft -= n;
346         }
347     }
348     out.flush();
349     }
350
351
352     /**
353      * When reading a document if a CRLF is encountered a property
354      * with this name is added and the value will be "\r\n".
355      */

356     public static final String JavaDoc EndOfLineStringProperty = "__EndOfLine__";
357
358     // --- names of well-known actions ---------------------------
359

360     /**
361      * Name of the action to place content into the associated
362      * document. If there is a selection, it is removed before
363      * the new content is added.
364      * @see #getActions
365      */

366     public static final String JavaDoc insertContentAction = "insert-content";
367
368     /**
369      * Name of the action to place a line/paragraph break into
370      * the document. If there is a selection, it is removed before
371      * the break is added.
372      * @see #getActions
373      */

374     public static final String JavaDoc insertBreakAction = "insert-break";
375
376     /**
377      * Name of the action to place a tab character into
378      * the document. If there is a selection, it is removed before
379      * the tab is added.
380      * @see #getActions
381      */

382     public static final String JavaDoc insertTabAction = "insert-tab";
383
384     /**
385      * Name of the action to delete the character of content that
386      * precedes the current caret position.
387      * @see #getActions
388      */

389     public static final String JavaDoc deletePrevCharAction = "delete-previous";
390
391     /**
392      * Name of the action to delete the character of content that
393      * follows the current caret position.
394      * @see #getActions
395      */

396     public static final String JavaDoc deleteNextCharAction = "delete-next";
397
398     /**
399      * Name of the action to set the editor into read-only
400      * mode.
401      * @see #getActions
402      */

403     public static final String JavaDoc readOnlyAction = "set-read-only";
404
405     /**
406      * Name of the action to set the editor into writeable
407      * mode.
408      * @see #getActions
409      */

410     public static final String JavaDoc writableAction = "set-writable";
411
412     /**
413      * Name of the action to cut the selected region
414      * and place the contents into the system clipboard.
415      * @see JTextComponent#cut
416      * @see #getActions
417      */

418     public static final String JavaDoc cutAction = "cut-to-clipboard";
419
420     /**
421      * Name of the action to copy the selected region
422      * and place the contents into the system clipboard.
423      * @see JTextComponent#copy
424      * @see #getActions
425      */

426     public static final String JavaDoc copyAction = "copy-to-clipboard";
427
428     /**
429      * Name of the action to paste the contents of the
430      * system clipboard into the selected region, or before the
431      * caret if nothing is selected.
432      * @see JTextComponent#paste
433      * @see #getActions
434      */

435     public static final String JavaDoc pasteAction = "paste-from-clipboard";
436
437     /**
438      * Name of the action to create a beep.
439      * @see #getActions
440      */

441     public static final String JavaDoc beepAction = "beep";
442
443     /**
444      * Name of the action to page up vertically.
445      * @see #getActions
446      */

447     public static final String JavaDoc pageUpAction = "page-up";
448
449     /**
450      * Name of the action to page down vertically.
451      * @see #getActions
452      */

453     public static final String JavaDoc pageDownAction = "page-down";
454
455     /**
456      * Name of the action to page up vertically, and move the
457      * selection.
458      * @see #getActions
459      */

460     /*public*/ static final String JavaDoc selectionPageUpAction = "selection-page-up";
461
462     /**
463      * Name of the action to page down vertically, and move the
464      * selection.
465      * @see #getActions
466      */

467     /*public*/ static final String JavaDoc selectionPageDownAction = "selection-page-down";
468
469     /**
470      * Name of the action to page left horizontally, and move the
471      * selection.
472      * @see #getActions
473      */

474     /*public*/ static final String JavaDoc selectionPageLeftAction = "selection-page-left";
475
476     /**
477      * Name of the action to page right horizontally, and move the
478      * selection.
479      * @see #getActions
480      */

481     /*public*/ static final String JavaDoc selectionPageRightAction = "selection-page-right";
482
483     /**
484      * Name of the Action for moving the caret
485      * logically forward one position.
486      * @see #getActions
487      */

488     public static final String JavaDoc forwardAction = "caret-forward";
489
490     /**
491      * Name of the Action for moving the caret
492      * logically backward one position.
493      * @see #getActions
494      */

495     public static final String JavaDoc backwardAction = "caret-backward";
496
497     /**
498      * Name of the Action for extending the selection
499      * by moving the caret logically forward one position.
500      * @see #getActions
501      */

502     public static final String JavaDoc selectionForwardAction = "selection-forward";
503
504     /**
505      * Name of the Action for extending the selection
506      * by moving the caret logically backward one position.
507      * @see #getActions
508      */

509     public static final String JavaDoc selectionBackwardAction = "selection-backward";
510
511     /**
512      * Name of the Action for moving the caret
513      * logically upward one position.
514      * @see #getActions
515      */

516     public static final String JavaDoc upAction = "caret-up";
517
518     /**
519      * Name of the Action for moving the caret
520      * logically downward one position.
521      * @see #getActions
522      */

523     public static final String JavaDoc downAction = "caret-down";
524
525     /**
526      * Name of the Action for moving the caret
527      * logically upward one position, extending the selection.
528      * @see #getActions
529      */

530     public static final String JavaDoc selectionUpAction = "selection-up";
531
532     /**
533      * Name of the Action for moving the caret
534      * logically downward one position, extending the selection.
535      * @see #getActions
536      */

537     public static final String JavaDoc selectionDownAction = "selection-down";
538
539     /**
540      * Name of the <code>Action</code> for moving the caret
541      * to the beginning of a word.
542      * @see #getActions
543      */

544     public static final String JavaDoc beginWordAction = "caret-begin-word";
545
546     /**
547      * Name of the Action for moving the caret
548      * to the end of a word.
549      * @see #getActions
550      */

551     public static final String JavaDoc endWordAction = "caret-end-word";
552
553     /**
554      * Name of the <code>Action</code> for moving the caret
555      * to the beginning of a word, extending the selection.
556      * @see #getActions
557      */

558     public static final String JavaDoc selectionBeginWordAction = "selection-begin-word";
559
560     /**
561      * Name of the Action for moving the caret
562      * to the end of a word, extending the selection.
563      * @see #getActions
564      */

565     public static final String JavaDoc selectionEndWordAction = "selection-end-word";
566
567     /**
568      * Name of the <code>Action</code> for moving the caret to the
569      * beginning of the previous word.
570      * @see #getActions
571      */

572     public static final String JavaDoc previousWordAction = "caret-previous-word";
573
574     /**
575      * Name of the <code>Action</code> for moving the caret to the
576      * beginning of the next word.
577      * @see #getActions
578      */

579     public static final String JavaDoc nextWordAction = "caret-next-word";
580
581     /**
582      * Name of the <code>Action</code> for moving the selection to the
583      * beginning of the previous word, extending the selection.
584      * @see #getActions
585      */

586     public static final String JavaDoc selectionPreviousWordAction = "selection-previous-word";
587
588     /**
589      * Name of the <code>Action</code> for moving the selection to the
590      * beginning of the next word, extending the selection.
591      * @see #getActions
592      */

593     public static final String JavaDoc selectionNextWordAction = "selection-next-word";
594
595     /**
596      * Name of the <code>Action</code> for moving the caret
597      * to the beginning of a line.
598      * @see #getActions
599      */

600     public static final String JavaDoc beginLineAction = "caret-begin-line";
601
602     /**
603      * Name of the <code>Action</code> for moving the caret
604      * to the end of a line.
605      * @see #getActions
606      */

607     public static final String JavaDoc endLineAction = "caret-end-line";
608
609     /**
610      * Name of the <code>Action</code> for moving the caret
611      * to the beginning of a line, extending the selection.
612      * @see #getActions
613      */

614     public static final String JavaDoc selectionBeginLineAction = "selection-begin-line";
615
616     /**
617      * Name of the <code>Action</code> for moving the caret
618      * to the end of a line, extending the selection.
619      * @see #getActions
620      */

621     public static final String JavaDoc selectionEndLineAction = "selection-end-line";
622
623     /**
624      * Name of the <code>Action</code> for moving the caret
625      * to the beginning of a paragraph.
626      * @see #getActions
627      */

628     public static final String JavaDoc beginParagraphAction = "caret-begin-paragraph";
629
630     /**
631      * Name of the <code>Action</code> for moving the caret
632      * to the end of a paragraph.
633      * @see #getActions
634      */

635     public static final String JavaDoc endParagraphAction = "caret-end-paragraph";
636
637     /**
638      * Name of the <code>Action</code> for moving the caret
639      * to the beginning of a paragraph, extending the selection.
640      * @see #getActions
641      */

642     public static final String JavaDoc selectionBeginParagraphAction = "selection-begin-paragraph";
643
644     /**
645      * Name of the <code>Action</code> for moving the caret
646      * to the end of a paragraph, extending the selection.
647      * @see #getActions
648      */

649     public static final String JavaDoc selectionEndParagraphAction = "selection-end-paragraph";
650
651     /**
652      * Name of the <code>Action</code> for moving the caret
653      * to the beginning of the document.
654      * @see #getActions
655      */

656     public static final String JavaDoc beginAction = "caret-begin";
657
658     /**
659      * Name of the <code>Action</code> for moving the caret
660      * to the end of the document.
661      * @see #getActions
662      */

663     public static final String JavaDoc endAction = "caret-end";
664
665     /**
666      * Name of the <code>Action</code> for moving the caret
667      * to the beginning of the document.
668      * @see #getActions
669      */

670     public static final String JavaDoc selectionBeginAction = "selection-begin";
671
672     /**
673      * Name of the Action for moving the caret
674      * to the end of the document.
675      * @see #getActions
676      */

677     public static final String JavaDoc selectionEndAction = "selection-end";
678
679     /**
680      * Name of the Action for selecting a word around the caret.
681      * @see #getActions
682      */

683     public static final String JavaDoc selectWordAction = "select-word";
684
685     /**
686      * Name of the Action for selecting a line around the caret.
687      * @see #getActions
688      */

689     public static final String JavaDoc selectLineAction = "select-line";
690
691     /**
692      * Name of the Action for selecting a paragraph around the caret.
693      * @see #getActions
694      */

695     public static final String JavaDoc selectParagraphAction = "select-paragraph";
696
697     /**
698      * Name of the Action for selecting the entire document
699      * @see #getActions
700      */

701     public static final String JavaDoc selectAllAction = "select-all";
702
703     /**
704      * Name of the Action for removing selection
705      * @see #getActions
706      */

707     /*public*/ static final String JavaDoc unselectAction = "unselect";
708   
709     /**
710      * Name of the Action for toggling the component's orientation.
711      * @see #getActions
712      */

713     /*public*/ static final String JavaDoc toggleComponentOrientationAction
714         = "toggle-componentOrientation";
715
716     /**
717      * Name of the action that is executed by default if
718      * a <em>key typed event</em> is received and there
719      * is no keymap entry.
720      * @see #getActions
721      */

722     public static final String JavaDoc defaultKeyTypedAction = "default-typed";
723
724     // --- Action implementations ---------------------------------
725

726     private static final Action JavaDoc[] defaultActions = {
727         new InsertContentAction(), new DeletePrevCharAction(),
728         new DeleteNextCharAction(), new ReadOnlyAction(),
729         new WritableAction(), new CutAction(),
730         new CopyAction(), new PasteAction(),
731         new VerticalPageAction(pageUpAction, -1, false),
732     new VerticalPageAction(pageDownAction, 1, false),
733         new VerticalPageAction(selectionPageUpAction, -1, true),
734     new VerticalPageAction(selectionPageDownAction, 1, true),
735         new PageAction(selectionPageLeftAction, true, true),
736     new PageAction(selectionPageRightAction, false, true),
737         new InsertBreakAction(), new BeepAction(),
738         new NextVisualPositionAction(forwardAction, false,
739                      SwingConstants.EAST),
740         new NextVisualPositionAction(backwardAction, false,
741                      SwingConstants.WEST),
742         new NextVisualPositionAction(selectionForwardAction, true,
743                      SwingConstants.EAST),
744         new NextVisualPositionAction(selectionBackwardAction, true,
745                      SwingConstants.WEST),
746         new NextVisualPositionAction(upAction, false,
747                      SwingConstants.NORTH),
748         new NextVisualPositionAction(downAction, false,
749                      SwingConstants.SOUTH),
750         new NextVisualPositionAction(selectionUpAction, true,
751                      SwingConstants.NORTH),
752         new NextVisualPositionAction(selectionDownAction, true,
753                      SwingConstants.SOUTH),
754         new BeginWordAction(beginWordAction, false),
755         new EndWordAction(endWordAction, false),
756         new BeginWordAction(selectionBeginWordAction, true),
757         new EndWordAction(selectionEndWordAction, true),
758         new PreviousWordAction(previousWordAction, false),
759         new NextWordAction(nextWordAction, false),
760         new PreviousWordAction(selectionPreviousWordAction, true),
761         new NextWordAction(selectionNextWordAction, true),
762         new BeginLineAction(beginLineAction, false),
763         new EndLineAction(endLineAction, false),
764         new BeginLineAction(selectionBeginLineAction, true),
765         new EndLineAction(selectionEndLineAction, true),
766         new BeginParagraphAction(beginParagraphAction, false),
767         new EndParagraphAction(endParagraphAction, false),
768         new BeginParagraphAction(selectionBeginParagraphAction, true),
769         new EndParagraphAction(selectionEndParagraphAction, true),
770         new BeginAction(beginAction, false),
771         new EndAction(endAction, false),
772         new BeginAction(selectionBeginAction, true),
773         new EndAction(selectionEndAction, true),
774         new DefaultKeyTypedAction(), new InsertTabAction(),
775         new SelectWordAction(), new SelectLineAction(),
776         new SelectParagraphAction(), new SelectAllAction(),
777         new UnselectAction(), new ToggleComponentOrientationAction(),
778         new DumpModelAction()
779     };
780
781     /**
782      * The action that is executed by default if
783      * a <em>key typed event</em> is received and there
784      * is no keymap entry. There is a variation across
785      * different VM's in what gets sent as a <em>key typed</em>
786      * event, and this action tries to filter out the undesired
787      * events. This filters the control characters and those
788      * with the ALT modifier. It allows Control-Alt sequences
789      * through as these form legitimate unicode characters on
790      * some PC keyboards.
791      * <p>
792      * If the event doesn't get filtered, it will try to insert
793      * content into the text editor. The content is fetched
794      * from the command string of the ActionEvent. The text
795      * entry is done through the <code>replaceSelection</code>
796      * method on the target text component. This is the
797      * action that will be fired for most text entry tasks.
798      * <p>
799      * <strong>Warning:</strong>
800      * Serialized objects of this class will not be compatible with
801      * future Swing releases. The current serialization support is
802      * appropriate for short term storage or RMI between applications running
803      * the same version of Swing. As of 1.4, support for long term storage
804      * of all JavaBeans<sup><font size="-2">TM</font></sup>
805      * has been added to the <code>java.beans</code> package.
806      * Please see {@link java.beans.XMLEncoder}.
807      *
808      * @see DefaultEditorKit#defaultKeyTypedAction
809      * @see DefaultEditorKit#getActions
810      * @see Keymap#setDefaultAction
811      * @see Keymap#getDefaultAction
812      */

813     public static class DefaultKeyTypedAction extends TextAction JavaDoc {
814
815         /**
816          * Creates this object with the appropriate identifier.
817          */

818         public DefaultKeyTypedAction() {
819             super(defaultKeyTypedAction);
820         }
821
822         /**
823          * The operation to perform when this action is triggered.
824          *
825          * @param e the action event
826          */

827         public void actionPerformed(ActionEvent JavaDoc e) {
828             JTextComponent JavaDoc target = getTextComponent(e);
829             if ((target != null) && (e != null)) {
830         if ((! target.isEditable()) || (! target.isEnabled())) {
831             return;
832         }
833                 String JavaDoc content = e.getActionCommand();
834                 int mod = e.getModifiers();
835                 if ((content != null) && (content.length() > 0) &&
836                     ((mod & ActionEvent.ALT_MASK) == (mod & ActionEvent.CTRL_MASK))) {
837                     char c = content.charAt(0);
838                     if ((c >= 0x20) && (c != 0x7F)) {
839                         target.replaceSelection(content);
840                     }
841                 }
842             }
843         }
844     }
845
846     /**
847      * Places content into the associated document.
848      * If there is a selection, it is removed before
849      * the new content is added.
850      * <p>
851      * <strong>Warning:</strong>
852      * Serialized objects of this class will not be compatible with
853      * future Swing releases. The current serialization support is
854      * appropriate for short term storage or RMI between applications running
855      * the same version of Swing. As of 1.4, support for long term storage
856      * of all JavaBeans<sup><font size="-2">TM</font></sup>
857      * has been added to the <code>java.beans</code> package.
858      * Please see {@link java.beans.XMLEncoder}.
859      *
860      * @see DefaultEditorKit#insertContentAction
861      * @see DefaultEditorKit#getActions
862      */

863     public static class InsertContentAction extends TextAction JavaDoc {
864
865         /**
866          * Creates this object with the appropriate identifier.
867          */

868         public InsertContentAction() {
869             super(insertContentAction);
870         }
871
872         /**
873          * The operation to perform when this action is triggered.
874          *
875          * @param e the action event
876          */

877         public void actionPerformed(ActionEvent JavaDoc e) {
878             JTextComponent JavaDoc target = getTextComponent(e);
879             if ((target != null) && (e != null)) {
880         if ((! target.isEditable()) || (! target.isEnabled())) {
881             UIManager.getLookAndFeel().provideErrorFeedback(target);
882             return;
883         }
884                 String JavaDoc content = e.getActionCommand();
885                 if (content != null) {
886                     target.replaceSelection(content);
887                 } else {
888             UIManager.getLookAndFeel().provideErrorFeedback(target);
889                 }
890             }
891         }
892     }
893
894     /**
895      * Places a line/paragraph break into the document.
896      * If there is a selection, it is removed before
897      * the break is added.
898      * <p>
899      * <strong>Warning:</strong>
900      * Serialized objects of this class will not be compatible with
901      * future Swing releases. The current serialization support is
902      * appropriate for short term storage or RMI between applications running
903      * the same version of Swing. As of 1.4, support for long term storage
904      * of all JavaBeans<sup><font size="-2">TM</font></sup>
905      * has been added to the <code>java.beans</code> package.
906      * Please see {@link java.beans.XMLEncoder}.
907      *
908      * @see DefaultEditorKit#insertBreakAction
909      * @see DefaultEditorKit#getActions
910      */

911     public static class InsertBreakAction extends TextAction JavaDoc {
912
913         /**
914          * Creates this object with the appropriate identifier.
915          */

916         public InsertBreakAction() {
917             super(insertBreakAction);
918         }
919
920         /**
921          * The operation to perform when this action is triggered.
922          *
923          * @param e the action event
924          */

925         public void actionPerformed(ActionEvent JavaDoc e) {
926             JTextComponent JavaDoc target = getTextComponent(e);
927             if (target != null) {
928         if ((! target.isEditable()) || (! target.isEnabled())) {
929             UIManager.getLookAndFeel().provideErrorFeedback(target);
930             return;
931         }
932                 target.replaceSelection("\n");
933             }
934         }
935     }
936
937     /**
938      * Places a tab character into the document. If there
939      * is a selection, it is removed before the tab is added.
940      * <p>
941      * <strong>Warning:</strong>
942      * Serialized objects of this class will not be compatible with
943      * future Swing releases. The current serialization support is
944      * appropriate for short term storage or RMI between applications running
945      * the same version of Swing. As of 1.4, support for long term storage
946      * of all JavaBeans<sup><font size="-2">TM</font></sup>
947      * has been added to the <code>java.beans</code> package.
948      * Please see {@link java.beans.XMLEncoder}.
949      *
950      * @see DefaultEditorKit#insertTabAction
951      * @see DefaultEditorKit#getActions
952      */

953     public static class InsertTabAction extends TextAction JavaDoc {
954
955         /**
956          * Creates this object with the appropriate identifier.
957          */

958         public InsertTabAction() {
959             super(insertTabAction);
960         }
961
962         /**
963          * The operation to perform when this action is triggered.
964          *
965          * @param e the action event
966          */

967         public void actionPerformed(ActionEvent JavaDoc e) {
968             JTextComponent JavaDoc target = getTextComponent(e);
969             if (target != null) {
970         if ((! target.isEditable()) || (! target.isEnabled())) {
971             UIManager.getLookAndFeel().provideErrorFeedback(target);
972             return;
973         }
974                 target.replaceSelection("\t");
975             }
976         }
977     }
978
979     /*
980      * Deletes the character of content that precedes the
981      * current caret position.
982      * @see DefaultEditorKit#deletePrevCharAction
983      * @see DefaultEditorKit#getActions
984      */

985     static class DeletePrevCharAction extends TextAction JavaDoc {
986
987         /**
988          * Creates this object with the appropriate identifier.
989          */

990         DeletePrevCharAction() {
991             super(deletePrevCharAction);
992         }
993
994         /**
995          * The operation to perform when this action is triggered.
996          *
997          * @param e the action event
998          */

999         public void actionPerformed(ActionEvent JavaDoc e) {
1000            JTextComponent JavaDoc target = getTextComponent(e);
1001            boolean beep = true;
1002            if ((target != null) && (target.isEditable())) {
1003                try {
1004                    Document JavaDoc doc = target.getDocument();
1005                    Caret JavaDoc caret = target.getCaret();
1006                    int dot = caret.getDot();
1007                    int mark = caret.getMark();
1008                    if (dot != mark) {
1009                        doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
1010                        beep = false;
1011                    } else if (dot > 0) {
1012                        int delChars = 1;
1013                        
1014                        if (dot > 1) {
1015                            String JavaDoc dotChars = doc.getText(dot - 2, 2);
1016                            char c0 = dotChars.charAt(0);
1017                            char c1 = dotChars.charAt(1);
1018                            
1019                            if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
1020                                c1 >= '\uDC00' && c1 <= '\uDFFF') {
1021                                delChars = 2;
1022                            }
1023                        }
1024                        
1025                        doc.remove(dot - delChars, delChars);
1026                        beep = false;
1027                    }
1028                } catch (BadLocationException JavaDoc bl) {
1029                }
1030            }
1031            if (beep) {
1032        UIManager.getLookAndFeel().provideErrorFeedback(target);
1033            }
1034        }
1035    }
1036
1037    /*
1038     * Deletes the character of content that follows the
1039     * current caret position.
1040     * @see DefaultEditorKit#deleteNextCharAction
1041     * @see DefaultEditorKit#getActions
1042     */

1043    static class DeleteNextCharAction extends TextAction JavaDoc {
1044
1045        /* Create this object with the appropriate identifier. */
1046        DeleteNextCharAction() {
1047            super(deleteNextCharAction);
1048        }
1049
1050        /** The operation to perform when this action is triggered. */
1051        public void actionPerformed(ActionEvent JavaDoc e) {
1052            JTextComponent JavaDoc target = getTextComponent(e);
1053            boolean beep = true;
1054            if ((target != null) && (target.isEditable())) {
1055                try {
1056                    Document JavaDoc doc = target.getDocument();
1057                    Caret JavaDoc caret = target.getCaret();
1058                    int dot = caret.getDot();
1059                    int mark = caret.getMark();
1060                    if (dot != mark) {
1061                        doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
1062                        beep = false;
1063                    } else if (dot < doc.getLength()) {
1064                        int delChars = 1;
1065                        
1066                        if (dot < doc.getLength() - 1) {
1067                            String JavaDoc dotChars = doc.getText(dot, 2);
1068                            char c0 = dotChars.charAt(0);
1069                            char c1 = dotChars.charAt(1);
1070                            
1071                            if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
1072                                c1 >= '\uDC00' && c1 <= '\uDFFF') {
1073                                delChars = 2;
1074                            }
1075                        }
1076                        
1077                        doc.remove(dot, delChars);
1078                        beep = false;
1079                    }
1080                } catch (BadLocationException JavaDoc bl) {
1081                }
1082            }
1083            if (beep) {
1084        UIManager.getLookAndFeel().provideErrorFeedback(target);
1085            }
1086        }
1087    }
1088
1089    /*
1090     * Sets the editor into read-only mode.
1091     * @see DefaultEditorKit#readOnlyAction
1092     * @see DefaultEditorKit#getActions
1093     */

1094    static class ReadOnlyAction extends TextAction JavaDoc {
1095
1096        /* Create this object with the appropriate identifier. */
1097        ReadOnlyAction() {
1098            super(readOnlyAction);
1099        }
1100
1101        /**
1102         * The operation to perform when this action is triggered.
1103         *
1104         * @param e the action event
1105         */

1106        public void actionPerformed(ActionEvent JavaDoc e) {
1107            JTextComponent JavaDoc target = getTextComponent(e);
1108            if (target != null) {
1109                target.setEditable(false);
1110            }
1111        }
1112    }
1113
1114    /*
1115     * Sets the editor into writeable mode.
1116     * @see DefaultEditorKit#writableAction
1117     * @see DefaultEditorKit#getActions
1118     */

1119    static class WritableAction extends TextAction JavaDoc {
1120
1121        /* Create this object with the appropriate identifier. */
1122        WritableAction() {
1123            super(writableAction);
1124        }
1125
1126        /**
1127         * The operation to perform when this action is triggered.
1128         *
1129         * @param e the action event
1130         */

1131        public void actionPerformed(ActionEvent JavaDoc e) {
1132            JTextComponent JavaDoc target = getTextComponent(e);
1133            if (target != null) {
1134                target.setEditable(true);
1135            }
1136        }
1137    }
1138
1139    /**
1140     * Cuts the selected region and place its contents
1141     * into the system clipboard.
1142     * <p>
1143     * <strong>Warning:</strong>
1144     * Serialized objects of this class will not be compatible with
1145     * future Swing releases. The current serialization support is
1146     * appropriate for short term storage or RMI between applications running
1147     * the same version of Swing. As of 1.4, support for long term storage
1148     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1149     * has been added to the <code>java.beans</code> package.
1150     * Please see {@link java.beans.XMLEncoder}.
1151     *
1152     * @see DefaultEditorKit#cutAction
1153     * @see DefaultEditorKit#getActions
1154     */

1155    public static class CutAction extends TextAction JavaDoc {
1156
1157        /** Create this object with the appropriate identifier. */
1158        public CutAction() {
1159            super(cutAction);
1160        }
1161
1162        /**
1163         * The operation to perform when this action is triggered.
1164         *
1165         * @param e the action event
1166         */

1167        public void actionPerformed(ActionEvent JavaDoc e) {
1168            JTextComponent JavaDoc target = getTextComponent(e);
1169            if (target != null) {
1170                target.cut();
1171            }
1172        }
1173    }
1174
1175    /**
1176     * Copies the selected region and place its contents
1177     * into the system clipboard.
1178     * <p>
1179     * <strong>Warning:</strong>
1180     * Serialized objects of this class will not be compatible with
1181     * future Swing releases. The current serialization support is
1182     * appropriate for short term storage or RMI between applications running
1183     * the same version of Swing. As of 1.4, support for long term storage
1184     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1185     * has been added to the <code>java.beans</code> package.
1186     * Please see {@link java.beans.XMLEncoder}.
1187     *
1188     * @see DefaultEditorKit#copyAction
1189     * @see DefaultEditorKit#getActions
1190     */

1191    public static class CopyAction extends TextAction JavaDoc {
1192
1193        /** Create this object with the appropriate identifier. */
1194        public CopyAction() {
1195            super(copyAction);
1196        }
1197
1198        /**
1199         * The operation to perform when this action is triggered.
1200         *
1201         * @param e the action event
1202         */

1203        public void actionPerformed(ActionEvent JavaDoc e) {
1204            JTextComponent JavaDoc target = getTextComponent(e);
1205            if (target != null) {
1206                target.copy();
1207            }
1208        }
1209    }
1210
1211    /**
1212     * Pastes the contents of the system clipboard into the
1213     * selected region, or before the caret if nothing is
1214     * selected.
1215     * <p>
1216     * <strong>Warning:</strong>
1217     * Serialized objects of this class will not be compatible with
1218     * future Swing releases. The current serialization support is
1219     * appropriate for short term storage or RMI between applications running
1220     * the same version of Swing. As of 1.4, support for long term storage
1221     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1222     * has been added to the <code>java.beans</code> package.
1223     * Please see {@link java.beans.XMLEncoder}.
1224     *
1225     * @see DefaultEditorKit#pasteAction
1226     * @see DefaultEditorKit#getActions
1227     */

1228    public static class PasteAction extends TextAction JavaDoc {
1229
1230        /** Create this object with the appropriate identifier. */
1231        public PasteAction() {
1232            super(pasteAction);
1233        }
1234
1235        /**
1236         * The operation to perform when this action is triggered.
1237         *
1238         * @param e the action event
1239         */

1240        public void actionPerformed(ActionEvent JavaDoc e) {
1241            JTextComponent JavaDoc target = getTextComponent(e);
1242            if (target != null) {
1243                target.paste();
1244            }
1245        }
1246    }
1247
1248    /**
1249     * Creates a beep.
1250     * <p>
1251     * <strong>Warning:</strong>
1252     * Serialized objects of this class will not be compatible with
1253     * future Swing releases. The current serialization support is
1254     * appropriate for short term storage or RMI between applications running
1255     * the same version of Swing. As of 1.4, support for long term storage
1256     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1257     * has been added to the <code>java.beans</code> package.
1258     * Please see {@link java.beans.XMLEncoder}.
1259     *
1260     * @see DefaultEditorKit#beepAction
1261     * @see DefaultEditorKit#getActions
1262     */

1263    public static class BeepAction extends TextAction JavaDoc {
1264
1265        /** Create this object with the appropriate identifier. */
1266        public BeepAction() {
1267            super(beepAction);
1268        }
1269
1270        /**
1271         * The operation to perform when this action is triggered.
1272         *
1273         * @param e the action event
1274         */

1275        public void actionPerformed(ActionEvent JavaDoc e) {
1276            JTextComponent JavaDoc target = getTextComponent(e);
1277        UIManager.getLookAndFeel().provideErrorFeedback(target);
1278        }
1279    }
1280
1281    /**
1282     * Scrolls up/down vertically. The select version of this action extends
1283     * the selection, instead of simply moving the caret.
1284     *
1285     * @see DefaultEditorKit#pageUpAction
1286     * @see DefaultEditorKit#selectPageUpAction
1287     * @see DefaultEditorKit#getActions
1288     */

1289    static class VerticalPageAction extends TextAction JavaDoc {
1290
1291    /** Create this object with the appropriate identifier. */
1292    public VerticalPageAction(String JavaDoc nm, int direction, boolean select) {
1293        super(nm);
1294        this.select = select;
1295            this.direction = direction;
1296    }
1297
1298    /** The operation to perform when this action is triggered. */
1299        public void actionPerformed(ActionEvent JavaDoc e) {
1300        JTextComponent JavaDoc target = getTextComponent(e);
1301        if (target != null) {
1302        Rectangle visible = target.getVisibleRect();
1303                Rectangle newVis = new Rectangle(visible);
1304                int selectedIndex = target.getCaretPosition();
1305                int scrollAmount = target.getScrollableBlockIncrement(
1306                                  visible, SwingConstants.VERTICAL, direction);
1307                int initialY = visible.y;
1308                Caret JavaDoc caret = target.getCaret();
1309                Point magicPosition = caret.getMagicCaretPosition();
1310                int yOffset;
1311
1312                if (selectedIndex != -1) {
1313                    try {
1314                        Rectangle dotBounds = target.modelToView(
1315                                                     selectedIndex);
1316                        int x = (magicPosition != null) ? magicPosition.x :
1317                                                          dotBounds.x;
1318                        // fix for 4697612
1319
int h = dotBounds.height;
1320                        yOffset = direction *
1321                                  (int)Math.ceil(scrollAmount / (double)h) * h;
1322                        newVis.y = constrainY(target, initialY + yOffset, yOffset);
1323
1324                        int newIndex;
1325
1326                        if (visible.contains(dotBounds.x, dotBounds.y)) {
1327                            // Dot is currently visible, base the new
1328
// location off the old, or
1329
newIndex = target.viewToModel(
1330                                new Point(x, constrainY(target,
1331                                          dotBounds.y + yOffset, 0)));
1332                        }
1333                        else {
1334                            // Dot isn't visible, choose the top or the bottom
1335
// for the new location.
1336
if (direction == -1) {
1337                                newIndex = target.viewToModel(new Point(
1338                                    x, newVis.y));
1339                            }
1340                            else {
1341                                newIndex = target.viewToModel(new Point(
1342                                    x, newVis.y + visible.height));
1343                            }
1344                        }
1345                        newIndex = constrainOffset(target, newIndex);
1346                        if (newIndex != selectedIndex) {
1347                            // Make sure the new visible location contains
1348
// the location of dot, otherwise Caret will
1349
// cause an additional scroll.
1350
adjustScrollIfNecessary(target, newVis, initialY,
1351                                                    newIndex);
1352                            if (select) {
1353                                target.moveCaretPosition(newIndex);
1354                            }
1355                            else {
1356                                target.setCaretPosition(newIndex);
1357                            }
1358                        }
1359                    } catch (BadLocationException JavaDoc ble) { }
1360                } else {
1361                    yOffset = direction * scrollAmount;
1362                    newVis.y = constrainY(target, initialY + yOffset, yOffset);
1363                }
1364                if (magicPosition != null) {
1365                    caret.setMagicCaretPosition(magicPosition);
1366                }
1367        target.scrollRectToVisible(newVis);
1368        }
1369    }
1370
1371        /**
1372         * Makes sure <code>y</code> is a valid location in
1373         * <code>target</code>.
1374         */

1375        private int constrainY(JTextComponent JavaDoc target, int y, int vis) {
1376            if (y < 0) {
1377                y = 0;
1378            }
1379            else if (y + vis > target.getHeight()) {
1380                y = Math.max(0, target.getHeight() - vis);
1381            }
1382            return y;
1383        }
1384
1385        /**
1386         * Ensures that <code>offset</code> is a valid offset into the
1387         * model for <code>text</code>.
1388         */

1389        private int constrainOffset(JTextComponent JavaDoc text, int offset) {
1390            Document JavaDoc doc = text.getDocument();
1391
1392            if ((offset != 0) && (offset > doc.getLength())) {
1393                offset = doc.getLength();
1394            }
1395            if (offset < 0) {
1396                offset = 0;
1397            }
1398            return offset;
1399        }
1400
1401        /**
1402         * Adjusts the rectangle that indicates the location to scroll to
1403         * after selecting <code>index</code>.
1404         */

1405        private void adjustScrollIfNecessary(JTextComponent JavaDoc text,
1406                                             Rectangle visible, int initialY,
1407                                             int index) {
1408            try {
1409                Rectangle dotBounds = text.modelToView(index);
1410
1411                if (dotBounds.y < visible.y ||
1412                       (dotBounds.y > (visible.y + visible.height)) ||
1413                       (dotBounds.y + dotBounds.height) >
1414                       (visible.y + visible.height)) {
1415                    int y;
1416
1417                    if (dotBounds.y < visible.y) {
1418                        y = dotBounds.y;
1419                    }
1420                    else {
1421                        y = dotBounds.y + dotBounds.height - visible.height;
1422                    }
1423                    if ((direction == -1 && y < initialY) ||
1424                                        (direction == 1 && y > initialY)) {
1425                        // Only adjust if won't cause scrolling upward.
1426
visible.y = y;
1427                    }
1428                }
1429            } catch (BadLocationException JavaDoc ble) {}
1430        }
1431
1432        /**
1433         * Adjusts the Rectangle to contain the bounds of the character at
1434         * <code>index</code> in response to a page up.
1435         */

1436        private boolean select;
1437
1438        /**
1439         * Direction to scroll, 1 is down, -1 is up.
1440         */

1441        private int direction;
1442    }
1443
1444
1445    /**
1446     * Pages one view to the left or right.
1447     */

1448    static class PageAction extends TextAction JavaDoc {
1449
1450    /** Create this object with the appropriate identifier. */
1451    public PageAction(String JavaDoc nm, boolean left, boolean select) {
1452        super(nm);
1453        this.select = select;
1454        this.left = left;
1455    }
1456
1457    /** The operation to perform when this action is triggered. */
1458        public void actionPerformed(ActionEvent JavaDoc e) {
1459        JTextComponent JavaDoc target = getTextComponent(e);
1460        if (target != null) {
1461        int selectedIndex;
1462        Rectangle visible = new Rectangle();
1463        target.computeVisibleRect(visible);
1464        if (left) {
1465            visible.x = Math.max(0, visible.x - visible.width);
1466        }
1467        else {
1468            visible.x += visible.width;
1469        }
1470        
1471        selectedIndex = target.getCaretPosition();
1472        if(selectedIndex != -1) {
1473            if (left) {
1474            selectedIndex = target.viewToModel
1475                (new Point(visible.x, visible.y));
1476            }
1477            else {
1478            selectedIndex = target.viewToModel
1479                (new Point(visible.x + visible.width - 1,
1480                       visible.y + visible.height - 1));
1481            }
1482            Document JavaDoc doc = target.getDocument();
1483            if ((selectedIndex != 0) &&
1484            (selectedIndex > (doc.getLength()-1))) {
1485            selectedIndex = doc.getLength()-1;
1486            }
1487            else if(selectedIndex < 0) {
1488            selectedIndex = 0;
1489            }
1490            if (select)
1491            target.moveCaretPosition(selectedIndex);
1492            else
1493            target.setCaretPosition(selectedIndex);
1494        }
1495        }
1496    }
1497
1498        private boolean select;
1499    private boolean left;
1500    }
1501
1502    static class DumpModelAction extends TextAction JavaDoc {
1503
1504        DumpModelAction() {
1505            super("dump-model");
1506        }
1507
1508        public void actionPerformed(ActionEvent JavaDoc e) {
1509            JTextComponent JavaDoc target = getTextComponent(e);
1510            if (target != null) {
1511                Document JavaDoc d = target.getDocument();
1512                if (d instanceof AbstractDocument JavaDoc) {
1513                    ((AbstractDocument JavaDoc) d).dump(System.err);
1514                }
1515            }
1516        }
1517    }
1518
1519    /*
1520     * Action to move the selection by way of the
1521     * getNextVisualPositionFrom method. Constructor indicates direction
1522     * to use.
1523     */

1524    static class NextVisualPositionAction extends TextAction JavaDoc {
1525
1526        /**
1527         * Create this action with the appropriate identifier.
1528         * @param nm the name of the action, Action.NAME.
1529         * @param select whether to extend the selection when
1530         * changing the caret position.
1531         */

1532        NextVisualPositionAction(String JavaDoc nm, boolean select, int direction) {
1533            super(nm);
1534            this.select = select;
1535        this.direction = direction;
1536        }
1537
1538        /** The operation to perform when this action is triggered. */
1539        public void actionPerformed(ActionEvent JavaDoc e) {
1540            JTextComponent JavaDoc target = getTextComponent(e);
1541            if (target != null) {
1542        Caret JavaDoc caret = target.getCaret();
1543        DefaultCaret JavaDoc bidiCaret = (caret instanceof DefaultCaret JavaDoc) ?
1544                                  (DefaultCaret JavaDoc)caret : null;
1545        int dot = caret.getDot();
1546        Position.Bias JavaDoc[] bias = new Position.Bias JavaDoc[1];
1547        Point magicPosition = caret.getMagicCaretPosition();
1548
1549        try {
1550            if(magicPosition == null &&
1551               (direction == SwingConstants.NORTH ||
1552            direction == SwingConstants.SOUTH)) {
1553            Rectangle r = (bidiCaret != null) ?
1554                target.getUI().modelToView(target, dot,
1555                              bidiCaret.getDotBias()) :
1556                target.modelToView(dot);
1557            magicPosition = new Point(r.x, r.y);
1558            }
1559
1560                    NavigationFilter JavaDoc filter = target.getNavigationFilter();
1561
1562                    if (filter != null) {
1563                        dot = filter.getNextVisualPositionFrom
1564                                     (target, dot, (bidiCaret != null) ?
1565                                      bidiCaret.getDotBias() :
1566                                      Position.Bias.Forward, direction, bias);
1567                    }
1568                    else {
1569                        dot = target.getUI().getNextVisualPositionFrom
1570                                     (target, dot, (bidiCaret != null) ?
1571                                      bidiCaret.getDotBias() :
1572                                      Position.Bias.Forward, direction, bias);
1573                    }
1574            if(bias[0] == null) {
1575            bias[0] = Position.Bias.Forward;
1576            }
1577            if(bidiCaret != null) {
1578            if (select) {
1579                bidiCaret.moveDot(dot, bias[0]);
1580            } else {
1581                bidiCaret.setDot(dot, bias[0]);
1582            }
1583            }
1584            else {
1585            if (select) {
1586                caret.moveDot(dot);
1587            } else {
1588                caret.setDot(dot);
1589            }
1590            }
1591            if(magicPosition != null &&
1592               (direction == SwingConstants.NORTH ||
1593            direction == SwingConstants.SOUTH)) {
1594            target.getCaret().setMagicCaretPosition(magicPosition);
1595            }
1596                } catch (BadLocationException JavaDoc ex) {
1597                }
1598            }
1599        }
1600
1601        private boolean select;
1602    private int direction;
1603    }
1604            
1605    /*
1606     * Position the caret to the beginning of the word.
1607     * @see DefaultEditorKit#beginWordAction
1608     * @see DefaultEditorKit#selectBeginWordAction
1609     * @see DefaultEditorKit#getActions
1610     */

1611    static class BeginWordAction extends TextAction JavaDoc {
1612
1613        /**
1614         * Create this action with the appropriate identifier.
1615         * @param nm the name of the action, Action.NAME.
1616         * @param select whether to extend the selection when
1617         * changing the caret position.
1618         */

1619        BeginWordAction(String JavaDoc nm, boolean select) {
1620            super(nm);
1621            this.select = select;
1622        }
1623
1624        /** The operation to perform when this action is triggered. */
1625        public void actionPerformed(ActionEvent JavaDoc e) {
1626            JTextComponent JavaDoc target = getTextComponent(e);
1627            if (target != null) {
1628                try {
1629                    int offs = target.getCaretPosition();
1630                    int begOffs = Utilities.getWordStart(target, offs);
1631                    if (select) {
1632                        target.moveCaretPosition(begOffs);
1633                    } else {
1634                        target.setCaretPosition(begOffs);
1635                    }
1636                } catch (BadLocationException JavaDoc bl) {
1637            UIManager.getLookAndFeel().provideErrorFeedback(target);
1638                }
1639            }
1640        }
1641
1642        private boolean select;
1643    }
1644
1645    /*
1646     * Position the caret to the end of the word.
1647     * @see DefaultEditorKit#endWordAction
1648     * @see DefaultEditorKit#selectEndWordAction
1649     * @see DefaultEditorKit#getActions
1650     */

1651    static class EndWordAction extends TextAction JavaDoc {
1652
1653        /**
1654         * Create this action with the appropriate identifier.
1655         * @param nm the name of the action, Action.NAME.
1656         * @param select whether to extend the selection when
1657         * changing the caret position.
1658         */

1659        EndWordAction(String JavaDoc nm, boolean select) {
1660            super(nm);
1661            this.select = select;
1662        }
1663
1664        /** The operation to perform when this action is triggered. */
1665        public void actionPerformed(ActionEvent JavaDoc e) {
1666            JTextComponent JavaDoc target = getTextComponent(e);
1667            if (target != null) {
1668                try {
1669                    int offs = target.getCaretPosition();
1670                    int endOffs = Utilities.getWordEnd(target, offs);
1671                    if (select) {
1672                        target.moveCaretPosition(endOffs);
1673                    } else {
1674                        target.setCaretPosition(endOffs);
1675                    }
1676                } catch (BadLocationException JavaDoc bl) {
1677            UIManager.getLookAndFeel().provideErrorFeedback(target);
1678                }
1679            }
1680        }
1681
1682        private boolean select;
1683    }
1684
1685    /*
1686     * Position the caret to the beginning of the previous word.
1687     * @see DefaultEditorKit#previousWordAction
1688     * @see DefaultEditorKit#selectPreviousWordAction
1689     * @see DefaultEditorKit#getActions
1690     */

1691    static class PreviousWordAction extends TextAction JavaDoc {
1692
1693        /**
1694         * Create this action with the appropriate identifier.
1695         * @param nm the name of the action, Action.NAME.
1696         * @param select whether to extend the selection when
1697         * changing the caret position.
1698         */

1699        PreviousWordAction(String JavaDoc nm, boolean select) {
1700            super(nm);
1701            this.select = select;
1702        }
1703
1704        /** The operation to perform when this action is triggered. */
1705        public void actionPerformed(ActionEvent JavaDoc e) {
1706            JTextComponent JavaDoc target = getTextComponent(e);
1707            if (target != null) {
1708                int offs = target.getCaretPosition();
1709                boolean failed = false;
1710                try {
1711                    Element JavaDoc curPara =
1712                            Utilities.getParagraphElement(target, offs);
1713                    offs = Utilities.getPreviousWord(target, offs);
1714                    if(offs < curPara.getStartOffset()) {
1715                        // we should first move to the end of the
1716
// previous paragraph (bug #4278839)
1717
offs = Utilities.getParagraphElement(target, offs).
1718                                getEndOffset() - 1;
1719                    }
1720                } catch (BadLocationException JavaDoc bl) {
1721                    if (offs != 0) {
1722                        offs = 0;
1723                    }
1724                    else {
1725                        failed = true;
1726                    }
1727                }
1728                if (!failed) {
1729                    if (select) {
1730                        target.moveCaretPosition(offs);
1731                    } else {
1732                        target.setCaretPosition(offs);
1733                    }
1734                }
1735                else {
1736            UIManager.getLookAndFeel().provideErrorFeedback(target);
1737                }
1738            }
1739        }
1740
1741        private boolean select;
1742    }
1743
1744    /*
1745     * Position the caret to the next of the word.
1746     * @see DefaultEditorKit#nextWordAction
1747     * @see DefaultEditorKit#selectNextWordAction
1748     * @see DefaultEditorKit#getActions
1749     */

1750    static class NextWordAction extends TextAction JavaDoc {
1751
1752        /**
1753         * Create this action with the appropriate identifier.
1754         * @param nm the name of the action, Action.NAME.
1755         * @param select whether to extend the selection when
1756         * changing the caret position.
1757         */

1758        NextWordAction(String JavaDoc nm, boolean select) {
1759            super(nm);
1760            this.select = select;
1761        }
1762
1763        /** The operation to perform when this action is triggered. */
1764        public void actionPerformed(ActionEvent JavaDoc e) {
1765            JTextComponent JavaDoc target = getTextComponent(e);
1766            if (target != null) {
1767                int offs = target.getCaretPosition();
1768                boolean failed = false;
1769                int oldOffs = offs;
1770                Element JavaDoc curPara =
1771                        Utilities.getParagraphElement(target, offs);
1772                try {
1773                    offs = Utilities.getNextWord(target, offs);
1774                    if(offs >= curPara.getEndOffset() &&
1775                            oldOffs != curPara.getEndOffset() - 1) {
1776                        // we should first move to the end of current
1777
// paragraph (bug #4278839)
1778
offs = curPara.getEndOffset() - 1;
1779                    }
1780                } catch (BadLocationException JavaDoc bl) {
1781                    int end = target.getDocument().getLength();
1782                    if (offs != end) {
1783                        if(oldOffs != curPara.getEndOffset() - 1) {
1784                            offs = curPara.getEndOffset() - 1;
1785                        } else {
1786                        offs = end;
1787                    }
1788                    }
1789                    else {
1790                        failed = true;
1791                    }
1792                }
1793                if (!failed) {
1794                    if (select) {
1795                        target.moveCaretPosition(offs);
1796                    } else {
1797                        target.setCaretPosition(offs);
1798                    }
1799                }
1800                else {
1801            UIManager.getLookAndFeel().provideErrorFeedback(target);
1802                }
1803            }
1804        }
1805
1806        private boolean select;
1807    }
1808
1809    /*
1810     * Position the caret to the beginning of the line.
1811     * @see DefaultEditorKit#beginLineAction
1812     * @see DefaultEditorKit#selectBeginLineAction
1813     * @see DefaultEditorKit#getActions
1814     */

1815    static class BeginLineAction extends TextAction JavaDoc {
1816
1817        /**
1818         * Create this action with the appropriate identifier.
1819         * @param nm the name of the action, Action.NAME.
1820         * @param select whether to extend the selection when
1821         * changing the caret position.
1822         */

1823        BeginLineAction(String JavaDoc nm, boolean select) {
1824            super(nm);
1825            this.select = select;
1826        }
1827
1828        /** The operation to perform when this action is triggered. */
1829        public void actionPerformed(ActionEvent JavaDoc e) {
1830            JTextComponent JavaDoc target = getTextComponent(e);
1831            if (target != null) {
1832                try {
1833                    int offs = target.getCaretPosition();
1834                    int begOffs = Utilities.getRowStart(target, offs);
1835                    if (select) {
1836                        target.moveCaretPosition(begOffs);
1837                    } else {
1838                        target.setCaretPosition(begOffs);
1839                    }
1840                } catch (BadLocationException JavaDoc bl) {
1841            UIManager.getLookAndFeel().provideErrorFeedback(target);
1842                }
1843            }
1844        }
1845
1846        private boolean select;
1847    }
1848
1849    /*
1850     * Position the caret to the end of the line.
1851     * @see DefaultEditorKit#endLineAction
1852     * @see DefaultEditorKit#selectEndLineAction
1853     * @see DefaultEditorKit#getActions
1854     */

1855    static class EndLineAction extends TextAction JavaDoc {
1856
1857        /**
1858         * Create this action with the appropriate identifier.
1859         * @param nm the name of the action, Action.NAME.
1860         * @param select whether to extend the selection when
1861         * changing the caret position.
1862         */

1863        EndLineAction(String JavaDoc nm, boolean select) {
1864            super(nm);
1865            this.select = select;
1866        }
1867
1868        /** The operation to perform when this action is triggered. */
1869        public void actionPerformed(ActionEvent JavaDoc e) {
1870            JTextComponent JavaDoc target = getTextComponent(e);
1871            if (target != null) {
1872                try {
1873                    int offs = target.getCaretPosition();
1874                    int endOffs = Utilities.getRowEnd(target, offs);
1875                    if (select) {
1876                        target.moveCaretPosition(endOffs);
1877                    } else {
1878                        target.setCaretPosition(endOffs);
1879                    }
1880                } catch (BadLocationException JavaDoc bl) {
1881            UIManager.getLookAndFeel().provideErrorFeedback(target);
1882                }
1883            }
1884        }
1885
1886        private boolean select;
1887    }
1888
1889    /*
1890     * Position the caret to the beginning of the paragraph.
1891     * @see DefaultEditorKit#beginParagraphAction
1892     * @see DefaultEditorKit#selectBeginParagraphAction
1893     * @see DefaultEditorKit#getActions
1894     */

1895    static class BeginParagraphAction extends TextAction JavaDoc {
1896
1897        /**
1898         * Create this action with the appropriate identifier.
1899         * @param nm the name of the action, Action.NAME.
1900         * @param select whether to extend the selection when
1901         * changing the caret position.
1902         */

1903        BeginParagraphAction(String JavaDoc nm, boolean select) {
1904            super(nm);
1905            this.select = select;
1906        }
1907
1908        /** The operation to perform when this action is triggered. */
1909        public void actionPerformed(ActionEvent JavaDoc e) {
1910            JTextComponent JavaDoc target = getTextComponent(e);
1911            if (target != null) {
1912                int offs = target.getCaretPosition();
1913                Element JavaDoc elem = Utilities.getParagraphElement(target, offs);
1914                offs = elem.getStartOffset();
1915                if (select) {
1916                    target.moveCaretPosition(offs);
1917                } else {
1918                    target.setCaretPosition(offs);
1919                }
1920            }
1921        }
1922
1923        private boolean select;
1924    }
1925
1926    /*
1927     * Position the caret to the end of the paragraph.
1928     * @see DefaultEditorKit#endParagraphAction
1929     * @see DefaultEditorKit#selectEndParagraphAction
1930     * @see DefaultEditorKit#getActions
1931     */

1932    static class EndParagraphAction extends TextAction JavaDoc {
1933
1934        /**
1935         * Create this action with the appropriate identifier.
1936         * @param nm the name of the action, Action.NAME.
1937         * @param select whether to extend the selection when
1938         * changing the caret position.
1939         */

1940        EndParagraphAction(String JavaDoc nm, boolean select) {
1941            super(nm);
1942            this.select = select;
1943        }
1944
1945        /** The operation to perform when this action is triggered. */
1946        public void actionPerformed(ActionEvent JavaDoc e) {
1947            JTextComponent JavaDoc target = getTextComponent(e);
1948            if (target != null) {
1949                int offs = target.getCaretPosition();
1950                Element JavaDoc elem = Utilities.getParagraphElement(target, offs);
1951                offs = Math.min(target.getDocument().getLength(),
1952                elem.getEndOffset());
1953                if (select) {
1954                    target.moveCaretPosition(offs);
1955                } else {
1956                    target.setCaretPosition(offs);
1957                }
1958            }
1959        }
1960
1961        private boolean select;
1962    }
1963
1964    /*
1965     * Move the caret to the beginning of the document.
1966     * @see DefaultEditorKit#beginAction
1967     * @see DefaultEditorKit#getActions
1968     */

1969    static class BeginAction extends TextAction JavaDoc {
1970
1971        /* Create this object with the appropriate identifier. */
1972        BeginAction(String JavaDoc nm, boolean select) {
1973            super(nm);
1974            this.select = select;
1975        }
1976
1977        /** The operation to perform when this action is triggered. */
1978        public void actionPerformed(ActionEvent JavaDoc e) {
1979            JTextComponent JavaDoc target = getTextComponent(e);
1980            if (target != null) {
1981                if (select) {
1982                    target.moveCaretPosition(0);
1983                } else {
1984                    target.setCaretPosition(0);
1985                }
1986            }
1987        }
1988
1989        private boolean select;
1990    }
1991
1992    /*
1993     * Move the caret to the end of the document.
1994     * @see DefaultEditorKit#endAction
1995     * @see DefaultEditorKit#getActions
1996     */

1997    static class EndAction extends TextAction JavaDoc {
1998
1999        /* Create this object with the appropriate identifier. */
2000        EndAction(String JavaDoc nm, boolean select) {
2001            super(nm);
2002            this.select = select;
2003        }
2004
2005        /** The operation to perform when this action is triggered. */
2006        public void actionPerformed(ActionEvent JavaDoc e) {
2007            JTextComponent JavaDoc target = getTextComponent(e);
2008            if (target != null) {
2009                Document JavaDoc doc = target.getDocument();
2010                int dot = doc.getLength();
2011                if (select) {
2012                    target.moveCaretPosition(dot);
2013                } else {
2014                    target.setCaretPosition(dot);
2015                }
2016            }
2017        }
2018
2019        private boolean select;
2020    }
2021
2022    /*
2023     * Select the word around the caret
2024     * @see DefaultEditorKit#endAction
2025     * @see DefaultEditorKit#getActions
2026     */

2027    static class SelectWordAction extends TextAction JavaDoc {
2028
2029        /**
2030         * Create this action with the appropriate identifier.
2031         * @param nm the name of the action, Action.NAME.
2032         * @param select whether to extend the selection when
2033         * changing the caret position.
2034         */

2035        SelectWordAction() {
2036            super(selectWordAction);
2037            start = new BeginWordAction("pigdog", false);
2038            end = new EndWordAction("pigdog", true);
2039        }
2040
2041        /** The operation to perform when this action is triggered. */
2042        public void actionPerformed(ActionEvent JavaDoc e) {
2043            start.actionPerformed(e);
2044            end.actionPerformed(e);
2045        }
2046
2047        private Action JavaDoc start;
2048        private Action JavaDoc end;
2049    }
2050
2051    /*
2052     * Select the line around the caret
2053     * @see DefaultEditorKit#endAction
2054     * @see DefaultEditorKit#getActions
2055     */

2056    static class SelectLineAction extends TextAction JavaDoc {
2057
2058        /**
2059         * Create this action with the appropriate identifier.
2060         * @param nm the name of the action, Action.NAME.
2061         * @param select whether to extend the selection when
2062         * changing the caret position.
2063         */

2064        SelectLineAction() {
2065            super(selectLineAction);
2066            start = new BeginLineAction("pigdog", false);
2067            end = new EndLineAction("pigdog", true);
2068        }
2069
2070        /** The operation to perform when this action is triggered. */
2071        public void actionPerformed(ActionEvent JavaDoc e) {
2072            start.actionPerformed(e);
2073            end.actionPerformed(e);
2074        }
2075
2076        private Action JavaDoc start;
2077        private Action JavaDoc end;
2078    }
2079
2080    /*
2081     * Select the paragraph around the caret
2082     * @see DefaultEditorKit#endAction
2083     * @see DefaultEditorKit#getActions
2084     */

2085    static class SelectParagraphAction extends TextAction JavaDoc {
2086
2087        /**
2088         * Create this action with the appropriate identifier.
2089         * @param nm the name of the action, Action.NAME.
2090         * @param select whether to extend the selection when
2091         * changing the caret position.
2092         */

2093        SelectParagraphAction() {
2094            super(selectParagraphAction);
2095            start = new BeginParagraphAction("pigdog", false);
2096            end = new EndParagraphAction("pigdog", true);
2097        }
2098
2099        /** The operation to perform when this action is triggered. */
2100        public void actionPerformed(ActionEvent JavaDoc e) {
2101            start.actionPerformed(e);
2102            end.actionPerformed(e);
2103        }
2104
2105        private Action JavaDoc start;
2106        private Action JavaDoc end;
2107    }
2108
2109    /*
2110     * Select the entire document
2111     * @see DefaultEditorKit#endAction
2112     * @see DefaultEditorKit#getActions
2113     */

2114    static class SelectAllAction extends TextAction JavaDoc {
2115
2116        /**
2117         * Create this action with the appropriate identifier.
2118         * @param nm the name of the action, Action.NAME.
2119         * @param select whether to extend the selection when
2120         * changing the caret position.
2121         */

2122        SelectAllAction() {
2123            super(selectAllAction);
2124        }
2125
2126        /** The operation to perform when this action is triggered. */
2127        public void actionPerformed(ActionEvent JavaDoc e) {
2128            JTextComponent JavaDoc target = getTextComponent(e);
2129            if (target != null) {
2130                Document JavaDoc doc = target.getDocument();
2131                target.setCaretPosition(0);
2132                target.moveCaretPosition(doc.getLength());
2133            }
2134        }
2135
2136    }
2137
2138    /*
2139     * Remove the selection, if any.
2140     * @see DefaultEditorKit#unselectAction
2141     * @see DefaultEditorKit#getActions
2142     */

2143    static class UnselectAction extends TextAction JavaDoc {
2144
2145        /**
2146         * Create this action with the appropriate identifier.
2147         */

2148        UnselectAction() {
2149            super(unselectAction);
2150        }
2151
2152        /** The operation to perform when this action is triggered. */
2153        public void actionPerformed(ActionEvent JavaDoc e) {
2154            JTextComponent JavaDoc target = getTextComponent(e);
2155            if (target != null) {
2156                target.setCaretPosition(target.getCaretPosition());
2157            }
2158        }
2159
2160    }
2161
2162    /*
2163     * Toggles the ComponentOrientation of the text component.
2164     * @see DefaultEditorKit#toggleComponentOrientationAction
2165     * @see DefaultEditorKit#getActions
2166     */

2167    static class ToggleComponentOrientationAction extends TextAction JavaDoc {
2168
2169        /**
2170         * Create this action with the appropriate identifier.
2171         */

2172        ToggleComponentOrientationAction() {
2173            super(toggleComponentOrientationAction);
2174        }
2175
2176        /** The operation to perform when this action is triggered. */
2177        public void actionPerformed(ActionEvent JavaDoc e) {
2178            JTextComponent JavaDoc target = getTextComponent(e);
2179            if (target != null) {
2180                ComponentOrientation last = target.getComponentOrientation();
2181                ComponentOrientation next;
2182                if( last == ComponentOrientation.RIGHT_TO_LEFT )
2183                    next = ComponentOrientation.LEFT_TO_RIGHT;
2184                else
2185                    next = ComponentOrientation.RIGHT_TO_LEFT;
2186                target.setComponentOrientation(next);
2187                target.repaint();
2188            }
2189        }
2190    }
2191
2192}
2193
Popular Tags