--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultEditorKit.java Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,2344 @@
+/*
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.swing.text;
+
+import sun.awt.SunToolkit;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.text.*;
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+
+/**
+ * This is the set of things needed by a text component
+ * to be a reasonably functioning editor for some <em>type</em>
+ * of text document. This implementation provides a default
+ * implementation which treats text as plain text and
+ * provides a minimal set of actions for a simple editor.
+ *
+ * <dl>
+ * <dt><b>Newlines</b>
+ * <dd>
+ * There are two properties which deal with newlines. The
+ * system property, <code>line.separator</code>, is defined to be
+ * platform-dependent, either "\n", "\r", or "\r\n". There is also
+ * a property defined in <code>DefaultEditorKit</code>, called
+ * <a href=#EndOfLineStringProperty><code>EndOfLineStringProperty</code></a>,
+ * which is defined automatically when a document is loaded, to be
+ * the first occurrence of any of the newline characters.
+ * When a document is loaded, <code>EndOfLineStringProperty</code>
+ * is set appropriately, and when the document is written back out, the
+ * <code>EndOfLineStringProperty</code> is used. But while the document
+ * is in memory, the "\n" character is used to define a
+ * newline, regardless of how the newline is defined when
+ * the document is on disk. Therefore, for searching purposes,
+ * "\n" should always be used. When a new document is created,
+ * and the <code>EndOfLineStringProperty</code> has not been defined,
+ * it will use the System property when writing out the
+ * document.
+ * <p>Note that <code>EndOfLineStringProperty</code> is set
+ * on the <code>Document</code> using the <code>get/putProperty</code>
+ * methods. Subclasses may override this behavior.
+ *
+ * </dl>
+ *
+ * @author Timothy Prinzing
+ */
+@SuppressWarnings("serial") // Same-version serialization only
+public class DefaultEditorKit extends EditorKit {
+
+ /**
+ * default constructor for DefaultEditorKit
+ */
+ public DefaultEditorKit() {
+ }
+
+ /**
+ * Gets the MIME type of the data that this
+ * kit represents support for. The default
+ * is <code>text/plain</code>.
+ *
+ * @return the type
+ */
+ public String getContentType() {
+ return "text/plain";
+ }
+
+ /**
+ * Fetches a factory that is suitable for producing
+ * views of any models that are produced by this
+ * kit. The default is to have the UI produce the
+ * factory, so this method has no implementation.
+ *
+ * @return the view factory
+ */
+ public ViewFactory getViewFactory() {
+ return null;
+ }
+
+ /**
+ * Fetches the set of commands that can be used
+ * on a text component that is using a model and
+ * view produced by this kit.
+ *
+ * @return the command list
+ */
+ public Action[] getActions() {
+ return defaultActions;
+ }
+
+ /**
+ * Fetches a caret that can navigate through views
+ * produced by the associated ViewFactory.
+ *
+ * @return the caret
+ */
+ public Caret createCaret() {
+ return null;
+ }
+
+ /**
+ * Creates an uninitialized text storage model (PlainDocument)
+ * that is appropriate for this type of editor.
+ *
+ * @return the model
+ */
+ public Document createDefaultDocument() {
+ return new PlainDocument();
+ }
+
+ /**
+ * Inserts content from the given stream which is expected
+ * to be in a format appropriate for this kind of content
+ * handler.
+ *
+ * @param in The stream to read from
+ * @param doc The destination for the insertion.
+ * @param pos The location in the document to place the
+ * content >=0.
+ * @exception IOException on any I/O error
+ * @exception BadLocationException if pos represents an invalid
+ * location within the document.
+ */
+ public void read(InputStream in, Document doc, int pos)
+ throws IOException, BadLocationException {
+
+ read(new InputStreamReader(in), doc, pos);
+ }
+
+ /**
+ * Writes content from a document to the given stream
+ * in a format appropriate for this kind of content handler.
+ *
+ * @param out The stream to write to
+ * @param doc The source for the write.
+ * @param pos The location in the document to fetch the
+ * content >=0.
+ * @param len The amount to write out >=0.
+ * @exception IOException on any I/O error
+ * @exception BadLocationException if pos represents an invalid
+ * location within the document.
+ */
+ public void write(OutputStream out, Document doc, int pos, int len)
+ throws IOException, BadLocationException {
+ OutputStreamWriter osw = new OutputStreamWriter(out);
+
+ write(osw, doc, pos, len);
+ osw.flush();
+ }
+
+ /**
+ * Gets the input attributes for the pane. This method exists for
+ * the benefit of StyledEditorKit so that the read method will
+ * pick up the correct attributes to apply to inserted text.
+ * This class's implementation simply returns null.
+ *
+ * @return null
+ */
+ MutableAttributeSet getInputAttributes() {
+ return null;
+ }
+
+ /**
+ * Inserts content from the given stream, which will be
+ * treated as plain text.
+ *
+ * @param in The stream to read from
+ * @param doc The destination for the insertion.
+ * @param pos The location in the document to place the
+ * content >=0.
+ * @exception IOException on any I/O error
+ * @exception BadLocationException if pos represents an invalid
+ * location within the document.
+ */
+ public void read(Reader in, Document doc, int pos)
+ throws IOException, BadLocationException {
+
+ char[] buff = new char[4096];
+ int nch;
+ boolean lastWasCR = false;
+ boolean isCRLF = false;
+ boolean isCR = false;
+ int last;
+ boolean wasEmpty = (doc.getLength() == 0);
+ AttributeSet attr = getInputAttributes();
+
+ // Read in a block at a time, mapping \r\n to \n, as well as single
+ // \r's to \n's. If a \r\n is encountered, \r\n will be set as the
+ // newline string for the document, if \r is encountered it will
+ // be set as the newline character, otherwise the newline property
+ // for the document will be removed.
+ while ((nch = in.read(buff, 0, buff.length)) != -1) {
+ last = 0;
+ for(int counter = 0; counter < nch; counter++) {
+ switch(buff[counter]) {
+ case '\r':
+ if (lastWasCR) {
+ isCR = true;
+ if (counter == 0) {
+ doc.insertString(pos, "\n", attr);
+ pos++;
+ }
+ else {
+ buff[counter - 1] = '\n';
+ }
+ }
+ else {
+ lastWasCR = true;
+ }
+ break;
+ case '\n':
+ if (lastWasCR) {
+ if (counter > (last + 1)) {
+ doc.insertString(pos, new String(buff, last,
+ counter - last - 1), attr);
+ pos += (counter - last - 1);
+ }
+ // else nothing to do, can skip \r, next write will
+ // write \n
+ lastWasCR = false;
+ last = counter;
+ isCRLF = true;
+ }
+ break;
+ default:
+ if (lastWasCR) {
+ isCR = true;
+ if (counter == 0) {
+ doc.insertString(pos, "\n", attr);
+ pos++;
+ }
+ else {
+ buff[counter - 1] = '\n';
+ }
+ lastWasCR = false;
+ }
+ break;
+ }
+ }
+ if (last < nch) {
+ if(lastWasCR) {
+ if (last < (nch - 1)) {
+ doc.insertString(pos, new String(buff, last,
+ nch - last - 1), attr);
+ pos += (nch - last - 1);
+ }
+ }
+ else {
+ doc.insertString(pos, new String(buff, last,
+ nch - last), attr);
+ pos += (nch - last);
+ }
+ }
+ }
+ if (lastWasCR) {
+ doc.insertString(pos, "\n", attr);
+ isCR = true;
+ }
+ if (wasEmpty) {
+ if (isCRLF) {
+ doc.putProperty(EndOfLineStringProperty, "\r\n");
+ }
+ else if (isCR) {
+ doc.putProperty(EndOfLineStringProperty, "\r");
+ }
+ else {
+ doc.putProperty(EndOfLineStringProperty, "\n");
+ }
+ }
+ }
+
+ /**
+ * Writes content from a document to the given stream
+ * as plain text.
+ *
+ * @param out The stream to write to
+ * @param doc The source for the write.
+ * @param pos The location in the document to fetch the
+ * content from >=0.
+ * @param len The amount to write out >=0.
+ * @exception IOException on any I/O error
+ * @exception BadLocationException if pos is not within 0 and
+ * the length of the document.
+ */
+ public void write(Writer out, Document doc, int pos, int len)
+ throws IOException, BadLocationException {
+
+ if ((pos < 0) || ((pos + len) > doc.getLength())) {
+ throw new BadLocationException("DefaultEditorKit.write", pos);
+ }
+ Segment data = new Segment();
+ int nleft = len;
+ int offs = pos;
+ Object endOfLineProperty = doc.getProperty(EndOfLineStringProperty);
+ if (endOfLineProperty == null) {
+ endOfLineProperty = System.lineSeparator();
+ }
+ String endOfLine;
+ if (endOfLineProperty instanceof String) {
+ endOfLine = (String)endOfLineProperty;
+ }
+ else {
+ endOfLine = null;
+ }
+ if (endOfLineProperty != null && !endOfLine.equals("\n")) {
+ // There is an end of line string that isn't \n, have to iterate
+ // through and find all \n's and translate to end of line string.
+ while (nleft > 0) {
+ int n = Math.min(nleft, 4096);
+ doc.getText(offs, n, data);
+ int last = data.offset;
+ char[] array = data.array;
+ int maxCounter = last + data.count;
+ for (int counter = last; counter < maxCounter; counter++) {
+ if (array[counter] == '\n') {
+ if (counter > last) {
+ out.write(array, last, counter - last);
+ }
+ out.write(endOfLine);
+ last = counter + 1;
+ }
+ }
+ if (maxCounter > last) {
+ out.write(array, last, maxCounter - last);
+ }
+ offs += n;
+ nleft -= n;
+ }
+ }
+ else {
+ // Just write out text, will already have \n, no mapping to
+ // do.
+ while (nleft > 0) {
+ int n = Math.min(nleft, 4096);
+ doc.getText(offs, n, data);
+ out.write(data.array, data.offset, data.count);
+ offs += n;
+ nleft -= n;
+ }
+ }
+ out.flush();
+ }
+
+
+ /**
+ * When reading a document if a CRLF is encountered a property
+ * with this name is added and the value will be "\r\n".
+ */
+ public static final String EndOfLineStringProperty = "__EndOfLine__";
+
+ // --- names of well-known actions ---------------------------
+
+ /**
+ * Name of the action to place content into the associated
+ * document. If there is a selection, it is removed before
+ * the new content is added.
+ * @see #getActions
+ */
+ public static final String insertContentAction = "insert-content";
+
+ /**
+ * Name of the action to place a line/paragraph break into
+ * the document. If there is a selection, it is removed before
+ * the break is added.
+ * @see #getActions
+ */
+ public static final String insertBreakAction = "insert-break";
+
+ /**
+ * Name of the action to place a tab character into
+ * the document. If there is a selection, it is removed before
+ * the tab is added.
+ * @see #getActions
+ */
+ public static final String insertTabAction = "insert-tab";
+
+ /**
+ * Name of the action to delete the character of content that
+ * precedes the current caret position.
+ * @see #getActions
+ */
+ public static final String deletePrevCharAction = "delete-previous";
+
+ /**
+ * Name of the action to delete the character of content that
+ * follows the current caret position.
+ * @see #getActions
+ */
+ public static final String deleteNextCharAction = "delete-next";
+
+ /**
+ * Name of the action to delete the word that
+ * follows the beginning of the selection.
+ * @see #getActions
+ * @see JTextComponent#getSelectionStart
+ * @since 1.6
+ */
+ public static final String deleteNextWordAction = "delete-next-word";
+
+ /**
+ * Name of the action to delete the word that
+ * precedes the beginning of the selection.
+ * @see #getActions
+ * @see JTextComponent#getSelectionStart
+ * @since 1.6
+ */
+ public static final String deletePrevWordAction = "delete-previous-word";
+
+ /**
+ * Name of the action to set the editor into read-only
+ * mode.
+ * @see #getActions
+ */
+ public static final String readOnlyAction = "set-read-only";
+
+ /**
+ * Name of the action to set the editor into writeable
+ * mode.
+ * @see #getActions
+ */
+ public static final String writableAction = "set-writable";
+
+ /**
+ * Name of the action to cut the selected region
+ * and place the contents into the system clipboard.
+ * @see JTextComponent#cut
+ * @see #getActions
+ */
+ public static final String cutAction = "cut-to-clipboard";
+
+ /**
+ * Name of the action to copy the selected region
+ * and place the contents into the system clipboard.
+ * @see JTextComponent#copy
+ * @see #getActions
+ */
+ public static final String copyAction = "copy-to-clipboard";
+
+ /**
+ * Name of the action to paste the contents of the
+ * system clipboard into the selected region, or before the
+ * caret if nothing is selected.
+ * @see JTextComponent#paste
+ * @see #getActions
+ */
+ public static final String pasteAction = "paste-from-clipboard";
+
+ /**
+ * Name of the action to create a beep.
+ * @see #getActions
+ */
+ public static final String beepAction = "beep";
+
+ /**
+ * Name of the action to page up vertically.
+ * @see #getActions
+ */
+ public static final String pageUpAction = "page-up";
+
+ /**
+ * Name of the action to page down vertically.
+ * @see #getActions
+ */
+ public static final String pageDownAction = "page-down";
+
+ /**
+ * Name of the action to page up vertically, and move the
+ * selection.
+ * @see #getActions
+ */
+ /*public*/ static final String selectionPageUpAction = "selection-page-up";
+
+ /**
+ * Name of the action to page down vertically, and move the
+ * selection.
+ * @see #getActions
+ */
+ /*public*/ static final String selectionPageDownAction = "selection-page-down";
+
+ /**
+ * Name of the action to page left horizontally, and move the
+ * selection.
+ * @see #getActions
+ */
+ /*public*/ static final String selectionPageLeftAction = "selection-page-left";
+
+ /**
+ * Name of the action to page right horizontally, and move the
+ * selection.
+ * @see #getActions
+ */
+ /*public*/ static final String selectionPageRightAction = "selection-page-right";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically forward one position.
+ * @see #getActions
+ */
+ public static final String forwardAction = "caret-forward";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically backward one position.
+ * @see #getActions
+ */
+ public static final String backwardAction = "caret-backward";
+
+ /**
+ * Name of the Action for extending the selection
+ * by moving the caret logically forward one position.
+ * @see #getActions
+ */
+ public static final String selectionForwardAction = "selection-forward";
+
+ /**
+ * Name of the Action for extending the selection
+ * by moving the caret logically backward one position.
+ * @see #getActions
+ */
+ public static final String selectionBackwardAction = "selection-backward";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically upward one position.
+ * @see #getActions
+ */
+ public static final String upAction = "caret-up";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically downward one position.
+ * @see #getActions
+ */
+ public static final String downAction = "caret-down";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically upward one position, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionUpAction = "selection-up";
+
+ /**
+ * Name of the Action for moving the caret
+ * logically downward one position, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionDownAction = "selection-down";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a word.
+ * @see #getActions
+ */
+ public static final String beginWordAction = "caret-begin-word";
+
+ /**
+ * Name of the Action for moving the caret
+ * to the end of a word.
+ * @see #getActions
+ */
+ public static final String endWordAction = "caret-end-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a word, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionBeginWordAction = "selection-begin-word";
+
+ /**
+ * Name of the Action for moving the caret
+ * to the end of a word, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionEndWordAction = "selection-end-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret to the
+ * beginning of the previous word.
+ * @see #getActions
+ */
+ public static final String previousWordAction = "caret-previous-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret to the
+ * beginning of the next word.
+ * @see #getActions
+ */
+ public static final String nextWordAction = "caret-next-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the selection to the
+ * beginning of the previous word, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionPreviousWordAction = "selection-previous-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the selection to the
+ * beginning of the next word, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionNextWordAction = "selection-next-word";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a line.
+ * @see #getActions
+ */
+ public static final String beginLineAction = "caret-begin-line";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the end of a line.
+ * @see #getActions
+ */
+ public static final String endLineAction = "caret-end-line";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a line, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionBeginLineAction = "selection-begin-line";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the end of a line, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionEndLineAction = "selection-end-line";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a paragraph.
+ * @see #getActions
+ */
+ public static final String beginParagraphAction = "caret-begin-paragraph";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the end of a paragraph.
+ * @see #getActions
+ */
+ public static final String endParagraphAction = "caret-end-paragraph";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of a paragraph, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionBeginParagraphAction = "selection-begin-paragraph";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the end of a paragraph, extending the selection.
+ * @see #getActions
+ */
+ public static final String selectionEndParagraphAction = "selection-end-paragraph";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of the document.
+ * @see #getActions
+ */
+ public static final String beginAction = "caret-begin";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the end of the document.
+ * @see #getActions
+ */
+ public static final String endAction = "caret-end";
+
+ /**
+ * Name of the <code>Action</code> for moving the caret
+ * to the beginning of the document.
+ * @see #getActions
+ */
+ public static final String selectionBeginAction = "selection-begin";
+
+ /**
+ * Name of the Action for moving the caret
+ * to the end of the document.
+ * @see #getActions
+ */
+ public static final String selectionEndAction = "selection-end";
+
+ /**
+ * Name of the Action for selecting a word around the caret.
+ * @see #getActions
+ */
+ public static final String selectWordAction = "select-word";
+
+ /**
+ * Name of the Action for selecting a line around the caret.
+ * @see #getActions
+ */
+ public static final String selectLineAction = "select-line";
+
+ /**
+ * Name of the Action for selecting a paragraph around the caret.
+ * @see #getActions
+ */
+ public static final String selectParagraphAction = "select-paragraph";
+
+ /**
+ * Name of the Action for selecting the entire document
+ * @see #getActions
+ */
+ public static final String selectAllAction = "select-all";
+
+ /**
+ * Name of the Action for removing selection
+ * @see #getActions
+ */
+ /*public*/ static final String unselectAction = "unselect";
+
+ /**
+ * Name of the Action for toggling the component's orientation.
+ * @see #getActions
+ */
+ /*public*/ static final String toggleComponentOrientationAction
+ = "toggle-componentOrientation";
+
+ /**
+ * Name of the action that is executed by default if
+ * a <em>key typed event</em> is received and there
+ * is no keymap entry.
+ * @see #getActions
+ */
+ public static final String defaultKeyTypedAction = "default-typed";
+
+ // --- Action implementations ---------------------------------
+
+ private static final Action[] defaultActions = {
+ new InsertContentAction(), new DeletePrevCharAction(),
+ new DeleteNextCharAction(), new ReadOnlyAction(),
+ new DeleteWordAction(deletePrevWordAction),
+ new DeleteWordAction(deleteNextWordAction),
+ new WritableAction(), new CutAction(),
+ new CopyAction(), new PasteAction(),
+ new VerticalPageAction(pageUpAction, -1, false),
+ new VerticalPageAction(pageDownAction, 1, false),
+ new VerticalPageAction(selectionPageUpAction, -1, true),
+ new VerticalPageAction(selectionPageDownAction, 1, true),
+ new PageAction(selectionPageLeftAction, true, true),
+ new PageAction(selectionPageRightAction, false, true),
+ new InsertBreakAction(), new BeepAction(),
+ new NextVisualPositionAction(forwardAction, false,
+ SwingConstants.EAST),
+ new NextVisualPositionAction(backwardAction, false,
+ SwingConstants.WEST),
+ new NextVisualPositionAction(selectionForwardAction, true,
+ SwingConstants.EAST),
+ new NextVisualPositionAction(selectionBackwardAction, true,
+ SwingConstants.WEST),
+ new NextVisualPositionAction(upAction, false,
+ SwingConstants.NORTH),
+ new NextVisualPositionAction(downAction, false,
+ SwingConstants.SOUTH),
+ new NextVisualPositionAction(selectionUpAction, true,
+ SwingConstants.NORTH),
+ new NextVisualPositionAction(selectionDownAction, true,
+ SwingConstants.SOUTH),
+ new BeginWordAction(beginWordAction, false),
+ new EndWordAction(endWordAction, false),
+ new BeginWordAction(selectionBeginWordAction, true),
+ new EndWordAction(selectionEndWordAction, true),
+ new PreviousWordAction(previousWordAction, false),
+ new NextWordAction(nextWordAction, false),
+ new PreviousWordAction(selectionPreviousWordAction, true),
+ new NextWordAction(selectionNextWordAction, true),
+ new BeginLineAction(beginLineAction, false),
+ new EndLineAction(endLineAction, false),
+ new BeginLineAction(selectionBeginLineAction, true),
+ new EndLineAction(selectionEndLineAction, true),
+ new BeginParagraphAction(beginParagraphAction, false),
+ new EndParagraphAction(endParagraphAction, false),
+ new BeginParagraphAction(selectionBeginParagraphAction, true),
+ new EndParagraphAction(selectionEndParagraphAction, true),
+ new BeginAction(beginAction, false),
+ new EndAction(endAction, false),
+ new BeginAction(selectionBeginAction, true),
+ new EndAction(selectionEndAction, true),
+ new DefaultKeyTypedAction(), new InsertTabAction(),
+ new SelectWordAction(), new SelectLineAction(),
+ new SelectParagraphAction(), new SelectAllAction(),
+ new UnselectAction(), new ToggleComponentOrientationAction(),
+ new DumpModelAction()
+ };
+
+ /**
+ * The action that is executed by default if
+ * a <em>key typed event</em> is received and there
+ * is no keymap entry. There is a variation across
+ * different VM's in what gets sent as a <em>key typed</em>
+ * event, and this action tries to filter out the undesired
+ * events. This filters the control characters and those
+ * with the ALT modifier. It allows Control-Alt sequences
+ * through as these form legitimate unicode characters on
+ * some PC keyboards.
+ * <p>
+ * If the event doesn't get filtered, it will try to insert
+ * content into the text editor. The content is fetched
+ * from the command string of the ActionEvent. The text
+ * entry is done through the <code>replaceSelection</code>
+ * method on the target text component. This is the
+ * action that will be fired for most text entry tasks.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#defaultKeyTypedAction
+ * @see DefaultEditorKit#getActions
+ * @see Keymap#setDefaultAction
+ * @see Keymap#getDefaultAction
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class DefaultKeyTypedAction extends TextAction {
+
+ /**
+ * Creates this object with the appropriate identifier.
+ */
+ public DefaultKeyTypedAction() {
+ super(defaultKeyTypedAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if ((target != null) && (e != null)) {
+ if ((! target.isEditable()) || (! target.isEnabled())) {
+ return;
+ }
+ String content = e.getActionCommand();
+ int mod = e.getModifiers();
+ if ((content != null) && (content.length() > 0)) {
+ boolean isPrintableMask = true;
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ if (tk instanceof SunToolkit) {
+ isPrintableMask = ((SunToolkit)tk).isPrintableCharacterModifiersMask(mod);
+ }
+
+ if (isPrintableMask) {
+ char c = content.charAt(0);
+ if ((c >= 0x20) && (c != 0x7F)) {
+ target.replaceSelection(content);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Places content into the associated document.
+ * If there is a selection, it is removed before
+ * the new content is added.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#insertContentAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class InsertContentAction extends TextAction {
+
+ /**
+ * Creates this object with the appropriate identifier.
+ */
+ public InsertContentAction() {
+ super(insertContentAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if ((target != null) && (e != null)) {
+ if ((! target.isEditable()) || (! target.isEnabled())) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ return;
+ }
+ String content = e.getActionCommand();
+ if (content != null) {
+ target.replaceSelection(content);
+ } else {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+ }
+
+ /**
+ * Places a line/paragraph break into the document.
+ * If there is a selection, it is removed before
+ * the break is added.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#insertBreakAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class InsertBreakAction extends TextAction {
+
+ /**
+ * Creates this object with the appropriate identifier.
+ */
+ public InsertBreakAction() {
+ super(insertBreakAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ if ((! target.isEditable()) || (! target.isEnabled())) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ return;
+ }
+ target.replaceSelection("\n");
+ }
+ }
+ }
+
+ /**
+ * Places a tab character into the document. If there
+ * is a selection, it is removed before the tab is added.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#insertTabAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class InsertTabAction extends TextAction {
+
+ /**
+ * Creates this object with the appropriate identifier.
+ */
+ public InsertTabAction() {
+ super(insertTabAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ if ((! target.isEditable()) || (! target.isEnabled())) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ return;
+ }
+ target.replaceSelection("\t");
+ }
+ }
+ }
+
+ /*
+ * Deletes the character of content that precedes the
+ * current caret position.
+ * @see DefaultEditorKit#deletePrevCharAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class DeletePrevCharAction extends TextAction {
+
+ /**
+ * Creates this object with the appropriate identifier.
+ */
+ DeletePrevCharAction() {
+ super(deletePrevCharAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ boolean beep = true;
+ if ((target != null) && (target.isEditable())) {
+ try {
+ Document doc = target.getDocument();
+ Caret caret = target.getCaret();
+ int dot = caret.getDot();
+ int mark = caret.getMark();
+ if (dot != mark) {
+ doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
+ beep = false;
+ } else if (dot > 0) {
+ int delChars = 1;
+
+ if (dot > 1) {
+ String dotChars = doc.getText(dot - 2, 2);
+ char c0 = dotChars.charAt(0);
+ char c1 = dotChars.charAt(1);
+
+ if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
+ c1 >= '\uDC00' && c1 <= '\uDFFF') {
+ delChars = 2;
+ }
+ }
+
+ doc.remove(dot - delChars, delChars);
+ beep = false;
+ }
+ } catch (BadLocationException bl) {
+ }
+ }
+ if (beep) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ /*
+ * Deletes the character of content that follows the
+ * current caret position.
+ * @see DefaultEditorKit#deleteNextCharAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class DeleteNextCharAction extends TextAction {
+
+ /* Create this object with the appropriate identifier. */
+ DeleteNextCharAction() {
+ super(deleteNextCharAction);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ boolean beep = true;
+ if ((target != null) && (target.isEditable())) {
+ try {
+ Document doc = target.getDocument();
+ Caret caret = target.getCaret();
+ int dot = caret.getDot();
+ int mark = caret.getMark();
+ if (dot != mark) {
+ doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
+ beep = false;
+ } else if (dot < doc.getLength()) {
+ int delChars = 1;
+
+ if (dot < doc.getLength() - 1) {
+ String dotChars = doc.getText(dot, 2);
+ char c0 = dotChars.charAt(0);
+ char c1 = dotChars.charAt(1);
+
+ if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
+ c1 >= '\uDC00' && c1 <= '\uDFFF') {
+ delChars = 2;
+ }
+ }
+
+ doc.remove(dot, delChars);
+ beep = false;
+ }
+ } catch (BadLocationException bl) {
+ }
+ }
+ if (beep) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+
+ /*
+ * Deletes the word that precedes/follows the beginning of the selection.
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class DeleteWordAction extends TextAction {
+ DeleteWordAction(String name) {
+ super(name);
+ assert (name == deletePrevWordAction)
+ || (name == deleteNextWordAction);
+ }
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ final JTextComponent target = getTextComponent(e);
+ if ((target != null) && (e != null)) {
+ if ((! target.isEditable()) || (! target.isEnabled())) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ return;
+ }
+ boolean beep = true;
+ try {
+ final int start = target.getSelectionStart();
+ final Element line =
+ Utilities.getParagraphElement(target, start);
+ int end;
+ if (deleteNextWordAction == getValue(Action.NAME)) {
+ end = Utilities.
+ getNextWordInParagraph(target, line, start, false);
+ if (end == java.text.BreakIterator.DONE) {
+ //last word in the paragraph
+ final int endOfLine = line.getEndOffset();
+ if (start == endOfLine - 1) {
+ //for last position remove last \n
+ end = endOfLine;
+ } else {
+ //remove to the end of the paragraph
+ end = endOfLine - 1;
+ }
+ }
+ } else {
+ end = Utilities.
+ getPrevWordInParagraph(target, line, start);
+ if (end == java.text.BreakIterator.DONE) {
+ //there is no previous word in the paragraph
+ final int startOfLine = line.getStartOffset();
+ if (start == startOfLine) {
+ //for first position remove previous \n
+ end = startOfLine - 1;
+ } else {
+ //remove to the start of the paragraph
+ end = startOfLine;
+ }
+ }
+ }
+ int offs = Math.min(start, end);
+ int len = Math.abs(end - start);
+ if (offs >= 0) {
+ target.getDocument().remove(offs, len);
+ beep = false;
+ }
+ } catch (BadLocationException ignore) {
+ }
+ if (beep) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+ }
+
+
+ /*
+ * Sets the editor into read-only mode.
+ * @see DefaultEditorKit#readOnlyAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class ReadOnlyAction extends TextAction {
+
+ /* Create this object with the appropriate identifier. */
+ ReadOnlyAction() {
+ super(readOnlyAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.setEditable(false);
+ }
+ }
+ }
+
+ /*
+ * Sets the editor into writeable mode.
+ * @see DefaultEditorKit#writableAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class WritableAction extends TextAction {
+
+ /* Create this object with the appropriate identifier. */
+ WritableAction() {
+ super(writableAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.setEditable(true);
+ }
+ }
+ }
+
+ /**
+ * Cuts the selected region and place its contents
+ * into the system clipboard.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#cutAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class CutAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public CutAction() {
+ super(cutAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.cut();
+ }
+ }
+ }
+
+ /**
+ * Copies the selected region and place its contents
+ * into the system clipboard.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#copyAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class CopyAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public CopyAction() {
+ super(copyAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.copy();
+ }
+ }
+ }
+
+ /**
+ * Pastes the contents of the system clipboard into the
+ * selected region, or before the caret if nothing is
+ * selected.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#pasteAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class PasteAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public PasteAction() {
+ super(pasteAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.paste();
+ }
+ }
+ }
+
+ /**
+ * Creates a beep.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing. As of 1.4, support for long term storage
+ * of all JavaBeans™
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see DefaultEditorKit#beepAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Same-version serialization only
+ public static class BeepAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public BeepAction() {
+ super(beepAction);
+ }
+
+ /**
+ * The operation to perform when this action is triggered.
+ *
+ * @param e the action event
+ */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+
+ /**
+ * Scrolls up/down vertically. The select version of this action extends
+ * the selection, instead of simply moving the caret.
+ *
+ * @see DefaultEditorKit#pageUpAction
+ * @see DefaultEditorKit#pageDownAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class VerticalPageAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public VerticalPageAction(String nm, int direction, boolean select) {
+ super(nm);
+ this.select = select;
+ this.direction = direction;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ Rectangle visible = target.getVisibleRect();
+ Rectangle newVis = new Rectangle(visible);
+ int selectedIndex = target.getCaretPosition();
+ int scrollAmount = direction *
+ target.getScrollableBlockIncrement(
+ visible, SwingConstants.VERTICAL, direction);
+ int initialY = visible.y;
+ Caret caret = target.getCaret();
+ Point magicPosition = caret.getMagicCaretPosition();
+
+ if (selectedIndex != -1) {
+ try {
+ Rectangle dotBounds = target.modelToView(
+ selectedIndex);
+ int x = (magicPosition != null) ? magicPosition.x :
+ dotBounds.x;
+ int h = dotBounds.height;
+ if (h > 0) {
+ // We want to scroll by a multiple of caret height,
+ // rounding towards lower integer
+ scrollAmount = scrollAmount / h * h;
+ }
+ newVis.y = constrainY(target,
+ initialY + scrollAmount, visible.height);
+
+ int newIndex;
+
+ if (visible.contains(dotBounds.x, dotBounds.y)) {
+ // Dot is currently visible, base the new
+ // location off the old, or
+ newIndex = target.viewToModel(
+ new Point(x, constrainY(target,
+ dotBounds.y + scrollAmount, 0)));
+ }
+ else {
+ // Dot isn't visible, choose the top or the bottom
+ // for the new location.
+ if (direction == -1) {
+ newIndex = target.viewToModel(new Point(
+ x, newVis.y));
+ }
+ else {
+ newIndex = target.viewToModel(new Point(
+ x, newVis.y + visible.height));
+ }
+ }
+ newIndex = constrainOffset(target, newIndex);
+ if (newIndex != selectedIndex) {
+ // Make sure the new visible location contains
+ // the location of dot, otherwise Caret will
+ // cause an additional scroll.
+ int newY = getAdjustedY(target, newVis, newIndex);
+
+ if (direction == -1 && newY <= initialY || direction == 1 && newY >= initialY) {
+ // Change index and correct newVis.y only if won't cause scrolling upward
+ newVis.y = newY;
+
+ if (select) {
+ target.moveCaretPosition(newIndex);
+ } else {
+ target.setCaretPosition(newIndex);
+ }
+ }
+ }
+ } catch (BadLocationException ble) { }
+ } else {
+ newVis.y = constrainY(target,
+ initialY + scrollAmount, visible.height);
+ }
+ if (magicPosition != null) {
+ caret.setMagicCaretPosition(magicPosition);
+ }
+ target.scrollRectToVisible(newVis);
+ }
+ }
+
+ /**
+ * Makes sure <code>y</code> is a valid location in
+ * <code>target</code>.
+ */
+ private int constrainY(JTextComponent target, int y, int vis) {
+ if (y < 0) {
+ y = 0;
+ }
+ else if (y + vis > target.getHeight()) {
+ y = Math.max(0, target.getHeight() - vis);
+ }
+ return y;
+ }
+
+ /**
+ * Ensures that <code>offset</code> is a valid offset into the
+ * model for <code>text</code>.
+ */
+ private int constrainOffset(JTextComponent text, int offset) {
+ Document doc = text.getDocument();
+
+ if ((offset != 0) && (offset > doc.getLength())) {
+ offset = doc.getLength();
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ return offset;
+ }
+
+ /**
+ * Returns adjustsed {@code y} position that indicates the location to scroll to
+ * after selecting <code>index</code>.
+ */
+ private int getAdjustedY(JTextComponent text, Rectangle visible, int index) {
+ int result = visible.y;
+
+ try {
+ Rectangle dotBounds = text.modelToView(index);
+
+ if (dotBounds.y < visible.y) {
+ result = dotBounds.y;
+ } else {
+ if ((dotBounds.y > visible.y + visible.height) ||
+ (dotBounds.y + dotBounds.height > visible.y + visible.height)) {
+ result = dotBounds.y + dotBounds.height - visible.height;
+ }
+ }
+ } catch (BadLocationException ble) {
+ }
+
+ return result;
+ }
+
+ /**
+ * Adjusts the Rectangle to contain the bounds of the character at
+ * <code>index</code> in response to a page up.
+ */
+ private boolean select;
+
+ /**
+ * Direction to scroll, 1 is down, -1 is up.
+ */
+ private int direction;
+ }
+
+
+ /**
+ * Pages one view to the left or right.
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class PageAction extends TextAction {
+
+ /** Create this object with the appropriate identifier. */
+ public PageAction(String nm, boolean left, boolean select) {
+ super(nm);
+ this.select = select;
+ this.left = left;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ int selectedIndex;
+ Rectangle visible = new Rectangle();
+ target.computeVisibleRect(visible);
+ if (left) {
+ visible.x = Math.max(0, visible.x - visible.width);
+ }
+ else {
+ visible.x += visible.width;
+ }
+
+ selectedIndex = target.getCaretPosition();
+ if(selectedIndex != -1) {
+ if (left) {
+ selectedIndex = target.viewToModel
+ (new Point(visible.x, visible.y));
+ }
+ else {
+ selectedIndex = target.viewToModel
+ (new Point(visible.x + visible.width - 1,
+ visible.y + visible.height - 1));
+ }
+ Document doc = target.getDocument();
+ if ((selectedIndex != 0) &&
+ (selectedIndex > (doc.getLength()-1))) {
+ selectedIndex = doc.getLength()-1;
+ }
+ else if(selectedIndex < 0) {
+ selectedIndex = 0;
+ }
+ if (select)
+ target.moveCaretPosition(selectedIndex);
+ else
+ target.setCaretPosition(selectedIndex);
+ }
+ }
+ }
+
+ private boolean select;
+ private boolean left;
+ }
+
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class DumpModelAction extends TextAction {
+
+ DumpModelAction() {
+ super("dump-model");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ Document d = target.getDocument();
+ if (d instanceof AbstractDocument) {
+ ((AbstractDocument) d).dump(System.err);
+ }
+ }
+ }
+ }
+
+ /*
+ * Action to move the selection by way of the
+ * getNextVisualPositionFrom method. Constructor indicates direction
+ * to use.
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class NextVisualPositionAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ NextVisualPositionAction(String nm, boolean select, int direction) {
+ super(nm);
+ this.select = select;
+ this.direction = direction;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ Caret caret = target.getCaret();
+ DefaultCaret bidiCaret = (caret instanceof DefaultCaret) ?
+ (DefaultCaret)caret : null;
+ int dot = caret.getDot();
+ Position.Bias[] bias = new Position.Bias[1];
+ Point magicPosition = caret.getMagicCaretPosition();
+
+ try {
+ if(magicPosition == null &&
+ (direction == SwingConstants.NORTH ||
+ direction == SwingConstants.SOUTH)) {
+ Rectangle r = (bidiCaret != null) ?
+ target.getUI().modelToView(target, dot,
+ bidiCaret.getDotBias()) :
+ target.modelToView(dot);
+ magicPosition = new Point(r.x, r.y);
+ }
+
+ NavigationFilter filter = target.getNavigationFilter();
+
+ if (filter != null) {
+ dot = filter.getNextVisualPositionFrom
+ (target, dot, (bidiCaret != null) ?
+ bidiCaret.getDotBias() :
+ Position.Bias.Forward, direction, bias);
+ }
+ else {
+ dot = target.getUI().getNextVisualPositionFrom
+ (target, dot, (bidiCaret != null) ?
+ bidiCaret.getDotBias() :
+ Position.Bias.Forward, direction, bias);
+ }
+ if(bias[0] == null) {
+ bias[0] = Position.Bias.Forward;
+ }
+ if(bidiCaret != null) {
+ if (select) {
+ bidiCaret.moveDot(dot, bias[0]);
+ } else {
+ bidiCaret.setDot(dot, bias[0]);
+ }
+ }
+ else {
+ if (select) {
+ caret.moveDot(dot);
+ } else {
+ caret.setDot(dot);
+ }
+ }
+ if(magicPosition != null &&
+ (direction == SwingConstants.NORTH ||
+ direction == SwingConstants.SOUTH)) {
+ target.getCaret().setMagicCaretPosition(magicPosition);
+ }
+ } catch (BadLocationException ex) {
+ }
+ }
+ }
+
+ private boolean select;
+ private int direction;
+ }
+
+ /*
+ * Position the caret to the beginning of the word.
+ * @see DefaultEditorKit#beginWordAction
+ * @see DefaultEditorKit#selectBeginWordAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class BeginWordAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ BeginWordAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ try {
+ int offs = target.getCaretPosition();
+ int begOffs = Utilities.getWordStart(target, offs);
+ if (select) {
+ target.moveCaretPosition(begOffs);
+ } else {
+ target.setCaretPosition(begOffs);
+ }
+ } catch (BadLocationException bl) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the end of the word.
+ * @see DefaultEditorKit#endWordAction
+ * @see DefaultEditorKit#selectEndWordAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class EndWordAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ EndWordAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ try {
+ int offs = target.getCaretPosition();
+ int endOffs = Utilities.getWordEnd(target, offs);
+ if (select) {
+ target.moveCaretPosition(endOffs);
+ } else {
+ target.setCaretPosition(endOffs);
+ }
+ } catch (BadLocationException bl) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the beginning of the previous word.
+ * @see DefaultEditorKit#previousWordAction
+ * @see DefaultEditorKit#selectPreviousWordAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class PreviousWordAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ PreviousWordAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ int offs = target.getCaretPosition();
+ boolean failed = false;
+ try {
+ Element curPara =
+ Utilities.getParagraphElement(target, offs);
+ offs = Utilities.getPreviousWord(target, offs);
+ if(offs < curPara.getStartOffset()) {
+ // we should first move to the end of the
+ // previous paragraph (bug #4278839)
+ offs = Utilities.getParagraphElement(target, offs).
+ getEndOffset() - 1;
+ }
+ } catch (BadLocationException bl) {
+ if (offs != 0) {
+ offs = 0;
+ }
+ else {
+ failed = true;
+ }
+ }
+ if (!failed) {
+ if (select) {
+ target.moveCaretPosition(offs);
+ } else {
+ target.setCaretPosition(offs);
+ }
+ }
+ else {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the next of the word.
+ * @see DefaultEditorKit#nextWordAction
+ * @see DefaultEditorKit#selectNextWordAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class NextWordAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ NextWordAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ int offs = target.getCaretPosition();
+ boolean failed = false;
+ int oldOffs = offs;
+ Element curPara =
+ Utilities.getParagraphElement(target, offs);
+ try {
+ offs = Utilities.getNextWord(target, offs);
+ if(offs >= curPara.getEndOffset() &&
+ oldOffs != curPara.getEndOffset() - 1) {
+ // we should first move to the end of current
+ // paragraph (bug #4278839)
+ offs = curPara.getEndOffset() - 1;
+ }
+ } catch (BadLocationException bl) {
+ int end = target.getDocument().getLength();
+ if (offs != end) {
+ if(oldOffs != curPara.getEndOffset() - 1) {
+ offs = curPara.getEndOffset() - 1;
+ } else {
+ offs = end;
+ }
+ }
+ else {
+ failed = true;
+ }
+ }
+ if (!failed) {
+ if (select) {
+ target.moveCaretPosition(offs);
+ } else {
+ target.setCaretPosition(offs);
+ }
+ }
+ else {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the beginning of the line.
+ * @see DefaultEditorKit#beginLineAction
+ * @see DefaultEditorKit#selectBeginLineAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class BeginLineAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ BeginLineAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ try {
+ int offs = target.getCaretPosition();
+ int begOffs = Utilities.getRowStart(target, offs);
+ if (select) {
+ target.moveCaretPosition(begOffs);
+ } else {
+ target.setCaretPosition(begOffs);
+ }
+ } catch (BadLocationException bl) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the end of the line.
+ * @see DefaultEditorKit#endLineAction
+ * @see DefaultEditorKit#selectEndLineAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class EndLineAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ EndLineAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ try {
+ int offs = target.getCaretPosition();
+ int endOffs = Utilities.getRowEnd(target, offs);
+ if (select) {
+ target.moveCaretPosition(endOffs);
+ } else {
+ target.setCaretPosition(endOffs);
+ }
+ } catch (BadLocationException bl) {
+ UIManager.getLookAndFeel().provideErrorFeedback(target);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the beginning of the paragraph.
+ * @see DefaultEditorKit#beginParagraphAction
+ * @see DefaultEditorKit#selectBeginParagraphAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class BeginParagraphAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ BeginParagraphAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ int offs = target.getCaretPosition();
+ Element elem = Utilities.getParagraphElement(target, offs);
+ offs = elem.getStartOffset();
+ if (select) {
+ target.moveCaretPosition(offs);
+ } else {
+ target.setCaretPosition(offs);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Position the caret to the end of the paragraph.
+ * @see DefaultEditorKit#endParagraphAction
+ * @see DefaultEditorKit#selectEndParagraphAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class EndParagraphAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ EndParagraphAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ int offs = target.getCaretPosition();
+ Element elem = Utilities.getParagraphElement(target, offs);
+ offs = Math.min(target.getDocument().getLength(),
+ elem.getEndOffset());
+ if (select) {
+ target.moveCaretPosition(offs);
+ } else {
+ target.setCaretPosition(offs);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Move the caret to the beginning of the document.
+ * @see DefaultEditorKit#beginAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class BeginAction extends TextAction {
+
+ /* Create this object with the appropriate identifier. */
+ BeginAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ if (select) {
+ target.moveCaretPosition(0);
+ } else {
+ target.setCaretPosition(0);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Move the caret to the end of the document.
+ * @see DefaultEditorKit#endAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class EndAction extends TextAction {
+
+ /* Create this object with the appropriate identifier. */
+ EndAction(String nm, boolean select) {
+ super(nm);
+ this.select = select;
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ Document doc = target.getDocument();
+ int dot = doc.getLength();
+ if (select) {
+ target.moveCaretPosition(dot);
+ } else {
+ target.setCaretPosition(dot);
+ }
+ }
+ }
+
+ private boolean select;
+ }
+
+ /*
+ * Select the word around the caret
+ * @see DefaultEditorKit#endAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class SelectWordAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ SelectWordAction() {
+ super(selectWordAction);
+ start = new BeginWordAction("pigdog", false);
+ end = new EndWordAction("pigdog", true);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ start.actionPerformed(e);
+ end.actionPerformed(e);
+ }
+
+ private Action start;
+ private Action end;
+ }
+
+ /*
+ * Select the line around the caret
+ * @see DefaultEditorKit#endAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class SelectLineAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ SelectLineAction() {
+ super(selectLineAction);
+ start = new BeginLineAction("pigdog", false);
+ end = new EndLineAction("pigdog", true);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ start.actionPerformed(e);
+ end.actionPerformed(e);
+ }
+
+ private Action start;
+ private Action end;
+ }
+
+ /*
+ * Select the paragraph around the caret
+ * @see DefaultEditorKit#endAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class SelectParagraphAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ SelectParagraphAction() {
+ super(selectParagraphAction);
+ start = new BeginParagraphAction("pigdog", false);
+ end = new EndParagraphAction("pigdog", true);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ start.actionPerformed(e);
+ end.actionPerformed(e);
+ }
+
+ private Action start;
+ private Action end;
+ }
+
+ /*
+ * Select the entire document
+ * @see DefaultEditorKit#endAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class SelectAllAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ * @param nm the name of the action, Action.NAME.
+ * @param select whether to extend the selection when
+ * changing the caret position.
+ */
+ SelectAllAction() {
+ super(selectAllAction);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ Document doc = target.getDocument();
+ target.setCaretPosition(0);
+ target.moveCaretPosition(doc.getLength());
+ }
+ }
+
+ }
+
+ /*
+ * Remove the selection, if any.
+ * @see DefaultEditorKit#unselectAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class UnselectAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ */
+ UnselectAction() {
+ super(unselectAction);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ target.setCaretPosition(target.getCaretPosition());
+ }
+ }
+
+ }
+
+ /*
+ * Toggles the ComponentOrientation of the text component.
+ * @see DefaultEditorKit#toggleComponentOrientationAction
+ * @see DefaultEditorKit#getActions
+ */
+ @SuppressWarnings("serial") // Superclass is not serializable across versions
+ static class ToggleComponentOrientationAction extends TextAction {
+
+ /**
+ * Create this action with the appropriate identifier.
+ */
+ ToggleComponentOrientationAction() {
+ super(toggleComponentOrientationAction);
+ }
+
+ /** The operation to perform when this action is triggered. */
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent target = getTextComponent(e);
+ if (target != null) {
+ ComponentOrientation last = target.getComponentOrientation();
+ ComponentOrientation next;
+ if( last == ComponentOrientation.RIGHT_TO_LEFT )
+ next = ComponentOrientation.LEFT_TO_RIGHT;
+ else
+ next = ComponentOrientation.RIGHT_TO_LEFT;
+ target.setComponentOrientation(next);
+ target.repaint();
+ }
+ }
+ }
+
+}