History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/text/DefaultEditorKit.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/text/DefaultEditorKit.java+2303−0
@@ -0,0 +1,2303 @@
1+/*
2+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package javax.swing.text;
26+
27+import java.io.*;
28+import java.awt.*;
29+import java.awt.event.ActionEvent;
30+import java.text.*;
31+import javax.swing.Action;
32+import javax.swing.KeyStroke;
33+import javax.swing.SwingConstants;
34+import javax.swing.UIManager;
35+
36+/**
37+ * This is the set of things needed by a text component
38+ * to be a reasonably functioning editor for some <em>type</em>
39+ * of text document. This implementation provides a default
40+ * implementation which treats text as plain text and
41+ * provides a minimal set of actions for a simple editor.
42+ * <p>
43+ * <dl>
44+ * <dt><b><font size=+1>Newlines</font></b>
45+ * <dd>
46+ * There are two properties which deal with newlines. The
47+ * system property, <code>line.separator</code>, is defined to be
48+ * platform-dependent, either "\n", "\r", or "\r\n". There is also
49+ * a property defined in <code>DefaultEditorKit</code>, called
50+ * <a href=#EndOfLineStringProperty><code>EndOfLineStringProperty</code></a>,
51+ * which is defined automatically when a document is loaded, to be
52+ * the first occurrence of any of the newline characters.
53+ * When a document is loaded, <code>EndOfLineStringProperty</code>
54+ * is set appropriately, and when the document is written back out, the
55+ * <code>EndOfLineStringProperty</code> is used. But while the document
56+ * is in memory, the "\n" character is used to define a
57+ * newline, regardless of how the newline is defined when
58+ * the document is on disk. Therefore, for searching purposes,
59+ * "\n" should always be used. When a new document is created,
60+ * and the <code>EndOfLineStringProperty</code> has not been defined,
61+ * it will use the System property when writing out the
62+ * document.
63+ * <p>Note that <code>EndOfLineStringProperty</code> is set
64+ * on the <code>Document</code> using the <code>get/putProperty</code>
65+ * methods. Subclasses may override this behavior.
66+ *
67+ * </dl>
68+ *
69+ * @author Timothy Prinzing
70+ */
71+public class DefaultEditorKit extends EditorKit {
72+
73+ /**
74+ * default constructor for DefaultEditorKit
75+ */
76+ public DefaultEditorKit() {
77+ }
78+
79+ /**
80+ * Gets the MIME type of the data that this
81+ * kit represents support for. The default
82+ * is <code>text/plain</code>.
83+ *
84+ * @return the type
85+ */
86+ public String getContentType() {
87+ return "text/plain";
88+ }
89+
90+ /**
91+ * Fetches a factory that is suitable for producing
92+ * views of any models that are produced by this
93+ * kit. The default is to have the UI produce the
94+ * factory, so this method has no implementation.
95+ *
96+ * @return the view factory
97+ */
98+ public ViewFactory getViewFactory() {
99+ return null;
100+ }
101+
102+ /**
103+ * Fetches the set of commands that can be used
104+ * on a text component that is using a model and
105+ * view produced by this kit.
106+ *
107+ * @return the command list
108+ */
109+ public Action[] getActions() {
110+ return defaultActions;
111+ }
112+
113+ /**
114+ * Fetches a caret that can navigate through views
115+ * produced by the associated ViewFactory.
116+ *
117+ * @return the caret
118+ */
119+ public Caret createCaret() {
120+ return null;
121+ }
122+
123+ /**
124+ * Creates an uninitialized text storage model (PlainDocument)
125+ * that is appropriate for this type of editor.
126+ *
127+ * @return the model
128+ */
129+ public Document createDefaultDocument() {
130+ return new PlainDocument();
131+ }
132+
133+ /**
134+ * Inserts content from the given stream which is expected
135+ * to be in a format appropriate for this kind of content
136+ * handler.
137+ *
138+ * @param in The stream to read from
139+ * @param doc The destination for the insertion.
140+ * @param pos The location in the document to place the
141+ * content >= 0.
142+ * @exception IOException on any I/O error
143+ * @exception BadLocationException if pos represents an invalid
144+ * location within the document.
145+ */
146+ public void read(InputStream in, Document doc, int pos)
147+ throws IOException, BadLocationException {
148+
149+ read(new InputStreamReader(in), doc, pos);
150+ }
151+
152+ /**
153+ * Writes content from a document to the given stream
154+ * in a format appropriate for this kind of content handler.
155+ *
156+ * @param out The stream to write to
157+ * @param doc The source for the write.
158+ * @param pos The location in the document to fetch the
159+ * content >= 0.
160+ * @param len The amount to write out >= 0.
161+ * @exception IOException on any I/O error
162+ * @exception BadLocationException if pos represents an invalid
163+ * location within the document.
164+ */
165+ public void write(OutputStream out, Document doc, int pos, int len)
166+ throws IOException, BadLocationException {
167+ OutputStreamWriter osw = new OutputStreamWriter(out);
168+
169+ write(osw, doc, pos, len);
170+ osw.flush();
171+ }
172+
173+ /**
174+ * Gets the input attributes for the pane. This method exists for
175+ * the benefit of StyledEditorKit so that the read method will
176+ * pick up the correct attributes to apply to inserted text.
177+ * This class's implementation simply returns null.
178+ *
179+ * @return null
180+ */
181+ MutableAttributeSet getInputAttributes() {
182+ return null;
183+ }
184+
185+ /**
186+ * Inserts content from the given stream, which will be
187+ * treated as plain text.
188+ *
189+ * @param in The stream to read from
190+ * @param doc The destination for the insertion.
191+ * @param pos The location in the document to place the
192+ * content >= 0.
193+ * @exception IOException on any I/O error
194+ * @exception BadLocationException if pos represents an invalid
195+ * location within the document.
196+ */
197+ public void read(Reader in, Document doc, int pos)
198+ throws IOException, BadLocationException {
199+
200+ char[] buff = new char[4096];
201+ int nch;
202+ boolean lastWasCR = false;
203+ boolean isCRLF = false;
204+ boolean isCR = false;
205+ int last;
206+ boolean wasEmpty = (doc.getLength() == 0);
207+ AttributeSet attr = getInputAttributes();
208+
209+ // Read in a block at a time, mapping \r\n to \n, as well as single
210+ // \r's to \n's. If a \r\n is encountered, \r\n will be set as the
211+ // newline string for the document, if \r is encountered it will
212+ // be set as the newline character, otherwise the newline property
213+ // for the document will be removed.
214+ while ((nch = in.read(buff, 0, buff.length)) != -1) {
215+ last = 0;
216+ for(int counter = 0; counter < nch; counter++) {
217+ switch(buff[counter]) {
218+ case '\r':
219+ if (lastWasCR) {
220+ isCR = true;
221+ if (counter == 0) {
222+ doc.insertString(pos, "\n", attr);
223+ pos++;
224+ }
225+ else {
226+ buff[counter - 1] = '\n';
227+ }
228+ }
229+ else {
230+ lastWasCR = true;
231+ }
232+ break;
233+ case '\n':
234+ if (lastWasCR) {
235+ if (counter > (last + 1)) {
236+ doc.insertString(pos, new String(buff, last,
237+ counter - last - 1), attr);
238+ pos += (counter - last - 1);
239+ }
240+ // else nothing to do, can skip \r, next write will
241+ // write \n
242+ lastWasCR = false;
243+ last = counter;
244+ isCRLF = true;
245+ }
246+ break;
247+ default:
248+ if (lastWasCR) {
249+ isCR = true;
250+ if (counter == 0) {
251+ doc.insertString(pos, "\n", attr);
252+ pos++;
253+ }
254+ else {
255+ buff[counter - 1] = '\n';
256+ }
257+ lastWasCR = false;
258+ }
259+ break;
260+ }
261+ }
262+ if (last < nch) {
263+ if(lastWasCR) {
264+ if (last < (nch - 1)) {
265+ doc.insertString(pos, new String(buff, last,
266+ nch - last - 1), attr);
267+ pos += (nch - last - 1);
268+ }
269+ }
270+ else {
271+ doc.insertString(pos, new String(buff, last,
272+ nch - last), attr);
273+ pos += (nch - last);
274+ }
275+ }
276+ }
277+ if (lastWasCR) {
278+ doc.insertString(pos, "\n", attr);
279+ isCR = true;
280+ }
281+ if (wasEmpty) {
282+ if (isCRLF) {
283+ doc.putProperty(EndOfLineStringProperty, "\r\n");
284+ }
285+ else if (isCR) {
286+ doc.putProperty(EndOfLineStringProperty, "\r");
287+ }
288+ else {
289+ doc.putProperty(EndOfLineStringProperty, "\n");
290+ }
291+ }
292+ }
293+
294+ /**
295+ * Writes content from a document to the given stream
296+ * as plain text.
297+ *
298+ * @param out The stream to write to
299+ * @param doc The source for the write.
300+ * @param pos The location in the document to fetch the
301+ * content from >= 0.
302+ * @param len The amount to write out >= 0.
303+ * @exception IOException on any I/O error
304+ * @exception BadLocationException if pos is not within 0 and
305+ * the length of the document.
306+ */
307+ public void write(Writer out, Document doc, int pos, int len)
308+ throws IOException, BadLocationException {
309+
310+ if ((pos < 0) || ((pos + len) > doc.getLength())) {
311+ throw new BadLocationException("DefaultEditorKit.write", pos);
312+ }
313+ Segment data = new Segment();
314+ int nleft = len;
315+ int offs = pos;
316+ Object endOfLineProperty = doc.getProperty(EndOfLineStringProperty);
317+ if (endOfLineProperty == null) {
318+ try {
319+ endOfLineProperty = System.getProperty("line.separator");
320+ } catch (SecurityException se) { }
321+ }
322+ String endOfLine;
323+ if (endOfLineProperty instanceof String) {
324+ endOfLine = (String)endOfLineProperty;
325+ }
326+ else {
327+ endOfLine = null;
328+ }
329+ if (endOfLineProperty != null && !endOfLine.equals("\n")) {
330+ // There is an end of line string that isn't \n, have to iterate
331+ // through and find all \n's and translate to end of line string.
332+ while (nleft > 0) {
333+ int n = Math.min(nleft, 4096);
334+ doc.getText(offs, n, data);
335+ int last = data.offset;
336+ char[] array = data.array;
337+ int maxCounter = last + data.count;
338+ for (int counter = last; counter < maxCounter; counter++) {
339+ if (array[counter] == '\n') {
340+ if (counter > last) {
341+ out.write(array, last, counter - last);
342+ }
343+ out.write(endOfLine);
344+ last = counter + 1;
345+ }
346+ }
347+ if (maxCounter > last) {
348+ out.write(array, last, maxCounter - last);
349+ }
350+ offs += n;
351+ nleft -= n;
352+ }
353+ }
354+ else {
355+ // Just write out text, will already have \n, no mapping to
356+ // do.
357+ while (nleft > 0) {
358+ int n = Math.min(nleft, 4096);
359+ doc.getText(offs, n, data);
360+ out.write(data.array, data.offset, data.count);
361+ offs += n;
362+ nleft -= n;
363+ }
364+ }
365+ out.flush();
366+ }
367+
368+
369+ /**
370+ * When reading a document if a CRLF is encountered a property
371+ * with this name is added and the value will be "\r\n".
372+ */
373+ public static final String EndOfLineStringProperty = "__EndOfLine__";
374+
375+ // --- names of well-known actions ---------------------------
376+
377+ /**
378+ * Name of the action to place content into the associated
379+ * document. If there is a selection, it is removed before
380+ * the new content is added.
381+ * @see #getActions
382+ */
383+ public static final String insertContentAction = "insert-content";
384+
385+ /**
386+ * Name of the action to place a line/paragraph break into
387+ * the document. If there is a selection, it is removed before
388+ * the break is added.
389+ * @see #getActions
390+ */
391+ public static final String insertBreakAction = "insert-break";
392+
393+ /**
394+ * Name of the action to place a tab character into
395+ * the document. If there is a selection, it is removed before
396+ * the tab is added.
397+ * @see #getActions
398+ */
399+ public static final String insertTabAction = "insert-tab";
400+
401+ /**
402+ * Name of the action to delete the character of content that
403+ * precedes the current caret position.
404+ * @see #getActions
405+ */
406+ public static final String deletePrevCharAction = "delete-previous";
407+
408+ /**
409+ * Name of the action to delete the character of content that
410+ * follows the current caret position.
411+ * @see #getActions
412+ */
413+ public static final String deleteNextCharAction = "delete-next";
414+
415+ /**
416+ * Name of the action to delete the word that
417+ * follows the beginning of the selection.
418+ * @see #getActions
419+ * @see JTextComponent#getSelectionStart
420+ * @since 1.6
421+ */
422+ public static final String deleteNextWordAction = "delete-next-word";
423+
424+ /**
425+ * Name of the action to delete the word that
426+ * precedes the beginning of the selection.
427+ * @see #getActions
428+ * @see JTextComponent#getSelectionStart
429+ * @since 1.6
430+ */
431+ public static final String deletePrevWordAction = "delete-previous-word";
432+
433+ /**
434+ * Name of the action to set the editor into read-only
435+ * mode.
436+ * @see #getActions
437+ */
438+ public static final String readOnlyAction = "set-read-only";
439+
440+ /**
441+ * Name of the action to set the editor into writeable
442+ * mode.
443+ * @see #getActions
444+ */
445+ public static final String writableAction = "set-writable";
446+
447+ /**
448+ * Name of the action to cut the selected region
449+ * and place the contents into the system clipboard.
450+ * @see JTextComponent#cut
451+ * @see #getActions
452+ */
453+ public static final String cutAction = "cut-to-clipboard";
454+
455+ /**
456+ * Name of the action to copy the selected region
457+ * and place the contents into the system clipboard.
458+ * @see JTextComponent#copy
459+ * @see #getActions
460+ */
461+ public static final String copyAction = "copy-to-clipboard";
462+
463+ /**
464+ * Name of the action to paste the contents of the
465+ * system clipboard into the selected region, or before the
466+ * caret if nothing is selected.
467+ * @see JTextComponent#paste
468+ * @see #getActions
469+ */
470+ public static final String pasteAction = "paste-from-clipboard";
471+
472+ /**
473+ * Name of the action to create a beep.
474+ * @see #getActions
475+ */
476+ public static final String beepAction = "beep";
477+
478+ /**
479+ * Name of the action to page up vertically.
480+ * @see #getActions
481+ */
482+ public static final String pageUpAction = "page-up";
483+
484+ /**
485+ * Name of the action to page down vertically.
486+ * @see #getActions
487+ */
488+ public static final String pageDownAction = "page-down";
489+
490+ /**
491+ * Name of the action to page up vertically, and move the
492+ * selection.
493+ * @see #getActions
494+ */
495+ /*public*/ static final String selectionPageUpAction = "selection-page-up";
496+
497+ /**
498+ * Name of the action to page down vertically, and move the
499+ * selection.
500+ * @see #getActions
501+ */
502+ /*public*/ static final String selectionPageDownAction = "selection-page-down";
503+
504+ /**
505+ * Name of the action to page left horizontally, and move the
506+ * selection.
507+ * @see #getActions
508+ */
509+ /*public*/ static final String selectionPageLeftAction = "selection-page-left";
510+
511+ /**
512+ * Name of the action to page right horizontally, and move the
513+ * selection.
514+ * @see #getActions
515+ */
516+ /*public*/ static final String selectionPageRightAction = "selection-page-right";
517+
518+ /**
519+ * Name of the Action for moving the caret
520+ * logically forward one position.
521+ * @see #getActions
522+ */
523+ public static final String forwardAction = "caret-forward";
524+
525+ /**
526+ * Name of the Action for moving the caret
527+ * logically backward one position.
528+ * @see #getActions
529+ */
530+ public static final String backwardAction = "caret-backward";
531+
532+ /**
533+ * Name of the Action for extending the selection
534+ * by moving the caret logically forward one position.
535+ * @see #getActions
536+ */
537+ public static final String selectionForwardAction = "selection-forward";
538+
539+ /**
540+ * Name of the Action for extending the selection
541+ * by moving the caret logically backward one position.
542+ * @see #getActions
543+ */
544+ public static final String selectionBackwardAction = "selection-backward";
545+
546+ /**
547+ * Name of the Action for moving the caret
548+ * logically upward one position.
549+ * @see #getActions
550+ */
551+ public static final String upAction = "caret-up";
552+
553+ /**
554+ * Name of the Action for moving the caret
555+ * logically downward one position.
556+ * @see #getActions
557+ */
558+ public static final String downAction = "caret-down";
559+
560+ /**
561+ * Name of the Action for moving the caret
562+ * logically upward one position, extending the selection.
563+ * @see #getActions
564+ */
565+ public static final String selectionUpAction = "selection-up";
566+
567+ /**
568+ * Name of the Action for moving the caret
569+ * logically downward one position, extending the selection.
570+ * @see #getActions
571+ */
572+ public static final String selectionDownAction = "selection-down";
573+
574+ /**
575+ * Name of the <code>Action</code> for moving the caret
576+ * to the beginning of a word.
577+ * @see #getActions
578+ */
579+ public static final String beginWordAction = "caret-begin-word";
580+
581+ /**
582+ * Name of the Action for moving the caret
583+ * to the end of a word.
584+ * @see #getActions
585+ */
586+ public static final String endWordAction = "caret-end-word";
587+
588+ /**
589+ * Name of the <code>Action</code> for moving the caret
590+ * to the beginning of a word, extending the selection.
591+ * @see #getActions
592+ */
593+ public static final String selectionBeginWordAction = "selection-begin-word";
594+
595+ /**
596+ * Name of the Action for moving the caret
597+ * to the end of a word, extending the selection.
598+ * @see #getActions
599+ */
600+ public static final String selectionEndWordAction = "selection-end-word";
601+
602+ /**
603+ * Name of the <code>Action</code> for moving the caret to the
604+ * beginning of the previous word.
605+ * @see #getActions
606+ */
607+ public static final String previousWordAction = "caret-previous-word";
608+
609+ /**
610+ * Name of the <code>Action</code> for moving the caret to the
611+ * beginning of the next word.
612+ * @see #getActions
613+ */
614+ public static final String nextWordAction = "caret-next-word";
615+
616+ /**
617+ * Name of the <code>Action</code> for moving the selection to the
618+ * beginning of the previous word, extending the selection.
619+ * @see #getActions
620+ */
621+ public static final String selectionPreviousWordAction = "selection-previous-word";
622+
623+ /**
624+ * Name of the <code>Action</code> for moving the selection to the
625+ * beginning of the next word, extending the selection.
626+ * @see #getActions
627+ */
628+ public static final String selectionNextWordAction = "selection-next-word";
629+
630+ /**
631+ * Name of the <code>Action</code> for moving the caret
632+ * to the beginning of a line.
633+ * @see #getActions
634+ */
635+ public static final String beginLineAction = "caret-begin-line";
636+
637+ /**
638+ * Name of the <code>Action</code> for moving the caret
639+ * to the end of a line.
640+ * @see #getActions
641+ */
642+ public static final String endLineAction = "caret-end-line";
643+
644+ /**
645+ * Name of the <code>Action</code> for moving the caret
646+ * to the beginning of a line, extending the selection.
647+ * @see #getActions
648+ */
649+ public static final String selectionBeginLineAction = "selection-begin-line";
650+
651+ /**
652+ * Name of the <code>Action</code> for moving the caret
653+ * to the end of a line, extending the selection.
654+ * @see #getActions
655+ */
656+ public static final String selectionEndLineAction = "selection-end-line";
657+
658+ /**
659+ * Name of the <code>Action</code> for moving the caret
660+ * to the beginning of a paragraph.
661+ * @see #getActions
662+ */
663+ public static final String beginParagraphAction = "caret-begin-paragraph";
664+
665+ /**
666+ * Name of the <code>Action</code> for moving the caret
667+ * to the end of a paragraph.
668+ * @see #getActions
669+ */
670+ public static final String endParagraphAction = "caret-end-paragraph";
671+
672+ /**
673+ * Name of the <code>Action</code> for moving the caret
674+ * to the beginning of a paragraph, extending the selection.
675+ * @see #getActions
676+ */
677+ public static final String selectionBeginParagraphAction = "selection-begin-paragraph";
678+
679+ /**
680+ * Name of the <code>Action</code> for moving the caret
681+ * to the end of a paragraph, extending the selection.
682+ * @see #getActions
683+ */
684+ public static final String selectionEndParagraphAction = "selection-end-paragraph";
685+
686+ /**
687+ * Name of the <code>Action</code> for moving the caret
688+ * to the beginning of the document.
689+ * @see #getActions
690+ */
691+ public static final String beginAction = "caret-begin";
692+
693+ /**
694+ * Name of the <code>Action</code> for moving the caret
695+ * to the end of the document.
696+ * @see #getActions
697+ */
698+ public static final String endAction = "caret-end";
699+
700+ /**
701+ * Name of the <code>Action</code> for moving the caret
702+ * to the beginning of the document.
703+ * @see #getActions
704+ */
705+ public static final String selectionBeginAction = "selection-begin";
706+
707+ /**
708+ * Name of the Action for moving the caret
709+ * to the end of the document.
710+ * @see #getActions
711+ */
712+ public static final String selectionEndAction = "selection-end";
713+
714+ /**
715+ * Name of the Action for selecting a word around the caret.
716+ * @see #getActions
717+ */
718+ public static final String selectWordAction = "select-word";
719+
720+ /**
721+ * Name of the Action for selecting a line around the caret.
722+ * @see #getActions
723+ */
724+ public static final String selectLineAction = "select-line";
725+
726+ /**
727+ * Name of the Action for selecting a paragraph around the caret.
728+ * @see #getActions
729+ */
730+ public static final String selectParagraphAction = "select-paragraph";
731+
732+ /**
733+ * Name of the Action for selecting the entire document
734+ * @see #getActions
735+ */
736+ public static final String selectAllAction = "select-all";
737+
738+ /**
739+ * Name of the Action for removing selection
740+ * @see #getActions
741+ */
742+ /*public*/ static final String unselectAction = "unselect";
743+
744+ /**
745+ * Name of the Action for toggling the component's orientation.
746+ * @see #getActions
747+ */
748+ /*public*/ static final String toggleComponentOrientationAction
749+ = "toggle-componentOrientation";
750+
751+ /**
752+ * Name of the action that is executed by default if
753+ * a <em>key typed event</em> is received and there
754+ * is no keymap entry.
755+ * @see #getActions
756+ */
757+ public static final String defaultKeyTypedAction = "default-typed";
758+
759+ // --- Action implementations ---------------------------------
760+
761+ private static final Action[] defaultActions = {
762+ new InsertContentAction(), new DeletePrevCharAction(),
763+ new DeleteNextCharAction(), new ReadOnlyAction(),
764+ new DeleteWordAction(deletePrevWordAction),
765+ new DeleteWordAction(deleteNextWordAction),
766+ new WritableAction(), new CutAction(),
767+ new CopyAction(), new PasteAction(),
768+ new VerticalPageAction(pageUpAction, -1, false),
769+ new VerticalPageAction(pageDownAction, 1, false),
770+ new VerticalPageAction(selectionPageUpAction, -1, true),
771+ new VerticalPageAction(selectionPageDownAction, 1, true),
772+ new PageAction(selectionPageLeftAction, true, true),
773+ new PageAction(selectionPageRightAction, false, true),
774+ new InsertBreakAction(), new BeepAction(),
775+ new NextVisualPositionAction(forwardAction, false,
776+ SwingConstants.EAST),
777+ new NextVisualPositionAction(backwardAction, false,
778+ SwingConstants.WEST),
779+ new NextVisualPositionAction(selectionForwardAction, true,
780+ SwingConstants.EAST),
781+ new NextVisualPositionAction(selectionBackwardAction, true,
782+ SwingConstants.WEST),
783+ new NextVisualPositionAction(upAction, false,
784+ SwingConstants.NORTH),
785+ new NextVisualPositionAction(downAction, false,
786+ SwingConstants.SOUTH),
787+ new NextVisualPositionAction(selectionUpAction, true,
788+ SwingConstants.NORTH),
789+ new NextVisualPositionAction(selectionDownAction, true,
790+ SwingConstants.SOUTH),
791+ new BeginWordAction(beginWordAction, false),
792+ new EndWordAction(endWordAction, false),
793+ new BeginWordAction(selectionBeginWordAction, true),
794+ new EndWordAction(selectionEndWordAction, true),
795+ new PreviousWordAction(previousWordAction, false),
796+ new NextWordAction(nextWordAction, false),
797+ new PreviousWordAction(selectionPreviousWordAction, true),
798+ new NextWordAction(selectionNextWordAction, true),
799+ new BeginLineAction(beginLineAction, false),
800+ new EndLineAction(endLineAction, false),
801+ new BeginLineAction(selectionBeginLineAction, true),
802+ new EndLineAction(selectionEndLineAction, true),
803+ new BeginParagraphAction(beginParagraphAction, false),
804+ new EndParagraphAction(endParagraphAction, false),
805+ new BeginParagraphAction(selectionBeginParagraphAction, true),
806+ new EndParagraphAction(selectionEndParagraphAction, true),
807+ new BeginAction(beginAction, false),
808+ new EndAction(endAction, false),
809+ new BeginAction(selectionBeginAction, true),
810+ new EndAction(selectionEndAction, true),
811+ new DefaultKeyTypedAction(), new InsertTabAction(),
812+ new SelectWordAction(), new SelectLineAction(),
813+ new SelectParagraphAction(), new SelectAllAction(),
814+ new UnselectAction(), new ToggleComponentOrientationAction(),
815+ new DumpModelAction()
816+ };
817+
818+ /**
819+ * The action that is executed by default if
820+ * a <em>key typed event</em> is received and there
821+ * is no keymap entry. There is a variation across
822+ * different VM's in what gets sent as a <em>key typed</em>
823+ * event, and this action tries to filter out the undesired
824+ * events. This filters the control characters and those
825+ * with the ALT modifier. It allows Control-Alt sequences
826+ * through as these form legitimate unicode characters on
827+ * some PC keyboards.
828+ * <p>
829+ * If the event doesn't get filtered, it will try to insert
830+ * content into the text editor. The content is fetched
831+ * from the command string of the ActionEvent. The text
832+ * entry is done through the <code>replaceSelection</code>
833+ * method on the target text component. This is the
834+ * action that will be fired for most text entry tasks.
835+ * <p>
836+ * <strong>Warning:</strong>
837+ * Serialized objects of this class will not be compatible with
838+ * future Swing releases. The current serialization support is
839+ * appropriate for short term storage or RMI between applications running
840+ * the same version of Swing. As of 1.4, support for long term storage
841+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
842+ * has been added to the <code>java.beans</code> package.
843+ * Please see {@link java.beans.XMLEncoder}.
844+ *
845+ * @see DefaultEditorKit#defaultKeyTypedAction
846+ * @see DefaultEditorKit#getActions
847+ * @see Keymap#setDefaultAction
848+ * @see Keymap#getDefaultAction
849+ */
850+ public static class DefaultKeyTypedAction extends TextAction {
851+
852+ /**
853+ * Creates this object with the appropriate identifier.
854+ */
855+ public DefaultKeyTypedAction() {
856+ super(defaultKeyTypedAction);
857+ }
858+
859+ /**
860+ * The operation to perform when this action is triggered.
861+ *
862+ * @param e the action event
863+ */
864+ public void actionPerformed(ActionEvent e) {
865+ JTextComponent target = getTextComponent(e);
866+ if ((target != null) && (e != null)) {
867+ if ((! target.isEditable()) || (! target.isEnabled())) {
868+ return;
869+ }
870+ String content = e.getActionCommand();
871+ int mod = e.getModifiers();
872+ if ((content != null) && (content.length() > 0) &&
873+ ((mod & ActionEvent.ALT_MASK) == (mod & ActionEvent.CTRL_MASK))) {
874+ char c = content.charAt(0);
875+ if ((c >= 0x20) && (c != 0x7F)) {
876+ target.replaceSelection(content);
877+ }
878+ }
879+ }
880+ }
881+ }
882+
883+ /**
884+ * Places content into the associated document.
885+ * If there is a selection, it is removed before
886+ * the new content is added.
887+ * <p>
888+ * <strong>Warning:</strong>
889+ * Serialized objects of this class will not be compatible with
890+ * future Swing releases. The current serialization support is
891+ * appropriate for short term storage or RMI between applications running
892+ * the same version of Swing. As of 1.4, support for long term storage
893+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
894+ * has been added to the <code>java.beans</code> package.
895+ * Please see {@link java.beans.XMLEncoder}.
896+ *
897+ * @see DefaultEditorKit#insertContentAction
898+ * @see DefaultEditorKit#getActions
899+ */
900+ public static class InsertContentAction extends TextAction {
901+
902+ /**
903+ * Creates this object with the appropriate identifier.
904+ */
905+ public InsertContentAction() {
906+ super(insertContentAction);
907+ }
908+
909+ /**
910+ * The operation to perform when this action is triggered.
911+ *
912+ * @param e the action event
913+ */
914+ public void actionPerformed(ActionEvent e) {
915+ JTextComponent target = getTextComponent(e);
916+ if ((target != null) && (e != null)) {
917+ if ((! target.isEditable()) || (! target.isEnabled())) {
918+ UIManager.getLookAndFeel().provideErrorFeedback(target);
919+ return;
920+ }
921+ String content = e.getActionCommand();
922+ if (content != null) {
923+ target.replaceSelection(content);
924+ } else {
925+ UIManager.getLookAndFeel().provideErrorFeedback(target);
926+ }
927+ }
928+ }
929+ }
930+
931+ /**
932+ * Places a line/paragraph break into the document.
933+ * If there is a selection, it is removed before
934+ * the break is added.
935+ * <p>
936+ * <strong>Warning:</strong>
937+ * Serialized objects of this class will not be compatible with
938+ * future Swing releases. The current serialization support is
939+ * appropriate for short term storage or RMI between applications running
940+ * the same version of Swing. As of 1.4, support for long term storage
941+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
942+ * has been added to the <code>java.beans</code> package.
943+ * Please see {@link java.beans.XMLEncoder}.
944+ *
945+ * @see DefaultEditorKit#insertBreakAction
946+ * @see DefaultEditorKit#getActions
947+ */
948+ public static class InsertBreakAction extends TextAction {
949+
950+ /**
951+ * Creates this object with the appropriate identifier.
952+ */
953+ public InsertBreakAction() {
954+ super(insertBreakAction);
955+ }
956+
957+ /**
958+ * The operation to perform when this action is triggered.
959+ *
960+ * @param e the action event
961+ */
962+ public void actionPerformed(ActionEvent e) {
963+ JTextComponent target = getTextComponent(e);
964+ if (target != null) {
965+ if ((! target.isEditable()) || (! target.isEnabled())) {
966+ UIManager.getLookAndFeel().provideErrorFeedback(target);
967+ return;
968+ }
969+ target.replaceSelection("\n");
970+ }
971+ }
972+ }
973+
974+ /**
975+ * Places a tab character into the document. If there
976+ * is a selection, it is removed before the tab is added.
977+ * <p>
978+ * <strong>Warning:</strong>
979+ * Serialized objects of this class will not be compatible with
980+ * future Swing releases. The current serialization support is
981+ * appropriate for short term storage or RMI between applications running
982+ * the same version of Swing. As of 1.4, support for long term storage
983+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
984+ * has been added to the <code>java.beans</code> package.
985+ * Please see {@link java.beans.XMLEncoder}.
986+ *
987+ * @see DefaultEditorKit#insertTabAction
988+ * @see DefaultEditorKit#getActions
989+ */
990+ public static class InsertTabAction extends TextAction {
991+
992+ /**
993+ * Creates this object with the appropriate identifier.
994+ */
995+ public InsertTabAction() {
996+ super(insertTabAction);
997+ }
998+
999+ /**
1000+ * The operation to perform when this action is triggered.
1001+ *
1002+ * @param e the action event
1003+ */
1004+ public void actionPerformed(ActionEvent e) {
1005+ JTextComponent target = getTextComponent(e);
1006+ if (target != null) {
1007+ if ((! target.isEditable()) || (! target.isEnabled())) {
1008+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1009+ return;
1010+ }
1011+ target.replaceSelection("\t");
1012+ }
1013+ }
1014+ }
1015+
1016+ /*
1017+ * Deletes the character of content that precedes the
1018+ * current caret position.
1019+ * @see DefaultEditorKit#deletePrevCharAction
1020+ * @see DefaultEditorKit#getActions
1021+ */
1022+ static class DeletePrevCharAction extends TextAction {
1023+
1024+ /**
1025+ * Creates this object with the appropriate identifier.
1026+ */
1027+ DeletePrevCharAction() {
1028+ super(deletePrevCharAction);
1029+ }
1030+
1031+ /**
1032+ * The operation to perform when this action is triggered.
1033+ *
1034+ * @param e the action event
1035+ */
1036+ public void actionPerformed(ActionEvent e) {
1037+ JTextComponent target = getTextComponent(e);
1038+ boolean beep = true;
1039+ if ((target != null) && (target.isEditable())) {
1040+ try {
1041+ Document doc = target.getDocument();
1042+ Caret caret = target.getCaret();
1043+ int dot = caret.getDot();
1044+ int mark = caret.getMark();
1045+ if (dot != mark) {
1046+ doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
1047+ beep = false;
1048+ } else if (dot > 0) {
1049+ int delChars = 1;
1050+
1051+ if (dot > 1) {
1052+ String dotChars = doc.getText(dot - 2, 2);
1053+ char c0 = dotChars.charAt(0);
1054+ char c1 = dotChars.charAt(1);
1055+
1056+ if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
1057+ c1 >= '\uDC00' && c1 <= '\uDFFF') {
1058+ delChars = 2;
1059+ }
1060+ }
1061+
1062+ doc.remove(dot - delChars, delChars);
1063+ beep = false;
1064+ }
1065+ } catch (BadLocationException bl) {
1066+ }
1067+ }
1068+ if (beep) {
1069+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1070+ }
1071+ }
1072+ }
1073+
1074+ /*
1075+ * Deletes the character of content that follows the
1076+ * current caret position.
1077+ * @see DefaultEditorKit#deleteNextCharAction
1078+ * @see DefaultEditorKit#getActions
1079+ */
1080+ static class DeleteNextCharAction extends TextAction {
1081+
1082+ /* Create this object with the appropriate identifier. */
1083+ DeleteNextCharAction() {
1084+ super(deleteNextCharAction);
1085+ }
1086+
1087+ /** The operation to perform when this action is triggered. */
1088+ public void actionPerformed(ActionEvent e) {
1089+ JTextComponent target = getTextComponent(e);
1090+ boolean beep = true;
1091+ if ((target != null) && (target.isEditable())) {
1092+ try {
1093+ Document doc = target.getDocument();
1094+ Caret caret = target.getCaret();
1095+ int dot = caret.getDot();
1096+ int mark = caret.getMark();
1097+ if (dot != mark) {
1098+ doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
1099+ beep = false;
1100+ } else if (dot < doc.getLength()) {
1101+ int delChars = 1;
1102+
1103+ if (dot < doc.getLength() - 1) {
1104+ String dotChars = doc.getText(dot, 2);
1105+ char c0 = dotChars.charAt(0);
1106+ char c1 = dotChars.charAt(1);
1107+
1108+ if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
1109+ c1 >= '\uDC00' && c1 <= '\uDFFF') {
1110+ delChars = 2;
1111+ }
1112+ }
1113+
1114+ doc.remove(dot, delChars);
1115+ beep = false;
1116+ }
1117+ } catch (BadLocationException bl) {
1118+ }
1119+ }
1120+ if (beep) {
1121+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1122+ }
1123+ }
1124+ }
1125+
1126+
1127+ /*
1128+ * Deletes the word that precedes/follows the beginning of the selection.
1129+ * @see DefaultEditorKit#getActions
1130+ */
1131+ static class DeleteWordAction extends TextAction {
1132+ DeleteWordAction(String name) {
1133+ super(name);
1134+ assert (name == deletePrevWordAction)
1135+ || (name == deleteNextWordAction);
1136+ }
1137+ /**
1138+ * The operation to perform when this action is triggered.
1139+ *
1140+ * @param e the action event
1141+ */
1142+ public void actionPerformed(ActionEvent e) {
1143+ final JTextComponent target = getTextComponent(e);
1144+ if ((target != null) && (e != null)) {
1145+ if ((! target.isEditable()) || (! target.isEnabled())) {
1146+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1147+ return;
1148+ }
1149+ boolean beep = true;
1150+ try {
1151+ final int start = target.getSelectionStart();
1152+ final Element line =
1153+ Utilities.getParagraphElement(target, start);
1154+ int end;
1155+ if (deleteNextWordAction == getValue(Action.NAME)) {
1156+ end = Utilities.
1157+ getNextWordInParagraph(target, line, start, false);
1158+ if (end == java.text.BreakIterator.DONE) {
1159+ //last word in the paragraph
1160+ final int endOfLine = line.getEndOffset();
1161+ if (start == endOfLine - 1) {
1162+ //for last position remove last \n
1163+ end = endOfLine;
1164+ } else {
1165+ //remove to the end of the paragraph
1166+ end = endOfLine - 1;
1167+ }
1168+ }
1169+ } else {
1170+ end = Utilities.
1171+ getPrevWordInParagraph(target, line, start);
1172+ if (end == java.text.BreakIterator.DONE) {
1173+ //there is no previous word in the paragraph
1174+ final int startOfLine = line.getStartOffset();
1175+ if (start == startOfLine) {
1176+ //for first position remove previous \n
1177+ end = startOfLine - 1;
1178+ } else {
1179+ //remove to the start of the paragraph
1180+ end = startOfLine;
1181+ }
1182+ }
1183+ }
1184+ int offs = Math.min(start, end);
1185+ int len = Math.abs(end - start);
1186+ if (offs >= 0) {
1187+ target.getDocument().remove(offs, len);
1188+ beep = false;
1189+ }
1190+ } catch (BadLocationException ignore) {
1191+ }
1192+ if (beep) {
1193+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1194+ }
1195+ }
1196+ }
1197+ }
1198+
1199+
1200+ /*
1201+ * Sets the editor into read-only mode.
1202+ * @see DefaultEditorKit#readOnlyAction
1203+ * @see DefaultEditorKit#getActions
1204+ */
1205+ static class ReadOnlyAction extends TextAction {
1206+
1207+ /* Create this object with the appropriate identifier. */
1208+ ReadOnlyAction() {
1209+ super(readOnlyAction);
1210+ }
1211+
1212+ /**
1213+ * The operation to perform when this action is triggered.
1214+ *
1215+ * @param e the action event
1216+ */
1217+ public void actionPerformed(ActionEvent e) {
1218+ JTextComponent target = getTextComponent(e);
1219+ if (target != null) {
1220+ target.setEditable(false);
1221+ }
1222+ }
1223+ }
1224+
1225+ /*
1226+ * Sets the editor into writeable mode.
1227+ * @see DefaultEditorKit#writableAction
1228+ * @see DefaultEditorKit#getActions
1229+ */
1230+ static class WritableAction extends TextAction {
1231+
1232+ /* Create this object with the appropriate identifier. */
1233+ WritableAction() {
1234+ super(writableAction);
1235+ }
1236+
1237+ /**
1238+ * The operation to perform when this action is triggered.
1239+ *
1240+ * @param e the action event
1241+ */
1242+ public void actionPerformed(ActionEvent e) {
1243+ JTextComponent target = getTextComponent(e);
1244+ if (target != null) {
1245+ target.setEditable(true);
1246+ }
1247+ }
1248+ }
1249+
1250+ /**
1251+ * Cuts the selected region and place its contents
1252+ * into the system clipboard.
1253+ * <p>
1254+ * <strong>Warning:</strong>
1255+ * Serialized objects of this class will not be compatible with
1256+ * future Swing releases. The current serialization support is
1257+ * appropriate for short term storage or RMI between applications running
1258+ * the same version of Swing. As of 1.4, support for long term storage
1259+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
1260+ * has been added to the <code>java.beans</code> package.
1261+ * Please see {@link java.beans.XMLEncoder}.
1262+ *
1263+ * @see DefaultEditorKit#cutAction
1264+ * @see DefaultEditorKit#getActions
1265+ */
1266+ public static class CutAction extends TextAction {
1267+
1268+ /** Create this object with the appropriate identifier. */
1269+ public CutAction() {
1270+ super(cutAction);
1271+ }
1272+
1273+ /**
1274+ * The operation to perform when this action is triggered.
1275+ *
1276+ * @param e the action event
1277+ */
1278+ public void actionPerformed(ActionEvent e) {
1279+ JTextComponent target = getTextComponent(e);
1280+ if (target != null) {
1281+ target.cut();
1282+ }
1283+ }
1284+ }
1285+
1286+ /**
1287+ * Copies the selected region and place its contents
1288+ * into the system clipboard.
1289+ * <p>
1290+ * <strong>Warning:</strong>
1291+ * Serialized objects of this class will not be compatible with
1292+ * future Swing releases. The current serialization support is
1293+ * appropriate for short term storage or RMI between applications running
1294+ * the same version of Swing. As of 1.4, support for long term storage
1295+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
1296+ * has been added to the <code>java.beans</code> package.
1297+ * Please see {@link java.beans.XMLEncoder}.
1298+ *
1299+ * @see DefaultEditorKit#copyAction
1300+ * @see DefaultEditorKit#getActions
1301+ */
1302+ public static class CopyAction extends TextAction {
1303+
1304+ /** Create this object with the appropriate identifier. */
1305+ public CopyAction() {
1306+ super(copyAction);
1307+ }
1308+
1309+ /**
1310+ * The operation to perform when this action is triggered.
1311+ *
1312+ * @param e the action event
1313+ */
1314+ public void actionPerformed(ActionEvent e) {
1315+ JTextComponent target = getTextComponent(e);
1316+ if (target != null) {
1317+ target.copy();
1318+ }
1319+ }
1320+ }
1321+
1322+ /**
1323+ * Pastes the contents of the system clipboard into the
1324+ * selected region, or before the caret if nothing is
1325+ * selected.
1326+ * <p>
1327+ * <strong>Warning:</strong>
1328+ * Serialized objects of this class will not be compatible with
1329+ * future Swing releases. The current serialization support is
1330+ * appropriate for short term storage or RMI between applications running
1331+ * the same version of Swing. As of 1.4, support for long term storage
1332+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
1333+ * has been added to the <code>java.beans</code> package.
1334+ * Please see {@link java.beans.XMLEncoder}.
1335+ *
1336+ * @see DefaultEditorKit#pasteAction
1337+ * @see DefaultEditorKit#getActions
1338+ */
1339+ public static class PasteAction extends TextAction {
1340+
1341+ /** Create this object with the appropriate identifier. */
1342+ public PasteAction() {
1343+ super(pasteAction);
1344+ }
1345+
1346+ /**
1347+ * The operation to perform when this action is triggered.
1348+ *
1349+ * @param e the action event
1350+ */
1351+ public void actionPerformed(ActionEvent e) {
1352+ JTextComponent target = getTextComponent(e);
1353+ if (target != null) {
1354+ target.paste();
1355+ }
1356+ }
1357+ }
1358+
1359+ /**
1360+ * Creates a beep.
1361+ * <p>
1362+ * <strong>Warning:</strong>
1363+ * Serialized objects of this class will not be compatible with
1364+ * future Swing releases. The current serialization support is
1365+ * appropriate for short term storage or RMI between applications running
1366+ * the same version of Swing. As of 1.4, support for long term storage
1367+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
1368+ * has been added to the <code>java.beans</code> package.
1369+ * Please see {@link java.beans.XMLEncoder}.
1370+ *
1371+ * @see DefaultEditorKit#beepAction
1372+ * @see DefaultEditorKit#getActions
1373+ */
1374+ public static class BeepAction extends TextAction {
1375+
1376+ /** Create this object with the appropriate identifier. */
1377+ public BeepAction() {
1378+ super(beepAction);
1379+ }
1380+
1381+ /**
1382+ * The operation to perform when this action is triggered.
1383+ *
1384+ * @param e the action event
1385+ */
1386+ public void actionPerformed(ActionEvent e) {
1387+ JTextComponent target = getTextComponent(e);
1388+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1389+ }
1390+ }
1391+
1392+ /**
1393+ * Scrolls up/down vertically. The select version of this action extends
1394+ * the selection, instead of simply moving the caret.
1395+ *
1396+ * @see DefaultEditorKit#pageUpAction
1397+ * @see DefaultEditorKit#pageDownAction
1398+ * @see DefaultEditorKit#getActions
1399+ */
1400+ static class VerticalPageAction extends TextAction {
1401+
1402+ /** Create this object with the appropriate identifier. */
1403+ public VerticalPageAction(String nm, int direction, boolean select) {
1404+ super(nm);
1405+ this.select = select;
1406+ this.direction = direction;
1407+ }
1408+
1409+ /** The operation to perform when this action is triggered. */
1410+ public void actionPerformed(ActionEvent e) {
1411+ JTextComponent target = getTextComponent(e);
1412+ if (target != null) {
1413+ Rectangle visible = target.getVisibleRect();
1414+ Rectangle newVis = new Rectangle(visible);
1415+ int selectedIndex = target.getCaretPosition();
1416+ int scrollAmount = direction *
1417+ target.getScrollableBlockIncrement(
1418+ visible, SwingConstants.VERTICAL, direction);
1419+ int initialY = visible.y;
1420+ Caret caret = target.getCaret();
1421+ Point magicPosition = caret.getMagicCaretPosition();
1422+
1423+ if (selectedIndex != -1) {
1424+ try {
1425+ Rectangle dotBounds = target.modelToView(
1426+ selectedIndex);
1427+ int x = (magicPosition != null) ? magicPosition.x :
1428+ dotBounds.x;
1429+ int h = dotBounds.height;
1430+ if (h > 0) {
1431+ // We want to scroll by a multiple of caret height,
1432+ // rounding towards lower integer
1433+ scrollAmount = scrollAmount / h * h;
1434+ }
1435+ newVis.y = constrainY(target,
1436+ initialY + scrollAmount, visible.height);
1437+
1438+ int newIndex;
1439+
1440+ if (visible.contains(dotBounds.x, dotBounds.y)) {
1441+ // Dot is currently visible, base the new
1442+ // location off the old, or
1443+ newIndex = target.viewToModel(
1444+ new Point(x, constrainY(target,
1445+ dotBounds.y + scrollAmount, 0)));
1446+ }
1447+ else {
1448+ // Dot isn't visible, choose the top or the bottom
1449+ // for the new location.
1450+ if (direction == -1) {
1451+ newIndex = target.viewToModel(new Point(
1452+ x, newVis.y));
1453+ }
1454+ else {
1455+ newIndex = target.viewToModel(new Point(
1456+ x, newVis.y + visible.height));
1457+ }
1458+ }
1459+ newIndex = constrainOffset(target, newIndex);
1460+ if (newIndex != selectedIndex) {
1461+ // Make sure the new visible location contains
1462+ // the location of dot, otherwise Caret will
1463+ // cause an additional scroll.
1464+ int newY = getAdjustedY(target, newVis, newIndex);
1465+
1466+ if (direction == -1 && newY <= initialY || direction == 1 && newY >= initialY) {
1467+ // Change index and correct newVis.y only if won't cause scrolling upward
1468+ newVis.y = newY;
1469+
1470+ if (select) {
1471+ target.moveCaretPosition(newIndex);
1472+ } else {
1473+ target.setCaretPosition(newIndex);
1474+ }
1475+ }
1476+ }
1477+ } catch (BadLocationException ble) { }
1478+ } else {
1479+ newVis.y = constrainY(target,
1480+ initialY + scrollAmount, visible.height);
1481+ }
1482+ if (magicPosition != null) {
1483+ caret.setMagicCaretPosition(magicPosition);
1484+ }
1485+ target.scrollRectToVisible(newVis);
1486+ }
1487+ }
1488+
1489+ /**
1490+ * Makes sure <code>y</code> is a valid location in
1491+ * <code>target</code>.
1492+ */
1493+ private int constrainY(JTextComponent target, int y, int vis) {
1494+ if (y < 0) {
1495+ y = 0;
1496+ }
1497+ else if (y + vis > target.getHeight()) {
1498+ y = Math.max(0, target.getHeight() - vis);
1499+ }
1500+ return y;
1501+ }
1502+
1503+ /**
1504+ * Ensures that <code>offset</code> is a valid offset into the
1505+ * model for <code>text</code>.
1506+ */
1507+ private int constrainOffset(JTextComponent text, int offset) {
1508+ Document doc = text.getDocument();
1509+
1510+ if ((offset != 0) && (offset > doc.getLength())) {
1511+ offset = doc.getLength();
1512+ }
1513+ if (offset < 0) {
1514+ offset = 0;
1515+ }
1516+ return offset;
1517+ }
1518+
1519+ /**
1520+ * Returns adjustsed {@code y} position that indicates the location to scroll to
1521+ * after selecting <code>index</code>.
1522+ */
1523+ private int getAdjustedY(JTextComponent text, Rectangle visible, int index) {
1524+ int result = visible.y;
1525+
1526+ try {
1527+ Rectangle dotBounds = text.modelToView(index);
1528+
1529+ if (dotBounds.y < visible.y) {
1530+ result = dotBounds.y;
1531+ } else {
1532+ if ((dotBounds.y > visible.y + visible.height) ||
1533+ (dotBounds.y + dotBounds.height > visible.y + visible.height)) {
1534+ result = dotBounds.y + dotBounds.height - visible.height;
1535+ }
1536+ }
1537+ } catch (BadLocationException ble) {
1538+ }
1539+
1540+ return result;
1541+ }
1542+
1543+ /**
1544+ * Adjusts the Rectangle to contain the bounds of the character at
1545+ * <code>index</code> in response to a page up.
1546+ */
1547+ private boolean select;
1548+
1549+ /**
1550+ * Direction to scroll, 1 is down, -1 is up.
1551+ */
1552+ private int direction;
1553+ }
1554+
1555+
1556+ /**
1557+ * Pages one view to the left or right.
1558+ */
1559+ static class PageAction extends TextAction {
1560+
1561+ /** Create this object with the appropriate identifier. */
1562+ public PageAction(String nm, boolean left, boolean select) {
1563+ super(nm);
1564+ this.select = select;
1565+ this.left = left;
1566+ }
1567+
1568+ /** The operation to perform when this action is triggered. */
1569+ public void actionPerformed(ActionEvent e) {
1570+ JTextComponent target = getTextComponent(e);
1571+ if (target != null) {
1572+ int selectedIndex;
1573+ Rectangle visible = new Rectangle();
1574+ target.computeVisibleRect(visible);
1575+ if (left) {
1576+ visible.x = Math.max(0, visible.x - visible.width);
1577+ }
1578+ else {
1579+ visible.x += visible.width;
1580+ }
1581+
1582+ selectedIndex = target.getCaretPosition();
1583+ if(selectedIndex != -1) {
1584+ if (left) {
1585+ selectedIndex = target.viewToModel
1586+ (new Point(visible.x, visible.y));
1587+ }
1588+ else {
1589+ selectedIndex = target.viewToModel
1590+ (new Point(visible.x + visible.width - 1,
1591+ visible.y + visible.height - 1));
1592+ }
1593+ Document doc = target.getDocument();
1594+ if ((selectedIndex != 0) &&
1595+ (selectedIndex > (doc.getLength()-1))) {
1596+ selectedIndex = doc.getLength()-1;
1597+ }
1598+ else if(selectedIndex < 0) {
1599+ selectedIndex = 0;
1600+ }
1601+ if (select)
1602+ target.moveCaretPosition(selectedIndex);
1603+ else
1604+ target.setCaretPosition(selectedIndex);
1605+ }
1606+ }
1607+ }
1608+
1609+ private boolean select;
1610+ private boolean left;
1611+ }
1612+
1613+ static class DumpModelAction extends TextAction {
1614+
1615+ DumpModelAction() {
1616+ super("dump-model");
1617+ }
1618+
1619+ public void actionPerformed(ActionEvent e) {
1620+ JTextComponent target = getTextComponent(e);
1621+ if (target != null) {
1622+ Document d = target.getDocument();
1623+ if (d instanceof AbstractDocument) {
1624+ ((AbstractDocument) d).dump(System.err);
1625+ }
1626+ }
1627+ }
1628+ }
1629+
1630+ /*
1631+ * Action to move the selection by way of the
1632+ * getNextVisualPositionFrom method. Constructor indicates direction
1633+ * to use.
1634+ */
1635+ static class NextVisualPositionAction extends TextAction {
1636+
1637+ /**
1638+ * Create this action with the appropriate identifier.
1639+ * @param nm the name of the action, Action.NAME.
1640+ * @param select whether to extend the selection when
1641+ * changing the caret position.
1642+ */
1643+ NextVisualPositionAction(String nm, boolean select, int direction) {
1644+ super(nm);
1645+ this.select = select;
1646+ this.direction = direction;
1647+ }
1648+
1649+ /** The operation to perform when this action is triggered. */
1650+ public void actionPerformed(ActionEvent e) {
1651+ JTextComponent target = getTextComponent(e);
1652+ if (target != null) {
1653+ Caret caret = target.getCaret();
1654+ DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ?
1655+ (DefaultCaret)caret : null;
1656+ int dot = caret.getDot();
1657+ Position.Bias[] bias = new Position.Bias[1];
1658+ Point magicPosition = caret.getMagicCaretPosition();
1659+
1660+ try {
1661+ if(magicPosition == null &&
1662+ (direction == SwingConstants.NORTH ||
1663+ direction == SwingConstants.SOUTH)) {
1664+ Rectangle r = (bidiCaret != null) ?
1665+ target.getUI().modelToView(target, dot,
1666+ bidiCaret.getDotBias()) :
1667+ target.modelToView(dot);
1668+ magicPosition = new Point(r.x, r.y);
1669+ }
1670+
1671+ NavigationFilter filter = target.getNavigationFilter();
1672+
1673+ if (filter != null) {
1674+ dot = filter.getNextVisualPositionFrom
1675+ (target, dot, (bidiCaret != null) ?
1676+ bidiCaret.getDotBias() :
1677+ Position.Bias.Forward, direction, bias);
1678+ }
1679+ else {
1680+ dot = target.getUI().getNextVisualPositionFrom
1681+ (target, dot, (bidiCaret != null) ?
1682+ bidiCaret.getDotBias() :
1683+ Position.Bias.Forward, direction, bias);
1684+ }
1685+ if(bias[0] == null) {
1686+ bias[0] = Position.Bias.Forward;
1687+ }
1688+ if(bidiCaret != null) {
1689+ if (select) {
1690+ bidiCaret.moveDot(dot, bias[0]);
1691+ } else {
1692+ bidiCaret.setDot(dot, bias[0]);
1693+ }
1694+ }
1695+ else {
1696+ if (select) {
1697+ caret.moveDot(dot);
1698+ } else {
1699+ caret.setDot(dot);
1700+ }
1701+ }
1702+ if(magicPosition != null &&
1703+ (direction == SwingConstants.NORTH ||
1704+ direction == SwingConstants.SOUTH)) {
1705+ target.getCaret().setMagicCaretPosition(magicPosition);
1706+ }
1707+ } catch (BadLocationException ex) {
1708+ }
1709+ }
1710+ }
1711+
1712+ private boolean select;
1713+ private int direction;
1714+ }
1715+
1716+ /*
1717+ * Position the caret to the beginning of the word.
1718+ * @see DefaultEditorKit#beginWordAction
1719+ * @see DefaultEditorKit#selectBeginWordAction
1720+ * @see DefaultEditorKit#getActions
1721+ */
1722+ static class BeginWordAction extends TextAction {
1723+
1724+ /**
1725+ * Create this action with the appropriate identifier.
1726+ * @param nm the name of the action, Action.NAME.
1727+ * @param select whether to extend the selection when
1728+ * changing the caret position.
1729+ */
1730+ BeginWordAction(String nm, boolean select) {
1731+ super(nm);
1732+ this.select = select;
1733+ }
1734+
1735+ /** The operation to perform when this action is triggered. */
1736+ public void actionPerformed(ActionEvent e) {
1737+ JTextComponent target = getTextComponent(e);
1738+ if (target != null) {
1739+ try {
1740+ int offs = target.getCaretPosition();
1741+ int begOffs = Utilities.getWordStart(target, offs);
1742+ if (select) {
1743+ target.moveCaretPosition(begOffs);
1744+ } else {
1745+ target.setCaretPosition(begOffs);
1746+ }
1747+ } catch (BadLocationException bl) {
1748+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1749+ }
1750+ }
1751+ }
1752+
1753+ private boolean select;
1754+ }
1755+
1756+ /*
1757+ * Position the caret to the end of the word.
1758+ * @see DefaultEditorKit#endWordAction
1759+ * @see DefaultEditorKit#selectEndWordAction
1760+ * @see DefaultEditorKit#getActions
1761+ */
1762+ static class EndWordAction extends TextAction {
1763+
1764+ /**
1765+ * Create this action with the appropriate identifier.
1766+ * @param nm the name of the action, Action.NAME.
1767+ * @param select whether to extend the selection when
1768+ * changing the caret position.
1769+ */
1770+ EndWordAction(String nm, boolean select) {
1771+ super(nm);
1772+ this.select = select;
1773+ }
1774+
1775+ /** The operation to perform when this action is triggered. */
1776+ public void actionPerformed(ActionEvent e) {
1777+ JTextComponent target = getTextComponent(e);
1778+ if (target != null) {
1779+ try {
1780+ int offs = target.getCaretPosition();
1781+ int endOffs = Utilities.getWordEnd(target, offs);
1782+ if (select) {
1783+ target.moveCaretPosition(endOffs);
1784+ } else {
1785+ target.setCaretPosition(endOffs);
1786+ }
1787+ } catch (BadLocationException bl) {
1788+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1789+ }
1790+ }
1791+ }
1792+
1793+ private boolean select;
1794+ }
1795+
1796+ /*
1797+ * Position the caret to the beginning of the previous word.
1798+ * @see DefaultEditorKit#previousWordAction
1799+ * @see DefaultEditorKit#selectPreviousWordAction
1800+ * @see DefaultEditorKit#getActions
1801+ */
1802+ static class PreviousWordAction extends TextAction {
1803+
1804+ /**
1805+ * Create this action with the appropriate identifier.
1806+ * @param nm the name of the action, Action.NAME.
1807+ * @param select whether to extend the selection when
1808+ * changing the caret position.
1809+ */
1810+ PreviousWordAction(String nm, boolean select) {
1811+ super(nm);
1812+ this.select = select;
1813+ }
1814+
1815+ /** The operation to perform when this action is triggered. */
1816+ public void actionPerformed(ActionEvent e) {
1817+ JTextComponent target = getTextComponent(e);
1818+ if (target != null) {
1819+ int offs = target.getCaretPosition();
1820+ boolean failed = false;
1821+ try {
1822+ Element curPara =
1823+ Utilities.getParagraphElement(target, offs);
1824+ offs = Utilities.getPreviousWord(target, offs);
1825+ if(offs < curPara.getStartOffset()) {
1826+ // we should first move to the end of the
1827+ // previous paragraph (bug #4278839)
1828+ offs = Utilities.getParagraphElement(target, offs).
1829+ getEndOffset() - 1;
1830+ }
1831+ } catch (BadLocationException bl) {
1832+ if (offs != 0) {
1833+ offs = 0;
1834+ }
1835+ else {
1836+ failed = true;
1837+ }
1838+ }
1839+ if (!failed) {
1840+ if (select) {
1841+ target.moveCaretPosition(offs);
1842+ } else {
1843+ target.setCaretPosition(offs);
1844+ }
1845+ }
1846+ else {
1847+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1848+ }
1849+ }
1850+ }
1851+
1852+ private boolean select;
1853+ }
1854+
1855+ /*
1856+ * Position the caret to the next of the word.
1857+ * @see DefaultEditorKit#nextWordAction
1858+ * @see DefaultEditorKit#selectNextWordAction
1859+ * @see DefaultEditorKit#getActions
1860+ */
1861+ static class NextWordAction extends TextAction {
1862+
1863+ /**
1864+ * Create this action with the appropriate identifier.
1865+ * @param nm the name of the action, Action.NAME.
1866+ * @param select whether to extend the selection when
1867+ * changing the caret position.
1868+ */
1869+ NextWordAction(String nm, boolean select) {
1870+ super(nm);
1871+ this.select = select;
1872+ }
1873+
1874+ /** The operation to perform when this action is triggered. */
1875+ public void actionPerformed(ActionEvent e) {
1876+ JTextComponent target = getTextComponent(e);
1877+ if (target != null) {
1878+ int offs = target.getCaretPosition();
1879+ boolean failed = false;
1880+ int oldOffs = offs;
1881+ Element curPara =
1882+ Utilities.getParagraphElement(target, offs);
1883+ try {
1884+ offs = Utilities.getNextWord(target, offs);
1885+ if(offs >= curPara.getEndOffset() &&
1886+ oldOffs != curPara.getEndOffset() - 1) {
1887+ // we should first move to the end of current
1888+ // paragraph (bug #4278839)
1889+ offs = curPara.getEndOffset() - 1;
1890+ }
1891+ } catch (BadLocationException bl) {
1892+ int end = target.getDocument().getLength();
1893+ if (offs != end) {
1894+ if(oldOffs != curPara.getEndOffset() - 1) {
1895+ offs = curPara.getEndOffset() - 1;
1896+ } else {
1897+ offs = end;
1898+ }
1899+ }
1900+ else {
1901+ failed = true;
1902+ }
1903+ }
1904+ if (!failed) {
1905+ if (select) {
1906+ target.moveCaretPosition(offs);
1907+ } else {
1908+ target.setCaretPosition(offs);
1909+ }
1910+ }
1911+ else {
1912+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1913+ }
1914+ }
1915+ }
1916+
1917+ private boolean select;
1918+ }
1919+
1920+ /*
1921+ * Position the caret to the beginning of the line.
1922+ * @see DefaultEditorKit#beginLineAction
1923+ * @see DefaultEditorKit#selectBeginLineAction
1924+ * @see DefaultEditorKit#getActions
1925+ */
1926+ static class BeginLineAction extends TextAction {
1927+
1928+ /**
1929+ * Create this action with the appropriate identifier.
1930+ * @param nm the name of the action, Action.NAME.
1931+ * @param select whether to extend the selection when
1932+ * changing the caret position.
1933+ */
1934+ BeginLineAction(String nm, boolean select) {
1935+ super(nm);
1936+ this.select = select;
1937+ }
1938+
1939+ /** The operation to perform when this action is triggered. */
1940+ public void actionPerformed(ActionEvent e) {
1941+ JTextComponent target = getTextComponent(e);
1942+ if (target != null) {
1943+ try {
1944+ int offs = target.getCaretPosition();
1945+ int begOffs = Utilities.getRowStart(target, offs);
1946+ if (select) {
1947+ target.moveCaretPosition(begOffs);
1948+ } else {
1949+ target.setCaretPosition(begOffs);
1950+ }
1951+ } catch (BadLocationException bl) {
1952+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1953+ }
1954+ }
1955+ }
1956+
1957+ private boolean select;
1958+ }
1959+
1960+ /*
1961+ * Position the caret to the end of the line.
1962+ * @see DefaultEditorKit#endLineAction
1963+ * @see DefaultEditorKit#selectEndLineAction
1964+ * @see DefaultEditorKit#getActions
1965+ */
1966+ static class EndLineAction extends TextAction {
1967+
1968+ /**
1969+ * Create this action with the appropriate identifier.
1970+ * @param nm the name of the action, Action.NAME.
1971+ * @param select whether to extend the selection when
1972+ * changing the caret position.
1973+ */
1974+ EndLineAction(String nm, boolean select) {
1975+ super(nm);
1976+ this.select = select;
1977+ }
1978+
1979+ /** The operation to perform when this action is triggered. */
1980+ public void actionPerformed(ActionEvent e) {
1981+ JTextComponent target = getTextComponent(e);
1982+ if (target != null) {
1983+ try {
1984+ int offs = target.getCaretPosition();
1985+ int endOffs = Utilities.getRowEnd(target, offs);
1986+ if (select) {
1987+ target.moveCaretPosition(endOffs);
1988+ } else {
1989+ target.setCaretPosition(endOffs);
1990+ }
1991+ } catch (BadLocationException bl) {
1992+ UIManager.getLookAndFeel().provideErrorFeedback(target);
1993+ }
1994+ }
1995+ }
1996+
1997+ private boolean select;
1998+ }
1999+
2000+ /*
2001+ * Position the caret to the beginning of the paragraph.
2002+ * @see DefaultEditorKit#beginParagraphAction
2003+ * @see DefaultEditorKit#selectBeginParagraphAction
2004+ * @see DefaultEditorKit#getActions
2005+ */
2006+ static class BeginParagraphAction extends TextAction {
2007+
2008+ /**
2009+ * Create this action with the appropriate identifier.
2010+ * @param nm the name of the action, Action.NAME.
2011+ * @param select whether to extend the selection when
2012+ * changing the caret position.
2013+ */
2014+ BeginParagraphAction(String nm, boolean select) {
2015+ super(nm);
2016+ this.select = select;
2017+ }
2018+
2019+ /** The operation to perform when this action is triggered. */
2020+ public void actionPerformed(ActionEvent e) {
2021+ JTextComponent target = getTextComponent(e);
2022+ if (target != null) {
2023+ int offs = target.getCaretPosition();
2024+ Element elem = Utilities.getParagraphElement(target, offs);
2025+ offs = elem.getStartOffset();
2026+ if (select) {
2027+ target.moveCaretPosition(offs);
2028+ } else {
2029+ target.setCaretPosition(offs);
2030+ }
2031+ }
2032+ }
2033+
2034+ private boolean select;
2035+ }
2036+
2037+ /*
2038+ * Position the caret to the end of the paragraph.
2039+ * @see DefaultEditorKit#endParagraphAction
2040+ * @see DefaultEditorKit#selectEndParagraphAction
2041+ * @see DefaultEditorKit#getActions
2042+ */
2043+ static class EndParagraphAction extends TextAction {
2044+
2045+ /**
2046+ * Create this action with the appropriate identifier.
2047+ * @param nm the name of the action, Action.NAME.
2048+ * @param select whether to extend the selection when
2049+ * changing the caret position.
2050+ */
2051+ EndParagraphAction(String nm, boolean select) {
2052+ super(nm);
2053+ this.select = select;
2054+ }
2055+
2056+ /** The operation to perform when this action is triggered. */
2057+ public void actionPerformed(ActionEvent e) {
2058+ JTextComponent target = getTextComponent(e);
2059+ if (target != null) {
2060+ int offs = target.getCaretPosition();
2061+ Element elem = Utilities.getParagraphElement(target, offs);
2062+ offs = Math.min(target.getDocument().getLength(),
2063+ elem.getEndOffset());
2064+ if (select) {
2065+ target.moveCaretPosition(offs);
2066+ } else {
2067+ target.setCaretPosition(offs);
2068+ }
2069+ }
2070+ }
2071+
2072+ private boolean select;
2073+ }
2074+
2075+ /*
2076+ * Move the caret to the beginning of the document.
2077+ * @see DefaultEditorKit#beginAction
2078+ * @see DefaultEditorKit#getActions
2079+ */
2080+ static class BeginAction extends TextAction {
2081+
2082+ /* Create this object with the appropriate identifier. */
2083+ BeginAction(String nm, boolean select) {
2084+ super(nm);
2085+ this.select = select;
2086+ }
2087+
2088+ /** The operation to perform when this action is triggered. */
2089+ public void actionPerformed(ActionEvent e) {
2090+ JTextComponent target = getTextComponent(e);
2091+ if (target != null) {
2092+ if (select) {
2093+ target.moveCaretPosition(0);
2094+ } else {
2095+ target.setCaretPosition(0);
2096+ }
2097+ }
2098+ }
2099+
2100+ private boolean select;
2101+ }
2102+
2103+ /*
2104+ * Move the caret to the end of the document.
2105+ * @see DefaultEditorKit#endAction
2106+ * @see DefaultEditorKit#getActions
2107+ */
2108+ static class EndAction extends TextAction {
2109+
2110+ /* Create this object with the appropriate identifier. */
2111+ EndAction(String nm, boolean select) {
2112+ super(nm);
2113+ this.select = select;
2114+ }
2115+
2116+ /** The operation to perform when this action is triggered. */
2117+ public void actionPerformed(ActionEvent e) {
2118+ JTextComponent target = getTextComponent(e);
2119+ if (target != null) {
2120+ Document doc = target.getDocument();
2121+ int dot = doc.getLength();
2122+ if (select) {
2123+ target.moveCaretPosition(dot);
2124+ } else {
2125+ target.setCaretPosition(dot);
2126+ }
2127+ }
2128+ }
2129+
2130+ private boolean select;
2131+ }
2132+
2133+ /*
2134+ * Select the word around the caret
2135+ * @see DefaultEditorKit#endAction
2136+ * @see DefaultEditorKit#getActions
2137+ */
2138+ static class SelectWordAction extends TextAction {
2139+
2140+ /**
2141+ * Create this action with the appropriate identifier.
2142+ * @param nm the name of the action, Action.NAME.
2143+ * @param select whether to extend the selection when
2144+ * changing the caret position.
2145+ */
2146+ SelectWordAction() {
2147+ super(selectWordAction);
2148+ start = new BeginWordAction("pigdog", false);
2149+ end = new EndWordAction("pigdog", true);
2150+ }
2151+
2152+ /** The operation to perform when this action is triggered. */
2153+ public void actionPerformed(ActionEvent e) {
2154+ start.actionPerformed(e);
2155+ end.actionPerformed(e);
2156+ }
2157+
2158+ private Action start;
2159+ private Action end;
2160+ }
2161+
2162+ /*
2163+ * Select the line around the caret
2164+ * @see DefaultEditorKit#endAction
2165+ * @see DefaultEditorKit#getActions
2166+ */
2167+ static class SelectLineAction extends TextAction {
2168+
2169+ /**
2170+ * Create this action with the appropriate identifier.
2171+ * @param nm the name of the action, Action.NAME.
2172+ * @param select whether to extend the selection when
2173+ * changing the caret position.
2174+ */
2175+ SelectLineAction() {
2176+ super(selectLineAction);
2177+ start = new BeginLineAction("pigdog", false);
2178+ end = new EndLineAction("pigdog", true);
2179+ }
2180+
2181+ /** The operation to perform when this action is triggered. */
2182+ public void actionPerformed(ActionEvent e) {
2183+ start.actionPerformed(e);
2184+ end.actionPerformed(e);
2185+ }
2186+
2187+ private Action start;
2188+ private Action end;
2189+ }
2190+
2191+ /*
2192+ * Select the paragraph around the caret
2193+ * @see DefaultEditorKit#endAction
2194+ * @see DefaultEditorKit#getActions
2195+ */
2196+ static class SelectParagraphAction extends TextAction {
2197+
2198+ /**
2199+ * Create this action with the appropriate identifier.
2200+ * @param nm the name of the action, Action.NAME.
2201+ * @param select whether to extend the selection when
2202+ * changing the caret position.
2203+ */
2204+ SelectParagraphAction() {
2205+ super(selectParagraphAction);
2206+ start = new BeginParagraphAction("pigdog", false);
2207+ end = new EndParagraphAction("pigdog", true);
2208+ }
2209+
2210+ /** The operation to perform when this action is triggered. */
2211+ public void actionPerformed(ActionEvent e) {
2212+ start.actionPerformed(e);
2213+ end.actionPerformed(e);
2214+ }
2215+
2216+ private Action start;
2217+ private Action end;
2218+ }
2219+
2220+ /*
2221+ * Select the entire document
2222+ * @see DefaultEditorKit#endAction
2223+ * @see DefaultEditorKit#getActions
2224+ */
2225+ static class SelectAllAction extends TextAction {
2226+
2227+ /**
2228+ * Create this action with the appropriate identifier.
2229+ * @param nm the name of the action, Action.NAME.
2230+ * @param select whether to extend the selection when
2231+ * changing the caret position.
2232+ */
2233+ SelectAllAction() {
2234+ super(selectAllAction);
2235+ }
2236+
2237+ /** The operation to perform when this action is triggered. */
2238+ public void actionPerformed(ActionEvent e) {
2239+ JTextComponent target = getTextComponent(e);
2240+ if (target != null) {
2241+ Document doc = target.getDocument();
2242+ target.setCaretPosition(0);
2243+ target.moveCaretPosition(doc.getLength());
2244+ }
2245+ }
2246+
2247+ }
2248+
2249+ /*
2250+ * Remove the selection, if any.
2251+ * @see DefaultEditorKit#unselectAction
2252+ * @see DefaultEditorKit#getActions
2253+ */
2254+ static class UnselectAction extends TextAction {
2255+
2256+ /**
2257+ * Create this action with the appropriate identifier.
2258+ */
2259+ UnselectAction() {
2260+ super(unselectAction);
2261+ }
2262+
2263+ /** The operation to perform when this action is triggered. */
2264+ public void actionPerformed(ActionEvent e) {
2265+ JTextComponent target = getTextComponent(e);
2266+ if (target != null) {
2267+ target.setCaretPosition(target.getCaretPosition());
2268+ }
2269+ }
2270+
2271+ }
2272+
2273+ /*
2274+ * Toggles the ComponentOrientation of the text component.
2275+ * @see DefaultEditorKit#toggleComponentOrientationAction
2276+ * @see DefaultEditorKit#getActions
2277+ */
2278+ static class ToggleComponentOrientationAction extends TextAction {
2279+
2280+ /**
2281+ * Create this action with the appropriate identifier.
2282+ */
2283+ ToggleComponentOrientationAction() {
2284+ super(toggleComponentOrientationAction);
2285+ }
2286+
2287+ /** The operation to perform when this action is triggered. */
2288+ public void actionPerformed(ActionEvent e) {
2289+ JTextComponent target = getTextComponent(e);
2290+ if (target != null) {
2291+ ComponentOrientation last = target.getComponentOrientation();
2292+ ComponentOrientation next;
2293+ if( last == ComponentOrientation.RIGHT_TO_LEFT )
2294+ next = ComponentOrientation.LEFT_TO_RIGHT;
2295+ else
2296+ next = ComponentOrientation.RIGHT_TO_LEFT;
2297+ target.setComponentOrientation(next);
2298+ target.repaint();
2299+ }
2300+ }
2301+ }
2302+
2303+}