0001: /*
0002: * Sun Public License Notice
0003: *
0004: * The contents of this file are subject to the Sun Public License
0005: * Version 1.0 (the "License"). You may not use this file except in
0006: * compliance with the License. A copy of the License is available at
0007: * http://www.sun.com/
0008: *
0009: * The Original Code is NetBeans. The Initial Developer of the Original
0010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
0011: * Microsystems, Inc. All Rights Reserved.
0012: */
0013:
0014: package org.netbeans.editor;
0015:
0016: import java.awt.Point;
0017: import java.awt.Rectangle;
0018: import java.awt.event.ActionEvent;
0019: import java.io.IOException;
0020: import java.io.Reader;
0021: import java.io.Writer;
0022: import java.util.ArrayList;
0023: import java.util.HashMap;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027:
0028: import javax.swing.Action;
0029: import javax.swing.JEditorPane;
0030: import javax.swing.SwingConstants;
0031: import javax.swing.text.BadLocationException;
0032: import javax.swing.text.Caret;
0033: import javax.swing.text.DefaultEditorKit;
0034: import javax.swing.text.Document;
0035: import javax.swing.text.JTextComponent;
0036: import javax.swing.text.ViewFactory;
0037:
0038: /**
0039: * Editor kit implementation for base document
0040: *
0041: * @author Miloslav Metelka
0042: * @version 1.00
0043: */
0044:
0045: public class BaseKit extends DefaultEditorKit {
0046:
0047: /** Cycle through annotations on the current line */
0048: public static final String annotationsCyclingAction = "annotations-cycling"; // NOI18N
0049:
0050: /** Move one page up and make or extend selection */
0051: public static final String selectionPageUpAction = "selection-page-up"; // NOI18N
0052:
0053: /** Move one page down and make or extend selection */
0054: public static final String selectionPageDownAction = "selection-page-down"; // NOI18N
0055:
0056: /** Remove indentation */
0057: public static final String removeTabAction = "remove-tab"; // NOI18N
0058:
0059: /** Remove selected block or do nothing - useful for popup menu */
0060: public static final String removeSelectionAction = "remove-selection"; // NOI18N
0061:
0062: /** Toggle bookmark on the current line */
0063: public static final String toggleBookmarkAction = "bookmark-toggle"; // NOI18N
0064:
0065: /** Goto the next bookmark */
0066: public static final String gotoNextBookmarkAction = "bookmark-next"; // NOI18N
0067:
0068: /** Expand the abbreviation */
0069: public static final String abbrevExpandAction = "abbrev-expand"; // NOI18N
0070:
0071: /** Reset the abbreviation accounting string */
0072: public static final String abbrevResetAction = "abbrev-reset"; // NOI18N
0073:
0074: /** Remove to the begining of the word */
0075: public static final String removeWordAction = "remove-word"; // NOI18N
0076:
0077: /** Remove to the begining of the line */
0078: public static final String removeLineBeginAction = "remove-line-begin"; // NOI18N
0079:
0080: /** Remove line */
0081: public static final String removeLineAction = "remove-line"; // NOI18N
0082:
0083: /** Toggle the typing mode to overwrite mode or back to insert mode */
0084: public static final String toggleTypingModeAction = "toggle-typing-mode"; // NOI18N
0085:
0086: /** Change the selected text or current character to uppercase */
0087: public static final String toUpperCaseAction = "to-upper-case"; // NOI18N
0088:
0089: /** Change the selected text or current character to lowercase */
0090: public static final String toLowerCaseAction = "to-lower-case"; // NOI18N
0091:
0092: /** Switch the case of the selected text or current character */
0093: public static final String switchCaseAction = "switch-case"; // NOI18N
0094:
0095: /** Find next occurence action */
0096: public static final String findNextAction = "find-next"; // NOI18N
0097:
0098: /** Find previous occurence action */
0099: public static final String findPreviousAction = "find-previous"; // NOI18N
0100:
0101: /** Toggle highlight search action */
0102: public static final String toggleHighlightSearchAction = "toggle-highlight-search"; // NOI18N
0103:
0104: /** Find current word */
0105: public static final String findSelectionAction = "find-selection"; // NOI18N
0106:
0107: /** Undo action */
0108: public static final String undoAction = "undo"; // NOI18N
0109:
0110: /** Redo action */
0111: public static final String redoAction = "redo"; // NOI18N
0112:
0113: /** Word match next */
0114: public static final String wordMatchNextAction = "word-match-next"; // NOI18N
0115:
0116: /** Word match prev */
0117: public static final String wordMatchPrevAction = "word-match-prev"; // NOI18N
0118:
0119: /** Shift line right action */
0120: public static final String shiftLineRightAction = "shift-line-right"; // NOI18N
0121:
0122: /** Shift line left action */
0123: public static final String shiftLineLeftAction = "shift-line-left"; // NOI18N
0124:
0125: /**
0126: * Action that scrolls the window so that caret is at the center of the
0127: * window
0128: */
0129: public static final String adjustWindowCenterAction = "adjust-window-center"; // NOI18N
0130:
0131: /** Action that scrolls the window so that caret is at the top of the window */
0132: public static final String adjustWindowTopAction = "adjust-window-top"; // NOI18N
0133:
0134: /**
0135: * Action that scrolls the window so that caret is at the bottom of the
0136: * window
0137: */
0138: public static final String adjustWindowBottomAction = "adjust-window-bottom"; // NOI18N
0139:
0140: /** Action that moves the caret so that caret is at the center of the window */
0141: public static final String adjustCaretCenterAction = "adjust-caret-center"; // NOI18N
0142:
0143: /** Action that moves the caret so that caret is at the top of the window */
0144: public static final String adjustCaretTopAction = "adjust-caret-top"; // NOI18N
0145:
0146: /** Action that moves the caret so that caret is at the bottom of the window */
0147: public static final String adjustCaretBottomAction = "adjust-caret-bottom"; // NOI18N
0148:
0149: /** Format part of the document text using Indent */
0150: public static final String formatAction = "format"; // NOI18N
0151:
0152: /** First non-white character on the line */
0153: public static final String firstNonWhiteAction = "first-non-white"; // NOI18N
0154:
0155: /** Last non-white character on the line */
0156: public static final String lastNonWhiteAction = "last-non-white"; // NOI18N
0157:
0158: /** First non-white character on the line */
0159: public static final String selectionFirstNonWhiteAction = "selection-first-non-white"; // NOI18N
0160:
0161: /** Last non-white character on the line */
0162: public static final String selectionLastNonWhiteAction = "selection-last-non-white"; // NOI18N
0163:
0164: /** Select the nearest identifier around caret */
0165: public static final String selectIdentifierAction = "select-identifier"; // NOI18N
0166:
0167: /** Select the next parameter (after the comma) in the given context */
0168: public static final String selectNextParameterAction = "select-next-parameter"; // NOI18N
0169:
0170: /** Go to the previous position stored in the jump-list */
0171: public static final String jumpListNextAction = "jump-list-next"; // NOI18N
0172:
0173: /** Go to the next position stored in the jump-list */
0174: public static final String jumpListPrevAction = "jump-list-prev"; // NOI18N
0175:
0176: /** Go to the last position in the previous component stored in the jump-list */
0177: public static final String jumpListNextComponentAction = "jump-list-next-component"; // NOI18N
0178:
0179: /** Go to the next position in the previous component stored in the jump-list */
0180: public static final String jumpListPrevComponentAction = "jump-list-prev-component"; // NOI18N
0181:
0182: /** Scroll window one line up */
0183: public static final String scrollUpAction = "scroll-up"; // NOI18N
0184:
0185: /** Scroll window one line down */
0186: public static final String scrollDownAction = "scroll-down"; // NOI18N
0187:
0188: /** Prefix of all macro-based actions */
0189: public static final String macroActionPrefix = "macro-"; // NOI18N
0190:
0191: /**
0192: * Start recording of macro. Only one macro recording can be active at the
0193: * time
0194: */
0195: public static final String startMacroRecordingAction = "start-macro-recording"; // NOI18N
0196:
0197: /** Stop the active recording */
0198: public static final String stopMacroRecordingAction = "stop-macro-recording"; // NOI18N
0199:
0200: /** Name of the action moving caret to the first column on the line */
0201: public static final String lineFirstColumnAction = "caret-line-first-column"; // NOI18N
0202:
0203: /** Insert the current Date and Time */
0204: public static final String insertDateTimeAction = "insert-date-time"; // NOI18N
0205:
0206: /**
0207: * Name of the action moving caret to the first column on the line and
0208: * extending the selection
0209: */
0210: public static final String selectionLineFirstColumnAction = "selection-line-first-column";
0211:
0212: /** Name of the action for generating of Glyph Gutter popup menu */
0213: public static final String generateGutterPopupAction = "generate-gutter-popup";
0214:
0215: /** Toggle visibility of line numbers */
0216: public static final String toggleLineNumbersAction = "toggle-line-numbers";
0217:
0218: private static final int KIT_CNT_PREALLOC = 57;
0219:
0220: static final long serialVersionUID = -8570495408376659348L;
0221:
0222: /** [kit-class, kit-instance] pairs are stored here */
0223: static Map kits = new HashMap(KIT_CNT_PREALLOC);
0224:
0225: /** [kit-class, keymap] pairs */
0226: static Map kitKeymaps = new HashMap(KIT_CNT_PREALLOC);
0227:
0228: /** [kit, action[]] pairs */
0229: static Map kitActions = new HashMap(KIT_CNT_PREALLOC);
0230:
0231: /** [kit, action-map] pairs */
0232: static Map kitActionMaps = new HashMap(KIT_CNT_PREALLOC);
0233:
0234: static SettingsChangeListener settingsListener = new SettingsChangeListener() {
0235: public void settingsChange(SettingsChangeEvent evt) {
0236: String settingName = (evt != null) ? evt.getSettingName()
0237: : null;
0238:
0239: boolean clearActions = (settingName == null
0240: || SettingsNames.CUSTOM_ACTION_LIST
0241: .equals(settingName) || SettingsNames.MACRO_MAP
0242: .equals(settingName));
0243:
0244: if (clearActions
0245: || SettingsNames.KEY_BINDING_LIST
0246: .equals(settingName)) {
0247: kitKeymaps.clear();
0248: }
0249:
0250: if (clearActions) {
0251: kitActions.clear();
0252: kitActionMaps.clear();
0253: } else { // only refresh action settings
0254: Iterator i = kitActions.entrySet().iterator();
0255: while (i.hasNext()) {
0256: Map.Entry me = (Map.Entry) i.next();
0257: updateActionSettings((Action[]) me.getValue(), evt,
0258: (Class) me.getKey());
0259: }
0260: }
0261: }
0262: };
0263:
0264: static {
0265: Settings.addSettingsChangeListener(settingsListener);
0266: }
0267:
0268: private static void updateActionSettings(Action[] actions,
0269: SettingsChangeEvent evt, Class kitClass) {
0270: for (int i = 0; i < actions.length; i++) {
0271: if (actions[i] instanceof BaseAction) {
0272: ((BaseAction) actions[i]).settingsChange(evt, kitClass);
0273: }
0274: }
0275: }
0276:
0277: public static synchronized BaseKit getKit(Class kitClass) {
0278: if (kitClass == null) {
0279: kitClass = BaseKit.class;
0280: }
0281: BaseKit kit = (BaseKit) kits.get(kitClass);
0282: if (kit == null) {
0283: try {
0284: kit = (BaseKit) kitClass.newInstance();
0285: } catch (IllegalAccessException e) {
0286: if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0287: e.printStackTrace();
0288: }
0289: } catch (InstantiationException e) {
0290: if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0291: e.printStackTrace();
0292: }
0293: }
0294: kits.put(kitClass, kit);
0295: }
0296: return kit;
0297: }
0298:
0299: public BaseKit() {
0300: // possibly register
0301: synchronized (BaseKit.class) {
0302: if (kits.get(this .getClass()) == null) {
0303: kits.put(this .getClass(), this ); // register itself
0304: }
0305: }
0306: }
0307:
0308: /** Clone this editor kit */
0309: public Object clone() {
0310: return this ; // no need to create another instance
0311: }
0312:
0313: /**
0314: * Fetches a factory that is suitable for producing views of any models that
0315: * are produced by this kit. The default is to have the UI produce the
0316: * factory, so this method has no implementation.
0317: *
0318: * @return the view factory
0319: */
0320: public ViewFactory getViewFactory() {
0321: return null;
0322: }
0323:
0324: /** Create caret to navigate through document */
0325: public Caret createCaret() {
0326: return new BaseCaret();
0327: }
0328:
0329: /** Create empty document */
0330: public Document createDefaultDocument() {
0331: return new BaseDocument(this .getClass(), true);
0332: }
0333:
0334: /**
0335: * Create new instance of syntax coloring scanner
0336: *
0337: * @param doc
0338: * document to operate on. It can be null in the cases the syntax
0339: * creation is not related to the particular document
0340: */
0341: public Syntax createSyntax(Document doc) {
0342: return new Syntax();
0343: }
0344:
0345: /** Create the syntax used for formatting */
0346: public Syntax createFormatSyntax(Document doc) {
0347: return createSyntax(doc);
0348: }
0349:
0350: /** Create syntax support */
0351: public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
0352: return new SyntaxSupport(doc);
0353: }
0354:
0355: /** Create the formatter appropriate for this kit */
0356: public Formatter createFormatter() {
0357: return new Formatter(this .getClass());
0358: }
0359:
0360: /** Create text UI */
0361: protected BaseTextUI createTextUI() {
0362: return new BaseTextUI();
0363: }
0364:
0365: /** Create extended UI */
0366: protected EditorUI createEditorUI() {
0367: return new EditorUI();
0368: }
0369:
0370: /** Create extended UI for printing a document. */
0371: protected EditorUI createPrintEditorUI(BaseDocument doc) {
0372: return new EditorUI(doc);
0373: }
0374:
0375: /**
0376: * This methods gives the class of the first component in the component
0377: * hierarchy that should be called when requesting focus for the other
0378: * component.
0379: *
0380: * @return class of the component that will be searched in the parents in
0381: * the hierarchy or null to do no search.
0382: */
0383: public Class getFocusableComponentClass(JTextComponent c) {
0384: return null;
0385: }
0386:
0387: public MultiKeymap getKeymap() {
0388: synchronized (Settings.class) {
0389: MultiKeymap km = (MultiKeymap) kitKeymaps.get(this
0390: .getClass());
0391: if (km == null) { // keymap not yet constructed
0392: // construct new keymap
0393: km = new MultiKeymap("Keymap for " + this .getClass()); // NOI18N
0394: // retrieve key bindings for this kit and super kits
0395: Settings.KitAndValue kv[] = Settings
0396: .getValueHierarchy(this .getClass(),
0397: SettingsNames.KEY_BINDING_LIST);
0398: // go through all levels and collect key bindings
0399: for (int i = kv.length - 1; i >= 0; i--) {
0400: List keyList = (List) kv[i].value;
0401: JTextComponent.KeyBinding[] keys = new JTextComponent.KeyBinding[keyList
0402: .size()];
0403: keyList.toArray(keys);
0404: km.load(keys, getActionMap());
0405: }
0406:
0407: kitKeymaps.put(this .getClass(), km);
0408: }
0409: return km;
0410: }
0411: }
0412:
0413: /** Inserts content from the given stream. */
0414: public void read(Reader in, Document doc, int pos)
0415: throws IOException, BadLocationException {
0416: if (doc instanceof BaseDocument) {
0417: ((BaseDocument) doc).read(in, pos); // delegate it to document
0418: } else {
0419: super .read(in, doc, pos);
0420: }
0421: }
0422:
0423: /** Writes content from a document to the given stream */
0424: public void write(Writer out, Document doc, int pos, int len)
0425: throws IOException, BadLocationException {
0426: if (doc instanceof BaseDocument) {
0427: ((BaseDocument) doc).write(out, pos, len);
0428: } else {
0429: super .write(out, doc, pos, len);
0430: }
0431: }
0432:
0433: /**
0434: * Creates map with [name, action] pairs from the given array of actions.
0435: */
0436: public static Map actionsToMap(Action[] actions) {
0437: Map map = new HashMap();
0438: for (int i = 0; i < actions.length; i++) {
0439: Action a = actions[i];
0440: String name = (String) a.getValue(Action.NAME);
0441: map.put(((name != null) ? name : ""), a); // NOI18N
0442: }
0443: return map;
0444: }
0445:
0446: /**
0447: * Converts map with [name, action] back to array of actions.
0448: */
0449: public static Action[] mapToActions(Map map) {
0450: Action[] actions = new Action[map.size()];
0451: int i = 0;
0452: for (Iterator iter = map.values().iterator(); iter.hasNext();) {
0453: actions[i++] = (Action) iter.next();
0454: }
0455: return actions;
0456: }
0457:
0458: /** Called after the kit is installed into JEditorPane */
0459: public void install(JEditorPane c) {
0460: BaseTextUI ui = createTextUI();
0461: c.setUI(ui);
0462:
0463: String propName = "netbeans.editor.noinputmethods";
0464: Object noInputMethods = System.getProperty(propName);
0465: boolean enableIM;
0466: if (noInputMethods != null) {
0467: enableIM = !Boolean.getBoolean(propName);
0468: } else {
0469: enableIM = SettingsUtil.getBoolean(this .getClass(),
0470: SettingsNames.INPUT_METHODS_ENABLED, true);
0471: }
0472:
0473: c.enableInputMethods(enableIM);
0474: executeInstallActions(c);
0475: }
0476:
0477: protected void executeInstallActions(JEditorPane c) {
0478: Settings.KitAndValue[] kv = Settings
0479: .getValueHierarchy(this .getClass(),
0480: SettingsNames.KIT_INSTALL_ACTION_NAME_LIST);
0481: for (int i = kv.length - 1; i >= 0; i--) {
0482: List actList = (List) kv[i].value;
0483: actList = translateActionNameList(actList); // translate names to
0484: // actions
0485: if (actList != null) {
0486: for (Iterator iter = actList.iterator(); iter.hasNext();) {
0487: Action a = (Action) iter.next();
0488: a.actionPerformed(new ActionEvent(c,
0489: ActionEvent.ACTION_PERFORMED, "")); // NOI18N
0490: }
0491: }
0492: }
0493: }
0494:
0495: public void deinstall(JEditorPane c) {
0496: executeDeinstallActions(c);
0497: c.setUI(null);
0498: }
0499:
0500: protected void executeDeinstallActions(JEditorPane c) {
0501: Settings.KitAndValue[] kv = Settings.getValueHierarchy(this
0502: .getClass(),
0503: SettingsNames.KIT_DEINSTALL_ACTION_NAME_LIST);
0504: for (int i = kv.length - 1; i >= 0; i--) {
0505: List actList = (List) kv[i].value;
0506: actList = translateActionNameList(actList); // translate names to
0507: // actions
0508: if (actList != null) {
0509: for (Iterator iter = actList.iterator(); iter.hasNext();) {
0510: Action a = (Action) iter.next();
0511: a.actionPerformed(new ActionEvent(c,
0512: ActionEvent.ACTION_PERFORMED, "")); // NOI18N
0513: }
0514: }
0515: }
0516: }
0517:
0518: /** Initialize document by adding the draw-layers for example. */
0519: protected void initDocument(BaseDocument doc) {
0520: }
0521:
0522: /**
0523: * Create actions that this kit supports. To use the actions of the parent
0524: * kit it's better instead of using super.createActions() to use
0525: * getKit(super.getClass()).getActions() because it can reuse existing
0526: * parent actions.
0527: */
0528: protected Action[] createActions() {
0529: return new Action[] {
0530: new DefaultKeyTypedAction(),
0531: new InsertContentAction(),
0532: new InsertBreakAction(),
0533: new InsertTabAction(),
0534: new DeleteCharAction(deletePrevCharAction, false),
0535: new DeleteCharAction(deleteNextCharAction, true),
0536: new ReadOnlyAction(),
0537: new WritableAction(),
0538: new CutAction(),
0539: new CopyAction(),
0540: new PasteAction(),
0541: new BeepAction(),
0542: new UpAction(upAction, false),
0543: new UpAction(selectionUpAction, true),
0544: new PageUpAction(pageUpAction, false),
0545: new PageUpAction(selectionPageUpAction, true),
0546: new DownAction(downAction, false),
0547: new DownAction(selectionDownAction, true),
0548: new PageDownAction(selectionPageDownAction, true),
0549: new PageDownAction(pageDownAction, false),
0550: new ForwardAction(forwardAction, false),
0551: new ForwardAction(selectionForwardAction, true),
0552: new BackwardAction(backwardAction, false),
0553: new BackwardAction(selectionBackwardAction, true),
0554: new BeginLineAction(lineFirstColumnAction, false, true),
0555: new BeginLineAction(selectionLineFirstColumnAction,
0556: true, true),
0557: new BeginLineAction(beginLineAction, false),
0558: new BeginLineAction(selectionBeginLineAction, true),
0559: new EndLineAction(endLineAction, false),
0560: new EndLineAction(selectionEndLineAction, true),
0561: new BeginAction(beginAction, false),
0562: new BeginAction(selectionBeginAction, true),
0563: new EndAction(endAction, false),
0564: new EndAction(selectionEndAction, true),
0565: new NextWordAction(nextWordAction, false),
0566: new NextWordAction(selectionNextWordAction, true),
0567: new PreviousWordAction(previousWordAction, false),
0568: new PreviousWordAction(selectionPreviousWordAction,
0569: true),
0570: new BeginWordAction(beginWordAction, false),
0571: new BeginWordAction(selectionBeginWordAction, true),
0572: new EndWordAction(endWordAction, false),
0573: new EndWordAction(selectionEndWordAction, true),
0574: new SelectWordAction(),
0575: new SelectLineAction(),
0576: new SelectAllAction(),
0577: new ActionFactory.RemoveTabAction(),
0578: new ActionFactory.RemoveWordAction(),
0579: new ActionFactory.RemoveLineBeginAction(),
0580: new ActionFactory.RemoveLineAction(),
0581: new ActionFactory.RemoveSelectionAction(),
0582: new ActionFactory.ToggleTypingModeAction(),
0583: new ActionFactory.ToggleBookmarkAction(),
0584: new ActionFactory.GotoNextBookmarkAction(
0585: gotoNextBookmarkAction, false),
0586: new ActionFactory.AbbrevExpandAction(),
0587: new ActionFactory.AbbrevResetAction(),
0588: new ActionFactory.ChangeCaseAction(toUpperCaseAction,
0589: Utilities.CASE_UPPER),
0590: new ActionFactory.ChangeCaseAction(toLowerCaseAction,
0591: Utilities.CASE_LOWER),
0592: new ActionFactory.ChangeCaseAction(switchCaseAction,
0593: Utilities.CASE_SWITCH),
0594: new ActionFactory.FindNextAction(),
0595: new ActionFactory.FindPreviousAction(),
0596: new ActionFactory.FindSelectionAction(),
0597: new ActionFactory.ToggleHighlightSearchAction(),
0598: new ActionFactory.UndoAction(),
0599: new ActionFactory.RedoAction(),
0600: new ActionFactory.WordMatchAction(wordMatchNextAction,
0601: true),
0602: new ActionFactory.WordMatchAction(wordMatchPrevAction,
0603: false),
0604: new ActionFactory.ShiftLineAction(shiftLineLeftAction,
0605: false),
0606: new ActionFactory.ShiftLineAction(shiftLineRightAction,
0607: true),
0608: new ActionFactory.AdjustWindowAction(
0609: adjustWindowTopAction, 0),
0610: new ActionFactory.AdjustWindowAction(
0611: adjustWindowCenterAction, 50),
0612: new ActionFactory.AdjustWindowAction(
0613: adjustWindowBottomAction, 100),
0614: new ActionFactory.AdjustCaretAction(
0615: adjustCaretTopAction, 0),
0616: new ActionFactory.AdjustCaretAction(
0617: adjustCaretCenterAction, 50),
0618: new ActionFactory.AdjustCaretAction(
0619: adjustCaretBottomAction, 100),
0620: new ActionFactory.FormatAction(),
0621: new ActionFactory.FirstNonWhiteAction(
0622: firstNonWhiteAction, false),
0623: new ActionFactory.FirstNonWhiteAction(
0624: selectionFirstNonWhiteAction, true),
0625: new ActionFactory.LastNonWhiteAction(
0626: lastNonWhiteAction, false),
0627: new ActionFactory.LastNonWhiteAction(
0628: selectionLastNonWhiteAction, true),
0629: new ActionFactory.SelectIdentifierAction(),
0630: new ActionFactory.SelectNextParameterAction(),
0631: new ActionFactory.JumpListPrevAction(),
0632: new ActionFactory.JumpListNextAction(),
0633: new ActionFactory.JumpListPrevComponentAction(),
0634: new ActionFactory.JumpListNextComponentAction(),
0635: new ActionFactory.ScrollUpAction(),
0636: new ActionFactory.ScrollDownAction(),
0637: new ActionFactory.StartMacroRecordingAction(),
0638: new ActionFactory.StopMacroRecordingAction(),
0639: new ActionFactory.InsertDateTimeAction(),
0640: new ActionFactory.GenerateGutterPopupAction(),
0641: new ActionFactory.ToggleLineNumbersAction(),
0642: new ActionFactory.AnnotationsCyclingAction()
0643:
0644: // Self test actions
0645: // new EditorDebug.SelfTestAction(),
0646: // new EditorDebug.DumpPlanesAction(),
0647: // new EditorDebug.DumpSyntaxMarksAction()
0648: };
0649: }
0650:
0651: protected Action[] getCustomActions() {
0652: Settings.KitAndValue kv[] = Settings.getValueHierarchy(this
0653: .getClass(), SettingsNames.CUSTOM_ACTION_LIST);
0654: if (kv.length == 0) {
0655: return null;
0656: }
0657: if (kv.length == 1) {
0658: List l = (List) kv[0].value;
0659: return (Action[]) l.toArray(new Action[l.size()]);
0660: }
0661: // more than one list of actions
0662: List l = new ArrayList();
0663: for (int i = kv.length - 1; i >= 0; i--) { // from BaseKit down
0664: l.addAll((List) kv[i].value);
0665: }
0666: return (Action[]) l.toArray(new Action[l.size()]);
0667: }
0668:
0669: protected Action[] getMacroActions() {
0670: Class kitClass = this .getClass();
0671: Map macroMap = (Map) Settings.getValue(kitClass,
0672: SettingsNames.MACRO_MAP);
0673: if (macroMap == null)
0674: return null;
0675: List actions = new ArrayList();
0676: for (Iterator it = macroMap.keySet().iterator(); it.hasNext();) {
0677: String macroName = (String) it.next();
0678: actions.add(new ActionFactory.RunMacroAction(macroName));
0679: }
0680: return (Action[]) actions.toArray(new Action[actions.size()]);
0681: }
0682:
0683: /**
0684: * Get actions associated with this kit. createActions() is called to get
0685: * basic list and then customActions are added.
0686: */
0687: public final Action[] getActions() {
0688: synchronized (Settings.class) { // possibly long running code follows
0689: Class this Class = this .getClass();
0690: Action[] actions = (Action[]) kitActions.get(this Class);
0691: if (actions == null) {
0692: // create map of actions
0693: Action[] createdActions = createActions();
0694: updateActionSettings(createdActions, null, this Class);
0695: Map actionMap = actionsToMap(createdActions);
0696: // add custom actions
0697: Action[] customActions = getCustomActions();
0698: if (customActions != null) {
0699: updateActionSettings(customActions, null, this Class);
0700: actionMap.putAll(actionsToMap(customActions));
0701: }
0702: Action[] macroActions = getMacroActions();
0703: if (macroActions != null) {
0704: updateActionSettings(macroActions, null, this Class);
0705: actionMap.putAll(actionsToMap(macroActions));
0706: }
0707:
0708: // store for later use
0709: kitActionMaps.put(this Class, actionMap);
0710: // create action array and store for later use
0711: actions = mapToActions(actionMap);
0712: kitActions.put(this Class, actions);
0713:
0714: // At this moment the actions are constructed completely
0715: // The actions will be updated now if necessary
0716: updateActions();
0717: }
0718: return actions;
0719: }
0720: }
0721:
0722: Map getActionMap() {
0723: Map actionMap = (Map) kitActionMaps.get(this .getClass());
0724: if (actionMap == null) {
0725: getActions(); // init action map
0726: actionMap = (Map) kitActionMaps.get(this .getClass());
0727: }
0728: return actionMap;
0729: }
0730:
0731: /**
0732: * Update the actions right after their creation was finished. The
0733: * <code>getActions()</code> and <code>getActionByName()</code> can be
0734: * used safely in this method. The implementation must call
0735: * <code>super.updateActions()</code> so that the updating in parent is
0736: * performed too.
0737: */
0738: protected void updateActions() {
0739: }
0740:
0741: /** Get action from its name. */
0742: public Action getActionByName(String name) {
0743: return (name != null) ? (Action) getActionMap().get(name)
0744: : null;
0745: }
0746:
0747: public List translateActionNameList(List actionNameList) {
0748: List ret = new ArrayList();
0749: if (actionNameList != null) {
0750: Iterator i = actionNameList.iterator();
0751: while (i.hasNext()) {
0752: Action a = getActionByName((String) i.next());
0753: if (a != null) {
0754: ret.add(a);
0755: }
0756: }
0757: }
0758: return ret;
0759: }
0760:
0761: /** Default typed action */
0762: public static class DefaultKeyTypedAction extends BaseAction {
0763:
0764: static final long serialVersionUID = 3069164318144463899L;
0765:
0766: public DefaultKeyTypedAction() {
0767: super (defaultKeyTypedAction, MAGIC_POSITION_RESET
0768: | SAVE_POSITION | CLEAR_STATUS_TEXT);
0769: }
0770:
0771: public void actionPerformed(ActionEvent evt,
0772: JTextComponent target) {
0773: if ((target != null) && (evt != null)) {
0774: // Check whether the target is enabled and editable
0775: if (!target.isEditable() || !target.isEnabled()) {
0776: target.getToolkit().beep();
0777: return;
0778: }
0779:
0780: // Check whether the modifiers are OK
0781: int mod = evt.getModifiers();
0782: boolean ctrl = ((mod & ActionEvent.CTRL_MASK) != 0);
0783: boolean alt = ((mod & ActionEvent.ALT_MASK) != 0);
0784: if ((alt && !ctrl) || (ctrl && !alt)) {
0785: return;
0786: }
0787:
0788: Caret caret = target.getCaret();
0789: BaseDocument doc = (BaseDocument) target.getDocument();
0790: EditorUI editorUI = Utilities.getEditorUI(target);
0791: // determine if typed char is valid
0792: String cmd = evt.getActionCommand();
0793: if ((cmd != null) && (cmd.length() == 1)) {
0794: // Utilities.clearStatusText(target);
0795:
0796: char ch = cmd.charAt(0);
0797: if ((ch >= 0x20) && (ch != 0x7F)) { // valid character
0798: editorUI.getWordMatch().clear(); // reset word
0799: // matching
0800:
0801: try {
0802: boolean doInsert = editorUI.getAbbrev()
0803: .checkAndExpand(ch, evt);
0804: if (doInsert) {
0805: if (caret.isSelectionVisible()) { // valid
0806: // selection
0807: target.replaceSelection(cmd);
0808: } else { // no selection
0809: int dotPos = caret.getDot();
0810: Boolean overwriteMode = (Boolean) editorUI
0811: .getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
0812: if (overwriteMode != null
0813: && overwriteMode
0814: .booleanValue()
0815: && dotPos < doc.getLength()
0816: && doc.getChars(dotPos, 1)[0] != '\n') { // overwrite
0817: // current
0818: // char
0819: doc.atomicLock();
0820: try {
0821: doc.remove(dotPos, 1);
0822: doc.insertString(dotPos,
0823: cmd, null);
0824: } finally {
0825: doc.atomicUnlock();
0826: }
0827: } else { // insert mode
0828: doc.insertString(dotPos, cmd,
0829: null);
0830: }
0831: }
0832: }
0833: } catch (BadLocationException e) {
0834: target.getToolkit().beep();
0835: }
0836: }
0837:
0838: checkIndent(target, cmd);
0839: }
0840:
0841: }
0842: }
0843:
0844: /**
0845: * Check whether there was any important character typed so that the
0846: * line should be possibly reformatted.
0847: */
0848: protected void checkIndent(JTextComponent target,
0849: String typedText) {
0850: }
0851:
0852: }
0853:
0854: public static class InsertBreakAction extends BaseAction {
0855:
0856: static final long serialVersionUID = 7966576342334158659L;
0857:
0858: public InsertBreakAction() {
0859: super (insertBreakAction, MAGIC_POSITION_RESET
0860: | ABBREV_RESET | WORD_MATCH_RESET);
0861: }
0862:
0863: public void actionPerformed(ActionEvent evt,
0864: JTextComponent target) {
0865: if (target != null) {
0866: if (!target.isEditable() || !target.isEnabled()) {
0867: target.getToolkit().beep();
0868: return;
0869: }
0870:
0871: target.replaceSelection("");
0872:
0873: Caret caret = target.getCaret();
0874: int dotPos = caret.getDot();
0875: BaseDocument doc = (BaseDocument) target.getDocument();
0876: dotPos = doc.getFormatter().indentNewLine(doc, dotPos);
0877: caret.setDot(dotPos);
0878: }
0879: }
0880:
0881: }
0882:
0883: public static class InsertTabAction extends BaseAction {
0884:
0885: static final long serialVersionUID = -3379768531715989243L;
0886:
0887: public InsertTabAction() {
0888: super (insertTabAction, MAGIC_POSITION_RESET | ABBREV_RESET
0889: | WORD_MATCH_RESET);
0890: }
0891:
0892: public void actionPerformed(ActionEvent evt,
0893: JTextComponent target) {
0894: if (target != null) {
0895: if (!target.isEditable() || !target.isEnabled()) {
0896: target.getToolkit().beep();
0897: return;
0898: }
0899:
0900: Caret caret = target.getCaret();
0901: BaseDocument doc = (BaseDocument) target.getDocument();
0902: if (caret.isSelectionVisible()) { // block selected
0903: try {
0904: doc.getFormatter().changeBlockIndent(doc,
0905: target.getSelectionStart(),
0906: target.getSelectionEnd(), +1);
0907: } catch (GuardedException e) {
0908: target.getToolkit().beep();
0909: } catch (BadLocationException e) {
0910: e.printStackTrace();
0911: }
0912: } else { // no selected text
0913: int dotPos = caret.getDot();
0914: int caretCol;
0915: // find caret column
0916: try {
0917: caretCol = doc.op.getVisColFromPos(dotPos);
0918: } catch (BadLocationException e) {
0919: if (Boolean
0920: .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0921: e.printStackTrace();
0922: }
0923: caretCol = 0;
0924: }
0925:
0926: try {
0927: // find indent of the first previous non-white row
0928: int upperCol = Utilities.getRowIndent(doc,
0929: dotPos, false);
0930: if (upperCol == -1) { // no prev line with indent
0931: upperCol = 0;
0932: }
0933: // is there any char on this line before cursor?
0934: int indent = Utilities
0935: .getRowIndent(doc, dotPos);
0936: // test whether we should indent
0937: if (indent == -1) {
0938: if (upperCol > caretCol) { // upper indent is
0939: // greater
0940: indent = upperCol;
0941: } else { // simulate insert tab by changing indent
0942: indent = Utilities.getNextTabColumn(
0943: doc, dotPos);
0944: }
0945: doc.getFormatter().changeRowIndent(doc,
0946: dotPos, indent);
0947: } else { // already chars on the line
0948: doc.getFormatter().insertTabString(doc,
0949: dotPos);
0950:
0951: }
0952: } catch (BadLocationException e) {
0953: // use the same pos
0954: }
0955: }
0956: }
0957:
0958: }
0959:
0960: }
0961:
0962: /** Compound action that encapsulates several actions */
0963: public static class CompoundAction extends BaseAction {
0964:
0965: Action[] actions;
0966:
0967: static final long serialVersionUID = 1649688300969753758L;
0968:
0969: public CompoundAction(String nm, Action actions[]) {
0970: this (nm, 0, actions);
0971: }
0972:
0973: public CompoundAction(String nm, int resetMask,
0974: Action actions[]) {
0975: super (nm, resetMask);
0976: this .actions = actions;
0977: }
0978:
0979: public void actionPerformed(ActionEvent evt,
0980: JTextComponent target) {
0981: if (target != null) {
0982: for (int i = 0; i < actions.length; i++) {
0983: Action a = actions[i];
0984: if (a instanceof BaseAction) {
0985: ((BaseAction) a).actionPerformed(evt, target);
0986: } else {
0987: a.actionPerformed(evt);
0988: }
0989: }
0990: }
0991: }
0992: }
0993:
0994: /**
0995: * Compound action that gets and executes its actions depending on the kit
0996: * of the component. The other advantage is that it doesn't create
0997: * additional instances of compound actions.
0998: */
0999: public static class KitCompoundAction extends BaseAction {
1000:
1001: private String[] actionNames;
1002:
1003: static final long serialVersionUID = 8415246475764264835L;
1004:
1005: public KitCompoundAction(String nm, String actionNames[]) {
1006: this (nm, 0, actionNames);
1007: }
1008:
1009: public KitCompoundAction(String nm, int resetMask,
1010: String actionNames[]) {
1011: super (nm, resetMask);
1012: this .actionNames = actionNames;
1013: }
1014:
1015: public void actionPerformed(ActionEvent evt,
1016: JTextComponent target) {
1017: if (target != null) {
1018: BaseKit kit = Utilities.getKit(target);
1019: if (kit != null) {
1020: for (int i = 0; i < actionNames.length; i++) {
1021: Action a = kit.getActionByName(actionNames[i]);
1022: if (a != null) {
1023: if (a instanceof BaseAction) {
1024: ((BaseAction) a).actionPerformed(evt,
1025: target);
1026: } else {
1027: a.actionPerformed(evt);
1028: }
1029: }
1030: }
1031: }
1032: }
1033: }
1034: }
1035:
1036: public static class InsertContentAction extends BaseAction {
1037:
1038: static final long serialVersionUID = 5647751370952797218L;
1039:
1040: public InsertContentAction() {
1041: super (insertContentAction, MAGIC_POSITION_RESET
1042: | ABBREV_RESET | WORD_MATCH_RESET);
1043: }
1044:
1045: public void actionPerformed(ActionEvent evt,
1046: JTextComponent target) {
1047: if ((target != null) && (evt != null)) {
1048: if (!target.isEditable() || !target.isEnabled()) {
1049: target.getToolkit().beep();
1050: return;
1051: }
1052:
1053: String content = evt.getActionCommand();
1054: if (content != null) {
1055: target.replaceSelection(content);
1056: } else {
1057: target.getToolkit().beep();
1058: }
1059: }
1060: }
1061: }
1062:
1063: /** Insert text specified in constructor */
1064: public static class InsertStringAction extends BaseAction {
1065:
1066: String text;
1067:
1068: static final long serialVersionUID = -2755852016584693328L;
1069:
1070: public InsertStringAction(String nm, String text) {
1071: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1072: | WORD_MATCH_RESET);
1073: this .text = text;
1074: }
1075:
1076: public void actionPerformed(ActionEvent evt,
1077: JTextComponent target) {
1078: if (target != null) {
1079: if (!target.isEditable() || !target.isEnabled()) {
1080: target.getToolkit().beep();
1081: return;
1082: }
1083:
1084: target.replaceSelection(text);
1085: }
1086: }
1087: }
1088:
1089: /** Remove previous or next character */
1090: public static class DeleteCharAction extends BaseAction {
1091:
1092: boolean nextChar;
1093:
1094: static final long serialVersionUID = -4321971925753148556L;
1095:
1096: public DeleteCharAction(String nm, boolean nextChar) {
1097: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1098: | WORD_MATCH_RESET);
1099: this .nextChar = nextChar;
1100: }
1101:
1102: public void actionPerformed(ActionEvent evt,
1103: JTextComponent target) {
1104: if (target != null) {
1105: if (!target.isEditable() || !target.isEnabled()) {
1106: target.getToolkit().beep();
1107: return;
1108: }
1109:
1110: try {
1111: Document doc = target.getDocument();
1112: Caret caret = target.getCaret();
1113: int dot = caret.getDot();
1114: int mark = caret.getMark();
1115: if (dot != mark) { // remove selection
1116: doc.remove(Math.min(dot, mark), Math.abs(dot
1117: - mark));
1118: } else {
1119: if (nextChar) { // remove next char
1120: doc.remove(dot, 1);
1121: } else { // remove previous char
1122: doc.remove(dot - 1, 1);
1123: }
1124: }
1125: } catch (BadLocationException e) {
1126: target.getToolkit().beep();
1127: }
1128: }
1129: }
1130: }
1131:
1132: public static class ReadOnlyAction extends BaseAction {
1133:
1134: static final long serialVersionUID = 9204335480208463193L;
1135:
1136: public ReadOnlyAction() {
1137: super (readOnlyAction);
1138: }
1139:
1140: public void actionPerformed(ActionEvent evt,
1141: JTextComponent target) {
1142: if (target != null) {
1143: target.setEditable(false);
1144: }
1145: }
1146: }
1147:
1148: public static class WritableAction extends BaseAction {
1149:
1150: static final long serialVersionUID = -5982547952800937954L;
1151:
1152: public WritableAction() {
1153: super (writableAction);
1154: }
1155:
1156: public void actionPerformed(ActionEvent evt,
1157: JTextComponent target) {
1158: if (target != null) {
1159: target.setEditable(true);
1160: }
1161: }
1162: }
1163:
1164: public static class CutAction extends BaseAction {
1165:
1166: static final long serialVersionUID = 6377157040901778853L;
1167:
1168: public CutAction() {
1169: super (cutAction, ABBREV_RESET | UNDO_MERGE_RESET
1170: | WORD_MATCH_RESET);
1171: setEnabled(false);
1172: putValue("helpID", CutAction.class.getName());
1173: }
1174:
1175: public void actionPerformed(ActionEvent evt,
1176: JTextComponent target) {
1177: if (target != null) {
1178: if (!target.isEditable() || !target.isEnabled()) {
1179: target.getToolkit().beep();
1180: return;
1181: }
1182:
1183: target.cut();
1184: }
1185: }
1186: }
1187:
1188: public static class CopyAction extends BaseAction {
1189:
1190: static final long serialVersionUID = -5119779005431986964L;
1191:
1192: public CopyAction() {
1193: super (copyAction, ABBREV_RESET | UNDO_MERGE_RESET
1194: | WORD_MATCH_RESET);
1195: setEnabled(false);
1196: putValue("helpID", CopyAction.class.getName());
1197: }
1198:
1199: public void actionPerformed(ActionEvent evt,
1200: JTextComponent target) {
1201: if (target != null) {
1202: target.copy();
1203: }
1204: }
1205: }
1206:
1207: public static class PasteAction extends BaseAction {
1208:
1209: static final long serialVersionUID = 5839791453996432149L;
1210:
1211: public PasteAction() {
1212: super (pasteAction, ABBREV_RESET | UNDO_MERGE_RESET
1213: | WORD_MATCH_RESET);
1214: putValue("helpID", PasteAction.class.getName());
1215: }
1216:
1217: public void actionPerformed(ActionEvent evt,
1218: JTextComponent target) {
1219: if (target != null) {
1220: if (!target.isEditable() || !target.isEnabled()) {
1221: target.getToolkit().beep();
1222: return;
1223: }
1224:
1225: target.paste();
1226: }
1227: }
1228: }
1229:
1230: public static class BeepAction extends BaseAction {
1231:
1232: static final long serialVersionUID = -4474054576633223968L;
1233:
1234: public BeepAction() {
1235: super (beepAction);
1236: }
1237:
1238: public void actionPerformed(ActionEvent evt,
1239: JTextComponent target) {
1240: if (target != null) {
1241: target.getToolkit().beep();
1242: }
1243: }
1244: }
1245:
1246: public static class UpAction extends BaseAction {
1247:
1248: boolean select;
1249:
1250: static final long serialVersionUID = 4621760742646981563L;
1251:
1252: public UpAction(String nm, boolean select) {
1253: super (nm, ABBREV_RESET | UNDO_MERGE_RESET
1254: | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1255: this .select = select;
1256: }
1257:
1258: public void actionPerformed(ActionEvent evt,
1259: JTextComponent target) {
1260: if (target != null) {
1261: try {
1262: Caret caret = target.getCaret();
1263: int dot = caret.getDot();
1264: Point p = caret.getMagicCaretPosition();
1265: if (p == null) {
1266: Rectangle r = target.modelToView(dot);
1267: p = new Point(r.x, r.y);
1268: caret.setMagicCaretPosition(p);
1269: }
1270: try {
1271: dot = Utilities.getPositionAbove(target, dot,
1272: p.x);
1273: if (select) {
1274: caret.moveDot(dot);
1275: } else {
1276: if (caret instanceof BaseCaret) {
1277: BaseCaret bCaret = (BaseCaret) caret;
1278: bCaret.setDot(dot, bCaret,
1279: EditorUI.SCROLL_MOVE);
1280:
1281: } else {
1282: caret.setDot(dot);
1283: }
1284: }
1285: } catch (BadLocationException e) {
1286: // the position stays the same
1287: }
1288: } catch (BadLocationException ex) {
1289: target.getToolkit().beep();
1290: }
1291: }
1292: }
1293: }
1294:
1295: public static class DownAction extends BaseAction {
1296:
1297: boolean select;
1298:
1299: static final long serialVersionUID = -5635702355125266822L;
1300:
1301: public DownAction(String nm, boolean select) {
1302: super (nm, ABBREV_RESET | UNDO_MERGE_RESET
1303: | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1304: this .select = select;
1305: }
1306:
1307: public void actionPerformed(ActionEvent evt,
1308: JTextComponent target) {
1309: if (target != null) {
1310: try {
1311: Caret caret = target.getCaret();
1312: int dot = caret.getDot();
1313: Point p = caret.getMagicCaretPosition();
1314: if (p == null) {
1315: Rectangle r = target.modelToView(dot);
1316: p = new Point(r.x, r.y);
1317: caret.setMagicCaretPosition(p);
1318: }
1319: try {
1320: dot = Utilities.getPositionBelow(target, dot,
1321: p.x);
1322: if (select) {
1323: caret.moveDot(dot);
1324: } else {
1325: if (caret instanceof BaseCaret) {
1326: BaseCaret bCaret = (BaseCaret) caret;
1327: bCaret.setDot(dot, bCaret,
1328: EditorUI.SCROLL_MOVE);
1329:
1330: } else {
1331: caret.setDot(dot);
1332: }
1333: }
1334: } catch (BadLocationException e) {
1335: // position stays the same
1336: }
1337: } catch (BadLocationException ex) {
1338: target.getToolkit().beep();
1339: }
1340: }
1341: }
1342: }
1343:
1344: /** Go one page up */
1345: public static class PageUpAction extends BaseAction {
1346:
1347: boolean select;
1348:
1349: static final long serialVersionUID = -3107382148581661079L;
1350:
1351: public PageUpAction(String nm, boolean select) {
1352: super (nm, ABBREV_RESET | UNDO_MERGE_RESET
1353: | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1354: this .select = select;
1355: }
1356:
1357: public void actionPerformed(ActionEvent evt,
1358: JTextComponent target) {
1359: if (target != null) {
1360: try {
1361: Caret caret = target.getCaret();
1362: BaseDocument doc = (BaseDocument) target
1363: .getDocument();
1364: int dot = caret.getDot();
1365: Rectangle tgtRect = ((BaseTextUI) target.getUI())
1366: .modelToView(target, dot);
1367: Point p = caret.getMagicCaretPosition();
1368: if (p == null) {
1369: p = new Point((int) tgtRect.x, (int) tgtRect.y);
1370: caret.setMagicCaretPosition(p);
1371: } else {
1372: p.y = (int) tgtRect.y;
1373: }
1374: EditorUI editorUI = ((BaseTextUI) target.getUI())
1375: .getEditorUI();
1376: Rectangle bounds = editorUI.getExtentBounds();
1377: int trHeight = Math.max(tgtRect.height, 1); // prevent
1378: // division by
1379: // zero
1380: int baseY = (bounds.y + trHeight - 1) / trHeight
1381: * trHeight;
1382: int lines = (int) (bounds.height / trHeight);
1383: int baseHeight = lines * trHeight;
1384: tgtRect.y = Math.max(baseY - baseHeight, 0);
1385: tgtRect.height = bounds.height;
1386: p.y = (int) Math.max(p.y - baseHeight, 0);
1387: int newDot = target.viewToModel(p);
1388: editorUI.scrollRectToVisible(tgtRect,
1389: EditorUI.SCROLL_DEFAULT);
1390: if (select) {
1391: caret.moveDot(newDot);
1392: } else {
1393: caret.setDot(newDot);
1394: }
1395: } catch (BadLocationException ex) {
1396: target.getToolkit().beep();
1397: }
1398: }
1399: }
1400: }
1401:
1402: public static class ForwardAction extends BaseAction {
1403:
1404: boolean select;
1405:
1406: static final long serialVersionUID = 8007293230193334414L;
1407:
1408: public ForwardAction(String nm, boolean select) {
1409: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1410: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1411: | CLEAR_STATUS_TEXT);
1412: this .select = select;
1413: }
1414:
1415: public void actionPerformed(ActionEvent evt,
1416: JTextComponent target) {
1417: if (target != null) {
1418: Caret caret = target.getCaret();
1419: try {
1420: int pos;
1421: if (!select && caret.isSelectionVisible()) {
1422: pos = target.getSelectionEnd();
1423: if (pos != caret.getDot())
1424: pos--;
1425: } else
1426: pos = caret.getDot();
1427: int dot = target.getUI().getNextVisualPositionFrom(
1428: target, pos, null, SwingConstants.EAST,
1429: null);
1430: if (select) {
1431: caret.moveDot(dot);
1432: } else {
1433: caret.setDot(dot);
1434: }
1435: } catch (BadLocationException ex) {
1436: target.getToolkit().beep();
1437: }
1438: }
1439: }
1440: }
1441:
1442: /** Go one page down */
1443: public static class PageDownAction extends BaseAction {
1444:
1445: boolean select;
1446:
1447: static final long serialVersionUID = 8942534850985048862L;
1448:
1449: public PageDownAction(String nm, boolean select) {
1450: super (nm, ABBREV_RESET | UNDO_MERGE_RESET
1451: | WORD_MATCH_RESET | CLEAR_STATUS_TEXT);
1452: this .select = select;
1453: }
1454:
1455: public void actionPerformed(ActionEvent evt,
1456: JTextComponent target) {
1457: if (target != null) {
1458: try {
1459: Caret caret = target.getCaret();
1460: BaseDocument doc = (BaseDocument) target
1461: .getDocument();
1462: int dot = caret.getDot();
1463: Rectangle tgtRect = ((BaseTextUI) target.getUI())
1464: .modelToView(target, dot);
1465: Point p = caret.getMagicCaretPosition();
1466: if (p == null) {
1467: p = new Point(tgtRect.x, tgtRect.y);
1468: caret.setMagicCaretPosition(p);
1469: } else {
1470: p.y = tgtRect.y;
1471: }
1472: EditorUI editorUI = ((BaseTextUI) target.getUI())
1473: .getEditorUI();
1474: Rectangle bounds = editorUI.getExtentBounds();
1475: int trHeight = Math.max(tgtRect.height, 1); // prevent
1476: // division by
1477: // zero
1478: int baseY = bounds.y / trHeight * trHeight;
1479: int lines = bounds.height / trHeight;
1480: int baseHeight = lines * trHeight;
1481: tgtRect.y = Math.max(baseY + baseHeight, 0);
1482: tgtRect.height = bounds.height;
1483: p.y = Math.max(p.y + baseHeight, 0);
1484: int newDot = target.viewToModel(p);
1485: editorUI.scrollRectToVisible(tgtRect,
1486: EditorUI.SCROLL_DEFAULT);
1487: if (select) {
1488: caret.moveDot(newDot);
1489: } else {
1490: if (caret instanceof BaseCaret) {
1491: BaseCaret bCaret = (BaseCaret) caret;
1492: bCaret.setDot(newDot, bCaret,
1493: EditorUI.SCROLL_MOVE);
1494:
1495: } else {
1496: caret.setDot(newDot);
1497: }
1498: }
1499: } catch (BadLocationException ex) {
1500: target.getToolkit().beep();
1501: }
1502: }
1503: }
1504: }
1505:
1506: public static class BackwardAction extends BaseAction {
1507:
1508: boolean select;
1509:
1510: static final long serialVersionUID = -3048379822817847356L;
1511:
1512: public BackwardAction(String nm, boolean select) {
1513: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1514: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1515: | CLEAR_STATUS_TEXT);
1516: this .select = select;
1517: }
1518:
1519: public void actionPerformed(ActionEvent evt,
1520: JTextComponent target) {
1521: if (target != null) {
1522: Caret caret = target.getCaret();
1523: try {
1524: int pos;
1525: if (!select && caret.isSelectionVisible()) {
1526: pos = target.getSelectionStart();
1527: if (pos != caret.getDot())
1528: pos++;
1529: } else
1530: pos = caret.getDot();
1531: int dot = target.getUI().getNextVisualPositionFrom(
1532: target, pos, null, SwingConstants.WEST,
1533: null);
1534: if (select) {
1535: caret.moveDot(dot);
1536: } else {
1537: if (caret instanceof BaseCaret) {
1538: BaseCaret bCaret = (BaseCaret) caret;
1539: bCaret.setDot(dot, bCaret,
1540: EditorUI.SCROLL_MOVE);
1541:
1542: } else {
1543: caret.setDot(dot);
1544: }
1545: }
1546: } catch (BadLocationException ex) {
1547: target.getToolkit().beep();
1548: }
1549: }
1550: }
1551: }
1552:
1553: public static class BeginLineAction extends BaseAction {
1554:
1555: protected boolean select;
1556:
1557: /**
1558: * Whether the action should go to the begining of the text on the line
1559: * or to the first column on the line
1560: */
1561: boolean homeKeyColumnOne;
1562:
1563: static final long serialVersionUID = 3269462923524077779L;
1564:
1565: public BeginLineAction(String nm, boolean select) {
1566: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1567: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1568: | CLEAR_STATUS_TEXT);
1569: this .select = select;
1570: homeKeyColumnOne = false;
1571: }
1572:
1573: public BeginLineAction(String nm, boolean select,
1574: boolean columnOne) {
1575: this (nm, select);
1576: homeKeyColumnOne = columnOne;
1577: }
1578:
1579: public void actionPerformed(ActionEvent evt,
1580: JTextComponent target) {
1581: if (target != null) {
1582: Caret caret = target.getCaret();
1583: BaseDocument doc = (BaseDocument) target.getDocument();
1584: try {
1585: int dot = caret.getDot();
1586: int lineStartPos = Utilities.getRowStart(doc, dot,
1587: 0);
1588: if (homeKeyColumnOne) { // to first column
1589: dot = lineStartPos;
1590: } else { // either to line start or text start
1591: int textStartPos = Utilities
1592: .getRowFirstNonWhite(doc, lineStartPos);
1593: if (textStartPos < 0) { // no text on the line
1594: textStartPos = Utilities.getRowEnd(doc,
1595: lineStartPos);
1596: }
1597: if (dot == lineStartPos) { // go to the text start pos
1598: dot = textStartPos;
1599: } else if (dot <= textStartPos) {
1600: dot = lineStartPos;
1601: } else {
1602: dot = textStartPos;
1603: }
1604: }
1605: if (select) {
1606: caret.moveDot(dot);
1607: } else {
1608: caret.setDot(dot);
1609: }
1610: } catch (BadLocationException e) {
1611: target.getToolkit().beep();
1612: }
1613: }
1614: }
1615: }
1616:
1617: public static class EndLineAction extends BaseAction {
1618:
1619: protected boolean select;
1620:
1621: static final long serialVersionUID = 5216077634055190170L;
1622:
1623: public EndLineAction(String nm, boolean select) {
1624: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1625: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1626: | CLEAR_STATUS_TEXT);
1627: this .select = select;
1628: }
1629:
1630: public void actionPerformed(ActionEvent evt,
1631: JTextComponent target) {
1632: if (target != null) {
1633: Caret caret = target.getCaret();
1634: try {
1635: int dot = Utilities.getRowEnd(target, caret
1636: .getDot());
1637: if (select) {
1638: caret.moveDot(dot);
1639: } else {
1640: caret.setDot(dot);
1641: }
1642: // now move the magic caret position far to the right
1643: Rectangle r = target.modelToView(dot);
1644: Point p = new Point(Integer.MAX_VALUE / 2, r.y);
1645: caret.setMagicCaretPosition(p);
1646: } catch (BadLocationException e) {
1647: target.getToolkit().beep();
1648: }
1649: }
1650: }
1651: }
1652:
1653: public static class BeginAction extends BaseAction {
1654:
1655: boolean select;
1656:
1657: static final long serialVersionUID = 3463563396210234361L;
1658:
1659: public BeginAction(String nm, boolean select) {
1660: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1661: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1662: | SAVE_POSITION | CLEAR_STATUS_TEXT);
1663: this .select = select;
1664: }
1665:
1666: public void actionPerformed(ActionEvent evt,
1667: JTextComponent target) {
1668: if (target != null) {
1669: Caret caret = target.getCaret();
1670: int dot = 0; // begin of document
1671: if (select) {
1672: caret.moveDot(dot);
1673: } else {
1674: caret.setDot(dot);
1675: }
1676: }
1677: }
1678: }
1679:
1680: public static class EndAction extends BaseAction {
1681:
1682: boolean select;
1683:
1684: static final long serialVersionUID = 8547506353130203657L;
1685:
1686: public EndAction(String nm, boolean select) {
1687: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1688: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1689: | SAVE_POSITION | CLEAR_STATUS_TEXT);
1690: this .select = select;
1691: }
1692:
1693: public void actionPerformed(ActionEvent evt,
1694: JTextComponent target) {
1695: if (target != null) {
1696: Caret caret = target.getCaret();
1697: int dot = target.getDocument().getLength(); // end of document
1698: if (select) {
1699: caret.moveDot(dot);
1700: } else {
1701: caret.setDot(dot);
1702: }
1703: }
1704: }
1705: }
1706:
1707: public static class NextWordAction extends BaseAction {
1708:
1709: boolean select;
1710:
1711: static final long serialVersionUID = -5909906947175434032L;
1712:
1713: public NextWordAction(String nm, boolean select) {
1714: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1715: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1716: | CLEAR_STATUS_TEXT);
1717: this .select = select;
1718: }
1719:
1720: public void actionPerformed(ActionEvent evt,
1721: JTextComponent target) {
1722: if (target != null) {
1723: Caret caret = target.getCaret();
1724: try {
1725: int dotPos = caret.getDot();
1726: dotPos = Utilities.getNextWord(target, dotPos);
1727: if (select) {
1728: caret.moveDot(dotPos);
1729: } else {
1730: caret.setDot(dotPos);
1731: }
1732: } catch (BadLocationException ex) {
1733: target.getToolkit().beep();
1734: }
1735: }
1736: }
1737: }
1738:
1739: public static class PreviousWordAction extends BaseAction {
1740:
1741: boolean select;
1742:
1743: static final long serialVersionUID = -5465143382669785799L;
1744:
1745: public PreviousWordAction(String nm, boolean select) {
1746: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1747: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1748: | CLEAR_STATUS_TEXT);
1749: this .select = select;
1750: }
1751:
1752: public void actionPerformed(ActionEvent evt,
1753: JTextComponent target) {
1754: if (target != null) {
1755: Caret caret = target.getCaret();
1756: try {
1757: int dot = Utilities.getPreviousWord(target, caret
1758: .getDot());
1759: if (select) {
1760: caret.moveDot(dot);
1761: } else {
1762: caret.setDot(dot);
1763: }
1764: } catch (BadLocationException ex) {
1765: target.getToolkit().beep();
1766: }
1767: }
1768: }
1769: }
1770:
1771: public static class BeginWordAction extends BaseAction {
1772:
1773: boolean select;
1774:
1775: static final long serialVersionUID = 3991338381212491110L;
1776:
1777: public BeginWordAction(String nm, boolean select) {
1778: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1779: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1780: | CLEAR_STATUS_TEXT);
1781: this .select = select;
1782: }
1783:
1784: public void actionPerformed(ActionEvent evt,
1785: JTextComponent target) {
1786: if (target != null) {
1787: Caret caret = target.getCaret();
1788: try {
1789: int dot = Utilities.getWordStart(target, caret
1790: .getDot());
1791: if (select) {
1792: caret.moveDot(dot);
1793: } else {
1794: caret.setDot(dot);
1795: }
1796: } catch (BadLocationException ex) {
1797: target.getToolkit().beep();
1798: }
1799: }
1800: }
1801: }
1802:
1803: public static class EndWordAction extends BaseAction {
1804:
1805: boolean select;
1806:
1807: static final long serialVersionUID = 3812523676620144633L;
1808:
1809: public EndWordAction(String nm, boolean select) {
1810: super (nm, MAGIC_POSITION_RESET | ABBREV_RESET
1811: | UNDO_MERGE_RESET | WORD_MATCH_RESET
1812: | CLEAR_STATUS_TEXT);
1813: this .select = select;
1814: }
1815:
1816: public void actionPerformed(ActionEvent evt,
1817: JTextComponent target) {
1818: if (target != null) {
1819: Caret caret = target.getCaret();
1820: try {
1821: int dot = Utilities.getWordEnd(target, caret
1822: .getDot());
1823: if (select) {
1824: caret.moveDot(dot);
1825: } else {
1826: caret.setDot(dot);
1827: }
1828: } catch (BadLocationException ex) {
1829: target.getToolkit().beep();
1830: }
1831: }
1832: }
1833: }
1834:
1835: /** Select word around caret */
1836: public static class SelectWordAction extends KitCompoundAction {
1837:
1838: static final long serialVersionUID = 7678848538073016357L;
1839:
1840: public SelectWordAction() {
1841: super (selectWordAction, new String[] { beginWordAction,
1842: selectionEndWordAction });
1843: }
1844:
1845: }
1846:
1847: /** Select line around caret */
1848: public static class SelectLineAction extends KitCompoundAction {
1849:
1850: static final long serialVersionUID = -7407681863035740281L;
1851:
1852: public SelectLineAction() {
1853: super (selectLineAction, new String[] {
1854: lineFirstColumnAction, selectionEndLineAction,
1855: selectionForwardAction });
1856: }
1857:
1858: }
1859:
1860: /** Select text of whole document */
1861: public static class SelectAllAction extends KitCompoundAction {
1862:
1863: static final long serialVersionUID = -3502499718130556524L;
1864:
1865: public SelectAllAction() {
1866: super (selectAllAction, new String[] { beginAction,
1867: selectionEndAction });
1868: }
1869:
1870: }
1871:
1872: }
|