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.ext;
0015:
0016: import java.awt.Rectangle;
0017: import java.awt.event.ActionEvent;
0018: import java.io.IOException;
0019: import java.util.Iterator;
0020: import java.util.List;
0021:
0022: import javax.swing.Action;
0023: import javax.swing.JMenuItem;
0024: import javax.swing.JPopupMenu;
0025: import javax.swing.KeyStroke;
0026: import javax.swing.text.BadLocationException;
0027: import javax.swing.text.Caret;
0028: import javax.swing.text.JTextComponent;
0029: import javax.swing.text.Keymap;
0030: import javax.swing.text.TextAction;
0031:
0032: import org.netbeans.editor.BaseAction;
0033: import org.netbeans.editor.BaseDocument;
0034: import org.netbeans.editor.BaseKit;
0035: import org.netbeans.editor.EditorUI;
0036: import org.netbeans.editor.Formatter;
0037: import org.netbeans.editor.Settings;
0038: import org.netbeans.editor.SyntaxSupport;
0039: import org.netbeans.editor.Utilities;
0040:
0041: /**
0042: * Extended kit offering advanced functionality
0043: *
0044: * @author Miloslav Metelka
0045: * @version 1.00
0046: */
0047: public class ExtKit extends BaseKit {
0048:
0049: /**
0050: * This action is searched and executed when the popup menu should be
0051: * displayed to build the popup menu.
0052: */
0053: public static final String buildPopupMenuAction = "build-popup-menu"; // NOI18N
0054:
0055: /**
0056: * Show popup menu.
0057: */
0058: public static final String showPopupMenuAction = "show-popup-menu"; // NOI18N
0059:
0060: /**
0061: * This action is searched and executed when the tool-tip should be
0062: * displayed by tool-tip support to build the tool-tip.
0063: */
0064: public static final String buildToolTipAction = "build-tool-tip"; // NOI18N
0065:
0066: /**
0067: * Open find dialog action - this action is defined in view package, but its
0068: * name is defined here for clarity
0069: */
0070: public static final String findAction = "find"; // NOI18N
0071:
0072: /**
0073: * Open replace dialog action - this action is defined in view package, but
0074: * its name is defined here for clarity
0075: */
0076: public static final String replaceAction = "replace"; // NOI18N
0077:
0078: /**
0079: * Open goto dialog action - this action is defined in view package, but its
0080: * name is defined here for clarity
0081: */
0082: public static final String gotoAction = "goto"; // NOI18N
0083:
0084: /** Goto declaration depending on the context under the caret */
0085: public static final String gotoDeclarationAction = "goto-declaration"; // NOI18N
0086:
0087: /** Goto source depending on the context under the caret */
0088: public static final String gotoSourceAction = "goto-source"; // NOI18N
0089:
0090: /** Goto help depending on the context under the caret */
0091: public static final String gotoHelpAction = "goto-help"; // NOI18N
0092:
0093: /** Match brace */
0094: public static final String matchBraceAction = "match-brace"; // NOI18N
0095:
0096: /** Select the text to the matching bracket */
0097: public static final String selectionMatchBraceAction = "selection-match-brace"; // NOI18N
0098:
0099: /** Toggle the case for the first character of the word under caret */
0100: public static final String toggleCaseIdentifierBeginAction = "toggle-case-identifier-begin"; // NOI18N
0101:
0102: /** Advanced code selection technique */
0103: public static final String codeSelectAction = "code-select"; // NOI18N
0104:
0105: /** Action used when escape is pressed. By default it hides popup-menu */
0106: public static final String escapeAction = "escape"; // NOI18N
0107:
0108: /** Find the completion help and show it in the completion pane. */
0109: public static final String completionShowAction = "completion-show"; // NOI18N
0110:
0111: /** Hide completion pane. */
0112: public static final String completionHideAction = "completion-hide"; // NOI18N
0113:
0114: /** Used by completion to provide alternate item inserting way. */
0115: public static final String shiftInsertBreakAction = "shift-insert-break"; // NOI18N
0116:
0117: /** Comment out the selected block */
0118: public static final String commentAction = "comment"; // NOI18N
0119:
0120: /** Uncomment the selected block */
0121: public static final String uncommentAction = "uncomment"; // NOI18N
0122:
0123: /** Shared suport for find and replace dialogs */
0124: private static FindDialogSupport findDialogSupport;
0125:
0126: public ExtKit() {
0127: }
0128:
0129: /** Create caret to navigate through document */
0130: public Caret createCaret() {
0131: return new ExtCaret();
0132: }
0133:
0134: public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
0135: return new ExtSyntaxSupport(doc);
0136: }
0137:
0138: public Completion createCompletion(ExtEditorUI extEditorUI) {
0139: return null;
0140: }
0141:
0142: protected EditorUI createEditorUI() {
0143: return new ExtEditorUI();
0144: }
0145:
0146: protected Action[] createActions() {
0147: Action[] extActions = new Action[] {
0148: new BuildPopupMenuAction(),
0149: new ShowPopupMenuAction(),
0150: new BuildToolTipAction(),
0151: new FindAction(),
0152: new ReplaceAction(),
0153: new GotoAction(),
0154: new GotoDeclarationAction(),
0155: new ToggleCaseIdentifierBeginAction(),
0156: new MatchBraceAction(matchBraceAction, false),
0157: new MatchBraceAction(selectionMatchBraceAction, true),
0158: // new CodeSelectAction(), // the actionPerformed is empty and
0159: // so I'm removing the action from the list
0160: new EscapeAction(), new ExtDefaultKeyTypedAction(),
0161: new ExtInsertTabAction(), new ExtInsertBreakAction(),
0162: new ExtUpAction(upAction, false),
0163: new ExtPageUpAction(pageUpAction, false),
0164: new ExtDownAction(downAction, false),
0165: new ExtPageDownAction(pageDownAction, false),
0166: new ExtBeginLineAction(beginLineAction, false),
0167: new ExtBeginLineAction(selectionBeginLineAction, true),
0168: new ExtEndLineAction(endLineAction, false),
0169: new ExtEndLineAction(selectionEndLineAction, true),
0170: new CompletionShowAction(), new CompletionHideAction(),
0171: new ShiftInsertBreakAction() };
0172: return TextAction
0173: .augmentList(super .createActions(), extActions);
0174: }
0175:
0176: /**
0177: * Called before the popup menu is shown to possibly rebuild the popup menu.
0178: */
0179: public static class BuildPopupMenuAction extends BaseAction {
0180:
0181: static final long serialVersionUID = 4257043398248915291L;
0182:
0183: public BuildPopupMenuAction() {
0184: super (buildPopupMenuAction, NO_RECORDING);
0185: }
0186:
0187: public void actionPerformed(ActionEvent evt,
0188: JTextComponent target) {
0189: if (target != null) {
0190: JPopupMenu pm = buildPopupMenu(target);
0191: ExtUtilities.getExtEditorUI(target).setPopupMenu(pm);
0192: }
0193: }
0194:
0195: protected JPopupMenu buildPopupMenu(JTextComponent target) {
0196: JPopupMenu pm = new JPopupMenu();
0197: EditorUI ui = Utilities.getEditorUI(target);
0198: List l = (List) Settings
0199: .getValue(
0200: Utilities.getKitClass(target),
0201: (ui == null || ui.hasExtComponent()) ? ExtSettingsNames.POPUP_MENU_ACTION_NAME_LIST
0202: : ExtSettingsNames.DIALOG_POPUP_MENU_ACTION_NAME_LIST);
0203:
0204: if (l != null) {
0205: Iterator i = l.iterator();
0206: while (i.hasNext()) {
0207: String an = (String) i.next();
0208: addAction(target, pm, an);
0209: }
0210: }
0211: return pm;
0212: }
0213:
0214: /**
0215: * Add the action to the popup menu. This method is called for each
0216: * action-name found in the action-name-list. It should add the
0217: * appopriate menu item to the popup menu.
0218: *
0219: * @param target
0220: * target component for which the menu is being constructed.
0221: * @param popupMenu
0222: * popup menu to which this method should add the item
0223: * corresponding to the action-name.
0224: * @param actionName
0225: * name of the action to add. The real action can be
0226: * retrieved from the kit by calling
0227: * <tt>getActionByName()</tt>.
0228: */
0229: protected void addAction(JTextComponent target,
0230: JPopupMenu popupMenu, String actionName) {
0231: Action a = Utilities.getKit(target).getActionByName(
0232: actionName);
0233: if (a != null) {
0234: JMenuItem item = null;
0235: if (a instanceof BaseAction) {
0236: item = ((BaseAction) a).getPopupMenuItem(target);
0237: }
0238: if (item == null) {
0239: String itemText = getItemText(target, actionName, a);
0240: if (itemText != null) {
0241: item = new JMenuItem(itemText);
0242: item.addActionListener(a);
0243: // Try to get the accelerator
0244: Keymap km = target.getKeymap();
0245: if (km != null) {
0246: KeyStroke[] keys = km
0247: .getKeyStrokesForAction(a);
0248: if (keys != null && keys.length > 0) {
0249: item.setAccelerator(keys[0]);
0250: }
0251: }
0252: item.setEnabled(a.isEnabled());
0253: Object helpID = a.getValue("helpID");
0254: if (helpID != null
0255: && (helpID instanceof String))
0256: item.putClientProperty("HelpID", helpID);
0257: }
0258: }
0259:
0260: if (item != null) {
0261: popupMenu.add(item);
0262: }
0263:
0264: } else { // action-name is null, add the separator
0265: popupMenu.addSeparator();
0266: }
0267: }
0268:
0269: protected String getItemText(JTextComponent target,
0270: String actionName, Action a) {
0271: String itemText;
0272: if (a instanceof BaseAction) {
0273: itemText = ((BaseAction) a).getPopupMenuText(target);
0274: } else {
0275: itemText = actionName;
0276: }
0277: return itemText;
0278: }
0279:
0280: }
0281:
0282: /**
0283: * Show the popup menu.
0284: */
0285: public static class ShowPopupMenuAction extends BaseAction {
0286:
0287: static final long serialVersionUID = 4257043398248915291L;
0288:
0289: public ShowPopupMenuAction() {
0290: super (showPopupMenuAction, NO_RECORDING);
0291: }
0292:
0293: public void actionPerformed(ActionEvent evt,
0294: JTextComponent target) {
0295: if (target != null) {
0296: try {
0297: int dotPos = target.getCaret().getDot();
0298: Rectangle r = target.getUI().modelToView(target,
0299: dotPos);
0300: if (r != null) {
0301: ExtUtilities.getExtEditorUI(target)
0302: .showPopupMenu(r.x, r.y + r.height);
0303: }
0304: } catch (BadLocationException e) {
0305: target.getToolkit().beep();
0306: }
0307: }
0308: }
0309:
0310: }
0311:
0312: public static class BuildToolTipAction extends BaseAction {
0313:
0314: static final long serialVersionUID = -2701131863705941250L;
0315:
0316: public BuildToolTipAction() {
0317: super (buildToolTipAction, NO_RECORDING);
0318: }
0319:
0320: protected String buildText(JTextComponent target) {
0321: ToolTipSupport tts = ExtUtilities.getExtEditorUI(target)
0322: .getToolTipSupport();
0323: return (tts != null) ? target.getToolTipText(tts
0324: .getLastMouseEvent()) : target.getToolTipText();
0325: }
0326:
0327: public void actionPerformed(ActionEvent evt,
0328: JTextComponent target) {
0329: if (target != null) {
0330: ToolTipSupport tts = ExtUtilities
0331: .getExtEditorUI(target).getToolTipSupport();
0332: if (tts != null) {
0333: tts.setToolTipText(buildText(target));
0334: }
0335: }
0336: }
0337:
0338: }
0339:
0340: public static class FindAction extends BaseAction {
0341:
0342: static final long serialVersionUID = 719554648887497427L;
0343:
0344: public FindAction() {
0345: super (findAction, ABBREV_RESET | MAGIC_POSITION_RESET
0346: | UNDO_MERGE_RESET | NO_RECORDING);
0347: }
0348:
0349: public FindDialogSupport getSupport() {
0350: if (findDialogSupport == null) {
0351: findDialogSupport = new FindDialogSupport();
0352: }
0353: return findDialogSupport;
0354: }
0355:
0356: public void actionPerformed(ActionEvent evt,
0357: JTextComponent target) {
0358: if (target != null) {
0359: getSupport().showFindDialog();
0360: }
0361: }
0362:
0363: }
0364:
0365: public static class ReplaceAction extends BaseAction {
0366:
0367: static final long serialVersionUID = 1828017436079834384L;
0368:
0369: public ReplaceAction() {
0370: super (replaceAction, ABBREV_RESET | MAGIC_POSITION_RESET
0371: | UNDO_MERGE_RESET | NO_RECORDING);
0372: }
0373:
0374: public FindDialogSupport getSupport() {
0375: if (findDialogSupport == null) {
0376: findDialogSupport = new FindDialogSupport();
0377: }
0378: return findDialogSupport;
0379: }
0380:
0381: public void actionPerformed(ActionEvent evt,
0382: JTextComponent target) {
0383: if (target != null) {
0384: getSupport().showReplaceDialog();
0385: }
0386: }
0387:
0388: }
0389:
0390: public static class GotoAction extends BaseAction {
0391:
0392: static final long serialVersionUID = 8425585413146373256L;
0393:
0394: public GotoAction() {
0395: super (gotoAction, ABBREV_RESET | MAGIC_POSITION_RESET
0396: | UNDO_MERGE_RESET);
0397: }
0398:
0399: /**
0400: * This method is called by the dialog support to translate the line
0401: * offset to the document position. This can be changed for example for
0402: * the diff operations.
0403: *
0404: * @param doc
0405: * document to operate over
0406: * @param lineOffset
0407: * the line offset to convert to position
0408: * @return document offset that corresponds to the row-start of the line
0409: * with the line-number equal to (lineOffset + 1).
0410: */
0411: protected int getOffsetFromLine(BaseDocument doc, int lineOffset) {
0412: return Utilities.getRowStartFromLineOffset(doc, lineOffset);
0413: }
0414:
0415: public void actionPerformed(ActionEvent evt,
0416: JTextComponent target) {
0417: if (target != null) {
0418: new GotoDialogSupport().showGotoDialog();
0419: }
0420: }
0421:
0422: }
0423:
0424: /**
0425: * Action to go to the declaration of the variable under the caret.
0426: */
0427: public static class GotoDeclarationAction extends BaseAction {
0428:
0429: static final long serialVersionUID = -6440495023918097760L;
0430:
0431: public GotoDeclarationAction() {
0432: super (gotoDeclarationAction, ABBREV_RESET
0433: | MAGIC_POSITION_RESET | UNDO_MERGE_RESET
0434: | SAVE_POSITION);
0435: }
0436:
0437: public boolean gotoDeclaration(JTextComponent target) {
0438: try {
0439: Caret caret = target.getCaret();
0440: int dotPos = caret.getDot();
0441: BaseDocument doc = (BaseDocument) target.getDocument();
0442: int[] idBlk = Utilities.getIdentifierBlock(doc, dotPos);
0443: ExtSyntaxSupport extSup = (ExtSyntaxSupport) doc
0444: .getSyntaxSupport();
0445: if (idBlk != null) {
0446: int decPos = extSup.findDeclarationPosition(doc
0447: .getText(idBlk), idBlk[1]);
0448: if (decPos >= 0) {
0449: caret.setDot(decPos);
0450: return true;
0451: }
0452: }
0453: } catch (BadLocationException e) {
0454: }
0455: return false;
0456: }
0457:
0458: public void actionPerformed(ActionEvent evt,
0459: JTextComponent target) {
0460: if (target != null) {
0461: gotoDeclaration(target); // try to go to the declaration
0462: // position
0463: }
0464: }
0465: }
0466:
0467: public static class ToggleCaseIdentifierBeginAction extends
0468: BaseAction {
0469:
0470: static final long serialVersionUID = 584392193824931979L;
0471:
0472: ToggleCaseIdentifierBeginAction() {
0473: super (toggleCaseIdentifierBeginAction, ABBREV_RESET
0474: | MAGIC_POSITION_RESET | UNDO_MERGE_RESET
0475: | WORD_MATCH_RESET);
0476: }
0477:
0478: public void actionPerformed(ActionEvent evt,
0479: JTextComponent target) {
0480: if (target != null) {
0481: if (!target.isEditable() || !target.isEnabled()) {
0482: target.getToolkit().beep();
0483: return;
0484: }
0485:
0486: try {
0487: Caret caret = target.getCaret();
0488: BaseDocument doc = (BaseDocument) target
0489: .getDocument();
0490: int[] idBlk = Utilities.getIdentifierBlock(doc,
0491: caret.getDot());
0492: if (idBlk != null) {
0493: Utilities.changeCase(doc, idBlk[0], 1,
0494: Utilities.CASE_SWITCH);
0495: }
0496: } catch (BadLocationException e) {
0497: target.getToolkit().beep();
0498: }
0499: }
0500: }
0501: }
0502:
0503: public static class MatchBraceAction extends BaseAction {
0504:
0505: boolean select;
0506:
0507: static final long serialVersionUID = -184887499045886231L;
0508:
0509: public MatchBraceAction(String name, boolean select) {
0510: super (name, ABBREV_RESET | MAGIC_POSITION_RESET
0511: | UNDO_MERGE_RESET);
0512: this .select = select;
0513: }
0514:
0515: public void actionPerformed(ActionEvent evt,
0516: JTextComponent target) {
0517: if (target != null) {
0518: try {
0519: Caret caret = target.getCaret();
0520: BaseDocument doc = Utilities.getDocument(target);
0521: int dotPos = caret.getDot();
0522: ExtSyntaxSupport sup = (ExtSyntaxSupport) doc
0523: .getSyntaxSupport();
0524: if (dotPos > 0) {
0525: int[] matchBlk = sup.findMatchingBlock(
0526: dotPos - 1, false);
0527: if (matchBlk != null) {
0528: if (select) {
0529: caret.moveDot(matchBlk[1]);
0530: } else {
0531: caret.setDot(matchBlk[1]);
0532: }
0533: }
0534: }
0535: } catch (BadLocationException e) {
0536: target.getToolkit().beep();
0537: }
0538: }
0539: }
0540: }
0541:
0542: public static class CodeSelectAction extends BaseAction {
0543:
0544: static final long serialVersionUID = 4033474080778585860L;
0545:
0546: public CodeSelectAction() {
0547: super (codeSelectAction);
0548: }
0549:
0550: public void actionPerformed(ActionEvent evt,
0551: JTextComponent target) {
0552: /*
0553: * if (target != null) { BaseDocument doc =
0554: * (BaseDocument)target.getDocument(); SyntaxSupport sup =
0555: * doc.getSyntaxSupport(); Caret caret = target.getCaret(); try {
0556: * int bracketPos = sup.findUnmatchedBracket(caret.getDot(),
0557: * sup.getRightBrackets()); if (bracketPos >= 0) {
0558: * caret.setDot(bracketPos); while (true) { int bolPos =
0559: * Utilities.getRowStart(doc, bracketPos); boolean isWSC =
0560: * sup.isCommentOrWhitespace(bolPos, bracketPos); if (isWSC) { //
0561: * get previous line end
0562: * } } } } catch (BadLocationException e) {
0563: * target.getToolkit().beep(); } }
0564: */
0565: }
0566: }
0567:
0568: /**
0569: * Prefix maker adds the prefix before the identifier under cursor. The
0570: * prefix is not added if it's already present. The prefix to be added is
0571: * specified in the constructor of the action together with the prefix
0572: * group. If there's already any prefix from the prefix group at the
0573: * begining of the identifier, that prefix is replaced by the actual prefix.
0574: */
0575: public static class PrefixMakerAction extends BaseAction {
0576:
0577: static final long serialVersionUID = -2305157963664484920L;
0578:
0579: private String prefix;
0580:
0581: private String[] prefixGroup;
0582:
0583: public PrefixMakerAction(String name, String prefix,
0584: String[] prefixGroup) {
0585: super (name);
0586: this .prefix = prefix;
0587: this .prefixGroup = prefixGroup;
0588: }
0589:
0590: public void actionPerformed(ActionEvent evt,
0591: JTextComponent target) {
0592: if (target != null) {
0593: if (!target.isEditable() || !target.isEnabled()) {
0594: target.getToolkit().beep();
0595: return;
0596: }
0597:
0598: BaseDocument doc = (BaseDocument) target.getDocument();
0599: int dotPos = target.getCaret().getDot();
0600: try {
0601: // look for identifier around caret
0602: int[] block = org.netbeans.editor.Utilities
0603: .getIdentifierBlock(doc, dotPos);
0604:
0605: // If there is no identifier around, warn user
0606: if (block == null) {
0607: target.getToolkit().beep();
0608: return;
0609: }
0610:
0611: // Get the identifier to operate on
0612: String identifier = doc.getText(block[0], block[1]
0613: - block[0]);
0614:
0615: // Handle the case we already have the work done - e.g. if
0616: // we got called over 'getValue'
0617: if (identifier.startsWith(prefix)
0618: && Character.isUpperCase(identifier
0619: .charAt(prefix.length())))
0620: return;
0621:
0622: // Handle the case we have other type of known xEr: eg
0623: // isRunning -> getRunning
0624: for (int i = 0; i < prefixGroup.length; i++) {
0625: String actPref = prefixGroup[i];
0626: if (identifier.startsWith(actPref)
0627: && identifier.length() > actPref
0628: .length()
0629: && Character.isUpperCase(identifier
0630: .charAt(actPref.length()))) {
0631: doc.remove(block[0], actPref.length());
0632: doc.insertString(block[0], prefix, null);
0633: return;
0634: }
0635: }
0636:
0637: // Upcase the first letter
0638: Utilities.changeCase(doc, block[0], 1,
0639: Utilities.CASE_UPPER);
0640: // Prepend the prefix before it
0641: doc.insertString(block[0], prefix, null);
0642: } catch (BadLocationException e) {
0643: target.getToolkit().beep();
0644: }
0645: }
0646: }
0647: }
0648:
0649: public static class CommentAction extends BaseAction {
0650:
0651: static final long serialVersionUID = -1422954906554289179L;
0652:
0653: private String lineCommentString;
0654:
0655: public CommentAction(String lineCommentString) {
0656: super (commentAction);
0657: this .lineCommentString = lineCommentString;
0658: }
0659:
0660: public void actionPerformed(ActionEvent evt,
0661: JTextComponent target) {
0662: if (target != null) {
0663: if (!target.isEditable() || !target.isEnabled()) {
0664: target.getToolkit().beep();
0665: return;
0666: }
0667: Caret caret = target.getCaret();
0668: BaseDocument doc = (BaseDocument) target.getDocument();
0669: try {
0670: if (caret.isSelectionVisible()) {
0671: int startPos = Utilities.getRowStart(doc,
0672: target.getSelectionStart());
0673: int endPos = target.getSelectionEnd();
0674: doc.atomicLock();
0675: try {
0676:
0677: if (endPos > 0
0678: && Utilities.getRowStart(doc,
0679: endPos) == endPos) {
0680: endPos--;
0681: }
0682:
0683: int pos = startPos;
0684: for (int lineCnt = Utilities.getRowCount(
0685: doc, startPos, endPos); lineCnt > 0; lineCnt--) {
0686: doc.insertString(pos,
0687: lineCommentString, null); // NOI18N
0688: pos = Utilities.getRowStart(doc, pos,
0689: +1);
0690: }
0691:
0692: } finally {
0693: doc.atomicUnlock();
0694: }
0695: } else { // selection not visible
0696: doc.insertString(Utilities.getRowStart(doc,
0697: target.getSelectionStart()),
0698: lineCommentString, null); // NOI18N
0699: }
0700: } catch (BadLocationException e) {
0701: target.getToolkit().beep();
0702: }
0703: }
0704: }
0705:
0706: }
0707:
0708: public static class UncommentAction extends BaseAction {
0709:
0710: static final long serialVersionUID = -7005758666529862034L;
0711:
0712: private String lineCommentString;
0713:
0714: public UncommentAction(String lineCommentString) {
0715: super (uncommentAction);
0716: this .lineCommentString = lineCommentString;
0717: }
0718:
0719: public void actionPerformed(ActionEvent evt,
0720: JTextComponent target) {
0721: if (target != null) {
0722: if (!target.isEditable() || !target.isEnabled()) {
0723: target.getToolkit().beep();
0724: return;
0725: }
0726: Caret caret = target.getCaret();
0727: BaseDocument doc = (BaseDocument) target.getDocument();
0728: try {
0729: if (caret.isSelectionVisible()) {
0730: int startPos = Utilities.getRowStart(doc,
0731: target.getSelectionStart());
0732: int endPos = target.getSelectionEnd();
0733: doc.atomicLock();
0734: try {
0735:
0736: if (endPos > 0
0737: && Utilities.getRowStart(doc,
0738: endPos) == endPos) {
0739: endPos--;
0740: }
0741:
0742: int pos = startPos;
0743: for (int lineCnt = Utilities.getRowCount(
0744: doc, startPos, endPos); lineCnt > 0; lineCnt--) {
0745: if (Utilities.getRowEnd(doc, pos) - pos >= 2
0746: && doc.getText(pos, 2).equals(
0747: lineCommentString)) {
0748: doc.remove(pos, 2);
0749: }
0750: pos = Utilities.getRowStart(doc, pos,
0751: +1);
0752: }
0753:
0754: } finally {
0755: doc.atomicUnlock();
0756: }
0757: } else { // selection not visible
0758: int pos = Utilities.getRowStart(doc, caret
0759: .getDot());
0760: if (Utilities.getRowEnd(doc, pos) - pos >= 2
0761: && doc.getText(pos, 2).equals(
0762: lineCommentString) // NOI18N
0763: ) {
0764: doc.remove(pos, 2);
0765: }
0766: }
0767: } catch (BadLocationException e) {
0768: target.getToolkit().beep();
0769: }
0770: }
0771: }
0772:
0773: }
0774:
0775: /**
0776: * Executed when the Escape key is pressed. By default it hides the popup
0777: * menu if visible.
0778: */
0779: public static class EscapeAction extends BaseAction {
0780:
0781: public EscapeAction() {
0782: super (escapeAction);
0783: }
0784:
0785: public void actionPerformed(ActionEvent evt,
0786: JTextComponent target) {
0787: if (target != null) {
0788: ExtUtilities.getExtEditorUI(target).hidePopupMenu();
0789: Completion cpl = ExtUtilities.getExtEditorUI(target)
0790: .getCompletion();
0791: if (cpl != null) {
0792: cpl.setPaneVisible(false);
0793: }
0794: }
0795: }
0796: }
0797:
0798: // Completion customized actions
0799: public static class ExtDefaultKeyTypedAction extends
0800: DefaultKeyTypedAction {
0801:
0802: static final long serialVersionUID = 5273032708909044812L;
0803:
0804: public void actionPerformed(ActionEvent evt,
0805: JTextComponent target) {
0806: String cmd = evt.getActionCommand();
0807: int mod = evt.getModifiers();
0808:
0809: // Dirty fix for Completion shortcut on Unix !!!
0810: if (cmd != null && cmd.equals(" ")
0811: && (mod == ActionEvent.CTRL_MASK)) { // NOI18N
0812: // Ctrl + SPACE
0813: } else {
0814: Caret caret = target.getCaret();
0815: if (caret instanceof ExtCaret) {
0816: ((ExtCaret) caret).requestMatchBraceUpdateSync(); // synced
0817: // bracket
0818: // update
0819: }
0820: super .actionPerformed(evt, target);
0821: }
0822:
0823: if ((target != null) && (evt != null)) {
0824: if ((cmd != null)
0825: && (cmd.length() == 1)
0826: && ((mod & ActionEvent.ALT_MASK) == 0 && (mod & ActionEvent.CTRL_MASK) == 0)) {
0827: // Check whether char that should reindent the line was
0828: // inserted
0829: checkIndentHotChars(target, cmd);
0830:
0831: // Check the completion
0832: checkCompletion(target, cmd);
0833: }
0834: }
0835: }
0836:
0837: /** Check the characters that should cause reindenting the line. */
0838: protected void checkIndentHotChars(JTextComponent target,
0839: String typedText) {
0840: BaseDocument doc = Utilities.getDocument(target);
0841: if (doc != null) {
0842: Caret caret = target.getCaret();
0843: Formatter f = doc.getFormatter();
0844: if (f instanceof ExtFormatter) {
0845: ExtFormatter ef = (ExtFormatter) f;
0846: int[] fmtBlk = ef.getReformatBlock(target,
0847: typedText);
0848:
0849: if (fmtBlk != null) {
0850: try {
0851: fmtBlk[0] = Utilities.getRowStart(doc,
0852: fmtBlk[0]);
0853: fmtBlk[1] = Utilities.getRowEnd(doc,
0854: fmtBlk[1]);
0855:
0856: // this was the of #18922, that causes the bug
0857: // #20198
0858: // ef.reformat(doc, fmtBlk[0], fmtBlk[1]);
0859:
0860: // bugfix of the bug #20198. Bug #18922 is fixed too
0861: // as well as #6968
0862: ef
0863: .reformat(doc, fmtBlk[0],
0864: fmtBlk[1], true);
0865: } catch (BadLocationException e) {
0866: } catch (IOException e) {
0867: }
0868: }
0869: }
0870: }
0871: }
0872:
0873: /** Check and possibly popup, hide or refresh the completion */
0874: protected void checkCompletion(JTextComponent target,
0875: String typedText) {
0876: Completion completion = ExtUtilities.getCompletion(target);
0877:
0878: BaseDocument doc = (BaseDocument) target.getDocument();
0879: ExtSyntaxSupport extSup = (ExtSyntaxSupport) doc
0880: .getSyntaxSupport();
0881:
0882: if (completion != null && typedText.length() > 0) {
0883: if (!completion.isPaneVisible()) {
0884: if (completion.isAutoPopupEnabled()) {
0885: int result = extSup.checkCompletion(target,
0886: typedText, false);
0887: if (result == ExtSyntaxSupport.COMPLETION_POPUP) {
0888: completion.popup(true);
0889: } else if (result == ExtSyntaxSupport.COMPLETION_CANCEL) {
0890: completion.cancelRequest();
0891: }
0892: }
0893: } else {
0894: int result = extSup.checkCompletion(target,
0895: typedText, true);
0896: switch (result) {
0897: case ExtSyntaxSupport.COMPLETION_HIDE:
0898: completion.setPaneVisible(false);
0899: break;
0900: case ExtSyntaxSupport.COMPLETION_REFRESH:
0901: completion.refresh(false);
0902: break;
0903: case ExtSyntaxSupport.COMPLETION_POST_REFRESH:
0904: completion.refresh(true);
0905: break;
0906: }
0907: }
0908: }
0909: }
0910: }
0911:
0912: public static class ExtInsertBreakAction extends InsertBreakAction {
0913:
0914: static final long serialVersionUID = 4004043376345356060L;
0915:
0916: public ExtInsertBreakAction() {
0917: super ();
0918: }
0919:
0920: public void actionPerformed(ActionEvent evt,
0921: JTextComponent target) {
0922: if (target != null) {
0923: Completion completion = ExtUtilities
0924: .getCompletion(target);
0925: if (completion != null && completion.isPaneVisible()) {
0926: if (completion.substituteText(false)) {
0927: completion.setPaneVisible(false);
0928: } else {
0929: completion.refresh(false);
0930: }
0931: } else {
0932: super .actionPerformed(evt, target);
0933: }
0934: }
0935: }
0936:
0937: }
0938:
0939: public static class ExtInsertTabAction extends InsertTabAction {
0940:
0941: static final long serialVersionUID = 2711045528538714986L;
0942:
0943: public ExtInsertTabAction() {
0944: super ();
0945: }
0946:
0947: public void actionPerformed(ActionEvent evt,
0948: JTextComponent target) {
0949: if (target != null) {
0950: Completion completion = ExtUtilities
0951: .getCompletion(target);
0952: if (completion != null && completion.isPaneVisible()) {
0953: completion.refresh(false);
0954: completion.substituteCommonText();
0955: } else {
0956: super .actionPerformed(evt, target);
0957: }
0958: }
0959: }
0960:
0961: }
0962:
0963: public static class ExtUpAction extends UpAction {
0964:
0965: static final long serialVersionUID = 9039435547323841544L;
0966:
0967: ExtUpAction(String nm, boolean select) {
0968: super (nm, select);
0969: }
0970:
0971: public void actionPerformed(ActionEvent evt,
0972: JTextComponent target) {
0973: if (target != null) {
0974: Completion completion = ExtUtilities
0975: .getCompletion(target);
0976: if (completion != null && completion.isPaneVisible()) {
0977: completion.getView().up();
0978: } else {
0979: super .actionPerformed(evt, target);
0980: }
0981: }
0982: }
0983: }
0984:
0985: public static class ExtDownAction extends DownAction {
0986:
0987: static final long serialVersionUID = 5728488498924841815L;
0988:
0989: ExtDownAction(String nm, boolean select) {
0990: super (nm, select);
0991: }
0992:
0993: public void actionPerformed(ActionEvent evt,
0994: JTextComponent target) {
0995: if (target != null) {
0996: Completion completion = ExtUtilities
0997: .getCompletion(target);
0998: if (completion != null && completion.isPaneVisible()) {
0999: completion.getView().down();
1000: } else {
1001: super .actionPerformed(evt, target);
1002: }
1003: }
1004: }
1005: }
1006:
1007: public static class ExtPageUpAction extends PageUpAction {
1008:
1009: static final long serialVersionUID = 4336328849128594564L;
1010:
1011: ExtPageUpAction(String nm, boolean select) {
1012: super (nm, select);
1013: }
1014:
1015: public void actionPerformed(ActionEvent evt,
1016: JTextComponent target) {
1017: if (target != null) {
1018: Completion completion = ExtUtilities
1019: .getCompletion(target);
1020: if (completion != null && completion.isPaneVisible()) {
1021: completion.getView().pageUp();
1022: } else {
1023: super .actionPerformed(evt, target);
1024: }
1025: }
1026: }
1027: }
1028:
1029: public static class ExtPageDownAction extends PageDownAction {
1030:
1031: static final long serialVersionUID = -2373608546477823838L;
1032:
1033: ExtPageDownAction(String nm, boolean select) {
1034: super (nm, select);
1035: }
1036:
1037: public void actionPerformed(ActionEvent evt,
1038: JTextComponent target) {
1039: if (target != null) {
1040: Completion completion = ExtUtilities
1041: .getCompletion(target);
1042: if (completion != null && completion.isPaneVisible()) {
1043: completion.getView().pageDown();
1044: } else {
1045: super .actionPerformed(evt, target);
1046: }
1047: }
1048: }
1049: }
1050:
1051: public static class ExtBeginLineAction extends BeginLineAction {
1052:
1053: static final long serialVersionUID = 1226924439847693361L;
1054:
1055: public ExtBeginLineAction(String nm, boolean select) {
1056: super (nm, select);
1057: }
1058:
1059: public void actionPerformed(ActionEvent evt,
1060: JTextComponent target) {
1061: if (target != null) {
1062: Completion completion = ExtUtilities
1063: .getCompletion(target);
1064: if (completion != null && completion.isPaneVisible()) {
1065: if (select) {
1066: completion.setPaneVisible(false);
1067: } else {
1068: completion.getView().begin();
1069: return;
1070: }
1071: }
1072: super .actionPerformed(evt, target);
1073: }
1074: }
1075: }
1076:
1077: public static class ExtEndLineAction extends EndLineAction {
1078:
1079: static final long serialVersionUID = -3703912765497771472L;
1080:
1081: public ExtEndLineAction(String nm, boolean select) {
1082: super (nm, select);
1083: }
1084:
1085: public void actionPerformed(ActionEvent evt,
1086: JTextComponent target) {
1087: if (target != null) {
1088: Completion completion = ExtUtilities
1089: .getCompletion(target);
1090: if (completion != null && completion.isPaneVisible()) {
1091: if (select) {
1092: completion.setPaneVisible(false);
1093: } else {
1094: completion.getView().end();
1095: return;
1096: }
1097: }
1098: super .actionPerformed(evt, target);
1099: }
1100: }
1101: }
1102:
1103: public static class CompletionShowAction extends BaseAction {
1104:
1105: static final long serialVersionUID = 1050644925893851146L;
1106:
1107: public CompletionShowAction() {
1108: super (completionShowAction);
1109: }
1110:
1111: public void actionPerformed(ActionEvent evt,
1112: JTextComponent target) {
1113: if (target != null) {
1114: Completion completion = ExtUtilities
1115: .getCompletion(target);
1116: if (completion != null) {
1117: completion.setPaneVisible(true);
1118: }
1119: }
1120: }
1121:
1122: }
1123:
1124: public static class CompletionHideAction extends BaseAction {
1125:
1126: static final long serialVersionUID = -9162014350666711948L;
1127:
1128: public CompletionHideAction() {
1129: super (completionHideAction);
1130: }
1131:
1132: public void actionPerformed(ActionEvent evt,
1133: JTextComponent target) {
1134: if (target != null) {
1135: Completion completion = ExtUtilities
1136: .getCompletion(target);
1137: if (completion != null) {
1138: completion.setPaneVisible(false);
1139: }
1140: }
1141: }
1142:
1143: }
1144:
1145: public static class ShiftInsertBreakAction extends BaseAction {
1146:
1147: public ShiftInsertBreakAction() {
1148: super (shiftInsertBreakAction, ABBREV_RESET
1149: | MAGIC_POSITION_RESET | UNDO_MERGE_RESET);
1150: }
1151:
1152: public void actionPerformed(ActionEvent evt,
1153: JTextComponent target) {
1154: if (target != null) {
1155: Completion completion = ExtUtilities
1156: .getCompletion(target);
1157: if (completion != null && completion.isPaneVisible()) {
1158: if (completion.substituteText(true)) {
1159: // completion.setPaneVisible(false);
1160: } else {
1161: completion.refresh(false);
1162: }
1163: }
1164: }
1165: }
1166:
1167: }
1168:
1169: }
|