001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.editor.java;
043:
044: import java.awt.event.ActionEvent;
045: import java.util.ArrayList;
046: import java.util.List;
047: import javax.swing.*;
048: import javax.swing.text.*;
049: import javax.swing.text.BadLocationException;
050: import org.netbeans.editor.*;
051: import org.netbeans.editor.Utilities;
052: import org.netbeans.editor.ext.*;
053: import org.netbeans.editor.ext.java.*;
054: import org.netbeans.api.editor.fold.FoldHierarchy;
055: import org.netbeans.api.editor.fold.FoldUtilities;
056: import org.netbeans.api.editor.mimelookup.MimeLookup;
057: import org.netbeans.api.editor.mimelookup.MimePath;
058: import org.netbeans.api.java.lexer.JavaTokenId;
059: import org.netbeans.api.java.queries.SourceLevelQuery;
060: import org.netbeans.api.lexer.TokenHierarchy;
061: import org.netbeans.api.lexer.TokenSequence;
062: import org.netbeans.editor.ext.ExtKit.CommentAction;
063: import org.netbeans.editor.ext.ExtKit.PrefixMakerAction;
064: import org.netbeans.editor.ext.ExtKit.UncommentAction;
065: import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
066: import org.netbeans.modules.editor.MainMenuAction;
067: import org.netbeans.modules.editor.NbEditorKit;
068: import org.netbeans.modules.editor.NbEditorUtilities;
069: import org.netbeans.modules.java.editor.codegen.InsertSemicolonAction;
070: import org.netbeans.modules.java.editor.codegen.GenerateCodeAction;
071: import org.netbeans.modules.java.editor.imports.FastImportAction;
072: import org.netbeans.modules.java.editor.imports.JavaFixAllImports;
073: import org.netbeans.modules.java.editor.overridden.GoToSuperTypeAction;
074: import org.netbeans.modules.java.editor.rename.InstantRenameAction;
075: import org.openide.filesystems.FileObject;
076: import org.openide.loaders.DataObject;
077: import org.openide.awt.Mnemonics;
078: import org.openide.util.*;
079:
080: /**
081: * Java editor kit with appropriate document
082: *
083: * @author Miloslav Metelka
084: * @version 1.00
085: */
086:
087: public class JavaKit extends NbEditorKit {
088:
089: public static final String JAVA_MIME_TYPE = "text/x-java"; // NOI18N
090:
091: private static final String[] getSetIsPrefixes = new String[] {
092: "get", "set", "is" // NOI18N
093: };
094:
095: /** Switch first letter of word to capital and insert 'get'
096: * at word begining.
097: */
098: public static final String makeGetterAction = "make-getter"; // NOI18N
099:
100: /** Switch first letter of word to capital and insert 'set'
101: * at word begining.
102: */
103: public static final String makeSetterAction = "make-setter"; // NOI18N
104:
105: /** Switch first letter of word to capital and insert 'is'
106: * at word begining.
107: */
108: public static final String makeIsAction = "make-is"; // NOI18N
109:
110: /** Add the watch depending on the context under the caret */
111: public static final String addWatchAction = "add-watch"; // NOI18N
112:
113: /** Toggle the breakpoint of the current line */
114: public static final String toggleBreakpointAction = "toggle-breakpoint"; // NOI18N
115:
116: /** Debug source and line number */
117: public static final String abbrevDebugLineAction = "abbrev-debug-line"; // NOI18N
118:
119: /** Menu item for adding all necessary imports in a file */
120: public static final String fixImportsAction = "fix-imports"; // NOI18N
121:
122: /** Open dialog for choosing the import statement to be added */
123: public static final String fastImportAction = "fast-import"; // NOI18N
124:
125: /** Opens Go To Class dialog */
126: //public static final String gotoClassAction = "goto-class"; //NOI18N
127: public static final String tryCatchAction = "try-catch"; // NOI18N
128:
129: public static final String javaDocShowAction = "javadoc-show-action"; // NOI18N
130:
131: public static final String expandAllJavadocFolds = "expand-all-javadoc-folds"; //NOI18N
132:
133: public static final String collapseAllJavadocFolds = "collapse-all-javadoc-folds"; //NOI18N
134:
135: public static final String expandAllCodeBlockFolds = "expand-all-code-block-folds"; //NOI18N
136:
137: public static final String collapseAllCodeBlockFolds = "collapse-all-code-block-folds"; //NOI18N
138:
139: public static final String selectNextElementAction = "select-element-next"; //NOI18N
140:
141: public static final String selectPreviousElementAction = "select-element-previous"; //NOI18N
142:
143: /* package */static final String previousCamelCasePosition = "previous-camel-case-position"; //NOI18N
144:
145: /* package */static final String nextCamelCasePosition = "next-camel-case-position"; //NOI18N
146:
147: /* package */static final String selectPreviousCamelCasePosition = "select-previous-camel-case-position"; //NOI18N
148:
149: /* package */static final String selectNextCamelCasePosition = "select-next-camel-case-position"; //NOI18N
150:
151: /* package */static final String deletePreviousCamelCasePosition = "delete-previous-camel-case-position"; //NOI18N
152:
153: /* package */static final String deleteNextCamelCasePosition = "delete-next-camel-case-position"; //NOI18N
154:
155: static final long serialVersionUID = -5445829962533684922L;
156:
157: public JavaKit() {
158: org.netbeans.modules.java.editor.JavaEditorModule.init();
159: }
160:
161: public String getContentType() {
162: return JAVA_MIME_TYPE;
163: }
164:
165: /** Create new instance of syntax coloring scanner
166: * @param doc document to operate on. It can be null in the cases the syntax
167: * creation is not related to the particular document
168: */
169: public Syntax createSyntax(Document doc) {
170: return new JavaSyntax(getSourceLevel((BaseDocument) doc));
171: }
172:
173: public Completion createCompletion(ExtEditorUI extEditorUI) {
174: return null;
175: }
176:
177: public CompletionJavaDoc createCompletionJavaDoc(
178: ExtEditorUI extEditorUI) {
179: return null;
180: }
181:
182: @Override
183: public Document createDefaultDocument() {
184: Document doc = new JavaDocument(this .getClass());
185: Object mimeType = doc.getProperty("mimeType"); //NOI18N
186: if (mimeType == null) {
187: doc.putProperty("mimeType", getContentType()); //NOI18N
188: }
189: return doc;
190: }
191:
192: public String getSourceLevel(BaseDocument doc) {
193: DataObject dob = NbEditorUtilities.getDataObject(doc);
194: return dob != null ? SourceLevelQuery.getSourceLevel(dob
195: .getPrimaryFile()) : null;
196: }
197:
198: /** Create the formatter appropriate for this kit */
199: public Formatter createFormatter() {
200: return new JavaFormatter(this .getClass());
201: }
202:
203: protected void initDocument(BaseDocument doc) {
204: // doc.addLayer(new JavaDrawLayerFactory.JavaLayer(),
205: // JavaDrawLayerFactory.JAVA_LAYER_VISIBILITY);
206: doc.putProperty(SyntaxUpdateTokens.class,
207: new SyntaxUpdateTokens() {
208:
209: private List tokenList = new ArrayList();
210:
211: public void syntaxUpdateStart() {
212: tokenList.clear();
213: }
214:
215: public List syntaxUpdateEnd() {
216: return tokenList;
217: }
218:
219: public void syntaxUpdateToken(TokenID id,
220: TokenContextPath contextPath, int offset,
221: int length) {
222: if (JavaTokenContext.LINE_COMMENT == id) {
223: tokenList.add(new TokenInfo(id,
224: contextPath, offset, length));
225: }
226: }
227: });
228:
229: //do not ask why, fire bug in the IZ:
230: CodeTemplateManager.get(doc);
231: }
232:
233: protected Action[] createActions() {
234: Action[] super Actions = super .createActions();
235: Action[] javaActions = new Action[] {
236: new JavaDefaultKeyTypedAction(),
237: new PrefixMakerAction(makeGetterAction, "get",
238: getSetIsPrefixes), // NOI18N
239: new PrefixMakerAction(makeSetterAction, "set",
240: getSetIsPrefixes), // NOI18N
241: new PrefixMakerAction(makeIsAction, "is",
242: getSetIsPrefixes), // NOI18N
243: new AbbrevDebugLineAction(),
244: new ToggleCommentAction("//"), // NOI18N
245: new JavaGenerateGoToPopupAction(),
246: new JavaInsertBreakAction(),
247: new JavaDeleteCharAction(deletePrevCharAction, false),
248: new JavaDeleteCharAction(deleteNextCharAction, true),
249: new ExpandAllJavadocFolds(),
250: new CollapseAllJavadocFolds(),
251: new ExpandAllCodeBlockFolds(),
252: new CollapseAllCodeBlockFolds(),
253: new JavaGenerateFoldPopupAction(),
254: new JavaGoToDeclarationAction(),
255: new JavaGoToSourceAction(),
256: new JavaGotoHelpAction(),
257: new InstantRenameAction(),
258: new JavaFixImports(),
259: new GenerateCodeAction(),
260: new InsertSemicolonAction(true),
261: new InsertSemicolonAction(false),
262: new SelectCodeElementAction(selectNextElementAction,
263: true),
264: new SelectCodeElementAction(
265: selectPreviousElementAction, false),
266:
267: new NextCamelCasePosition(findAction(super Actions,
268: nextWordAction)),
269: new PreviousCamelCasePosition(findAction(super Actions,
270: previousWordAction)),
271: new SelectNextCamelCasePosition(findAction(
272: super Actions, selectionNextWordAction)),
273: new SelectPreviousCamelCasePosition(findAction(
274: super Actions, selectionPreviousWordAction)),
275: new DeleteToNextCamelCasePosition(findAction(
276: super Actions, removeNextWordAction)),
277: new DeleteToPreviousCamelCasePosition(findAction(
278: super Actions, removePreviousWordAction)),
279:
280: new FastImportAction(), new GoToSuperTypeAction(), };
281:
282: return TextAction.augmentList(super Actions, javaActions);
283: }
284:
285: private static Action findAction(Action[] actions, String name) {
286: for (Action a : actions) {
287: Object nameObj = a.getValue(Action.NAME);
288: if (nameObj instanceof String && name.equals(nameObj)) {
289: return a;
290: }
291: }
292: return null;
293: }
294:
295: public static class JavaDefaultKeyTypedAction extends
296: ExtDefaultKeyTypedAction {
297:
298: protected void insertString(BaseDocument doc, int dotPos,
299: Caret caret, String str, boolean overwrite)
300: throws BadLocationException {
301: char insertedChar = str.charAt(0);
302: if (insertedChar == '\"' || insertedChar == '\'') {
303: boolean inserted = BracketCompletion.completeQuote(doc,
304: dotPos, caret, insertedChar);
305: if (inserted) {
306: caret.setDot(dotPos + 1);
307: } else {
308: super .insertString(doc, dotPos, caret, str,
309: overwrite);
310:
311: }
312: } else {
313: super .insertString(doc, dotPos, caret, str, overwrite);
314: BracketCompletion.charInserted(doc, dotPos, caret,
315: insertedChar);
316: }
317: }
318:
319: protected void replaceSelection(JTextComponent target,
320: int dotPos, Caret caret, String str, boolean overwrite)
321: throws BadLocationException {
322: char insertedChar = str.charAt(0);
323: Document doc = target.getDocument();
324: if (insertedChar == '\"' || insertedChar == '\'') {
325: if (doc != null) {
326: try {
327: boolean inserted = false;
328: int p0 = Math.min(caret.getDot(), caret
329: .getMark());
330: int p1 = Math.max(caret.getDot(), caret
331: .getMark());
332: if (p0 != p1) {
333: doc.remove(p0, p1 - p0);
334: }
335: int caretPosition = caret.getDot();
336: if (doc instanceof BaseDocument) {
337: inserted = BracketCompletion.completeQuote(
338: (BaseDocument) doc, caretPosition,
339: caret, insertedChar);
340: }
341: if (inserted) {
342: caret.setDot(caretPosition + 1);
343: } else {
344: if (str != null && str.length() > 0) {
345: doc.insertString(p0, str, null);
346: }
347: }
348: } catch (BadLocationException e) {
349: e.printStackTrace();
350: }
351: }
352: } else {
353: super .replaceSelection(target, dotPos, caret, str,
354: overwrite);
355: if (doc instanceof BaseDocument) {
356: BracketCompletion.charInserted((BaseDocument) doc,
357: caret.getDot() - 1, caret, insertedChar);
358: }
359: }
360: }
361: }
362:
363: public static class JavaGenerateGoToPopupAction extends
364: NbGenerateGoToPopupAction {
365:
366: public void actionPerformed(ActionEvent evt,
367: JTextComponent target) {
368: }
369:
370: private void addAcceleretors(Action a, JMenuItem item,
371: JTextComponent target) {
372: // Try to get the accelerator
373: Keymap km = target.getKeymap();
374: if (km != null) {
375:
376: KeyStroke[] keys = km.getKeyStrokesForAction(a);
377: if (keys != null && keys.length > 0) {
378: item.setAccelerator(keys[0]);
379: } else if (a != null) {
380: KeyStroke ks = (KeyStroke) a
381: .getValue(Action.ACCELERATOR_KEY);
382: if (ks != null) {
383: item.setAccelerator(ks);
384: }
385: }
386: }
387: }
388:
389: private void addAction(JTextComponent target, JMenu menu,
390: Action a) {
391: if (a != null) {
392: String actionName = (String) a.getValue(Action.NAME);
393: JMenuItem item = null;
394: if (a instanceof BaseAction) {
395: item = ((BaseAction) a).getPopupMenuItem(target);
396: }
397: if (item == null) {
398: // gets trimmed text that doesn' contain "go to"
399: String itemText = (String) a
400: .getValue(ExtKit.TRIMMED_TEXT);
401: if (itemText == null) {
402: itemText = getItemText(target, actionName, a);
403: }
404: if (itemText != null) {
405: item = new JMenuItem(itemText);
406: Mnemonics.setLocalizedText(item, itemText);
407: item.addActionListener(a);
408: addAcceleretors(a, item, target);
409: item.setEnabled(a.isEnabled());
410: Object helpID = a.getValue("helpID"); // NOI18N
411: if (helpID != null
412: && (helpID instanceof String))
413: item.putClientProperty("HelpID", helpID); // NOI18N
414: } else {
415: if (ExtKit.gotoSourceAction.equals(actionName)) {
416: item = new JMenuItem(
417: NbBundle
418: .getBundle(JavaKit.class)
419: .getString(
420: "goto_source_open_source_not_formatted")); //NOI18N
421: addAcceleretors(a, item, target);
422: item.setEnabled(false);
423: }
424: }
425: }
426:
427: if (item != null) {
428: menu.add(item);
429: }
430:
431: }
432: }
433:
434: protected void addAction(JTextComponent target, JMenu menu,
435: String actionName) {
436: BaseKit kit = Utilities.getKit(target);
437: if (kit == null)
438: return;
439: Action a = kit.getActionByName(actionName);
440: if (a != null) {
441: addAction(target, menu, a);
442: } else { // action-name is null, add the separator
443: menu.addSeparator();
444: }
445: }
446:
447: protected String getItemText(JTextComponent target,
448: String actionName, Action a) {
449: String itemText;
450: if (a instanceof BaseAction) {
451: itemText = ((BaseAction) a).getPopupMenuText(target);
452: } else {
453: itemText = actionName;
454: }
455: return itemText;
456: }
457:
458: public JMenuItem getPopupMenuItem(final JTextComponent target) {
459: String menuText = NbBundle.getBundle(JavaKit.class)
460: .getString("generate-goto-popup"); //NOI18N
461: JMenu jm = new JMenu(menuText);
462: addAction(target, jm, ExtKit.gotoSourceAction);
463: addAction(target, jm, ExtKit.gotoDeclarationAction);
464: addAction(target, jm, gotoSuperImplementationAction);
465: addAction(target, jm, ExtKit.gotoAction);
466: return jm;
467: }
468:
469: }
470:
471: public static class AbbrevDebugLineAction extends BaseAction {
472:
473: public AbbrevDebugLineAction() {
474: super (abbrevDebugLineAction);
475: }
476:
477: public void actionPerformed(ActionEvent evt,
478: JTextComponent target) {
479: if (target != null) {
480: if (!target.isEditable() || !target.isEnabled()) {
481: target.getToolkit().beep();
482: return;
483: }
484: BaseDocument doc = (BaseDocument) target.getDocument();
485: StringBuffer sb = new StringBuffer(
486: "System.out.println(\""); // NOI18N
487: String title = (String) doc
488: .getProperty(Document.TitleProperty);
489: if (title != null) {
490: sb.append(title);
491: sb.append(':');
492: }
493: try {
494: sb.append(Utilities.getLineOffset(doc, target
495: .getCaret().getDot()) + 1);
496: } catch (BadLocationException e) {
497: }
498: sb.append(' ');
499:
500: BaseKit kit = Utilities.getKit(target);
501: if (kit == null)
502: return;
503: Action a = kit
504: .getActionByName(BaseKit.insertContentAction);
505: if (a != null) {
506: Utilities.performAction(a,
507: new ActionEvent(target,
508: ActionEvent.ACTION_PERFORMED, sb
509: .toString()), target);
510: }
511: }
512: }
513:
514: }
515:
516: public static class JavaInsertBreakAction extends InsertBreakAction {
517:
518: static final long serialVersionUID = -1506173310438326380L;
519:
520: private boolean isJavadocTouched = false;
521:
522: @Override
523: public void actionPerformed(ActionEvent evt,
524: JTextComponent target) {
525: try {
526: super .actionPerformed(evt, target);
527:
528: // XXX temporary solution until the editor will provide a SPI to plug. See issue #115739
529: // This must run outside the document lock
530: if (isJavadocTouched) {
531: Lookup.Result<TextAction> res = MimeLookup
532: .getLookup(MimePath.parse("text/x-javadoc"))
533: .lookupResult(TextAction.class);
534: ActionEvent newevt = new ActionEvent(target,
535: ActionEvent.ACTION_PERFORMED, "fix-javadoc");
536: for (TextAction action : res.allInstances()) {
537: action.actionPerformed(newevt);
538: }
539: }
540: } finally {
541: isJavadocTouched = false;
542: }
543: }
544:
545: protected Object beforeBreak(JTextComponent target,
546: BaseDocument doc, Caret caret) {
547: int dotPos = caret.getDot();
548: if (BracketCompletion.posWithinString(doc, dotPos)) {
549: try {
550: doc.insertString(dotPos, "\" + \"", null); //NOI18N
551: dotPos += 3;
552: caret.setDot(dotPos);
553: return new Integer(dotPos);
554: } catch (BadLocationException ex) {
555: }
556: } else {
557: try {
558: if (BracketCompletion.isAddRightBrace(doc, dotPos)) {
559: int end = BracketCompletion.getRowOrBlockEnd(
560: doc, dotPos);
561: doc.insertString(end, "}", null); // NOI18N
562: doc.getFormatter().indentNewLine(doc, end);
563: caret.setDot(dotPos);
564: return Boolean.TRUE;
565: }
566: } catch (BadLocationException ex) {
567: }
568: }
569:
570: return javadocBlockCompletion(target, doc, dotPos);
571: }
572:
573: protected void afterBreak(JTextComponent target,
574: BaseDocument doc, Caret caret, Object cookie) {
575: if (cookie != null) {
576: if (cookie instanceof Integer) {
577: // integer
578: int nowDotPos = caret.getDot();
579: caret.setDot(nowDotPos + 1);
580: }
581: }
582: }
583:
584: private Object javadocBlockCompletion(JTextComponent target,
585: BaseDocument doc, final int dotPosition) {
586: try {
587: TokenHierarchy<BaseDocument> tokens = TokenHierarchy
588: .get(doc);
589: TokenSequence ts = tokens.tokenSequence();
590: ts.move(dotPosition);
591: if (!((ts.moveNext() || ts.movePrevious()) && ts
592: .token().id() == JavaTokenId.JAVADOC_COMMENT)) {
593: return null;
594: }
595:
596: int jdoffset = dotPosition - 3;
597: if (jdoffset >= 0) {
598: CharSequence content = org.netbeans.lib.editor.util.swing.DocumentUtilities
599: .getText(doc);
600: if (isOpenJavadoc(content, dotPosition - 1)
601: && !isClosedJavadoc(content, dotPosition)) {
602: // complete open javadoc
603: // note that the formater will add one line of javadoc
604: doc.insertString(dotPosition, "*/", null); // NOI18N
605: doc.getFormatter().indentNewLine(doc,
606: dotPosition);
607: target.setCaretPosition(dotPosition);
608:
609: isJavadocTouched = true;
610: return Boolean.TRUE;
611: }
612: }
613: } catch (BadLocationException ex) {
614: // ignore
615: Exceptions.printStackTrace(ex);
616: }
617: return null;
618: }
619:
620: private static boolean isOpenJavadoc(CharSequence content,
621: int pos) {
622: for (int i = pos; i >= 0; i--) {
623: char c = content.charAt(i);
624: if (c == '*' && i - 2 >= 0
625: && content.charAt(i - 1) == '*'
626: && content.charAt(i - 2) == '/') {
627: // matched /**
628: return true;
629: } else if (c == '\n') {
630: // no javadoc, matched start of line
631: return false;
632: } else if (c == '/' && i - 1 >= 0
633: && content.charAt(i - 1) == '*') {
634: // matched javadoc enclosing tag
635: return false;
636: }
637: }
638:
639: return false;
640: }
641:
642: private static boolean isClosedJavadoc(CharSequence txt, int pos) {
643: int length = txt.length();
644: int quotation = 0;
645: for (int i = pos; i < length; i++) {
646: char c = txt.charAt(i);
647: if (c == '*' && i < length - 1
648: && txt.charAt(i + 1) == '/') {
649: if (quotation == 0 || i < length - 2) {
650: return true;
651: }
652: // guess it is not just part of some text constant
653: boolean isClosed = true;
654: for (int j = i + 2; j < length; j++) {
655: char cc = txt.charAt(j);
656: if (cc == '\n') {
657: break;
658: } else if (cc == '"' && j < length - 1
659: && txt.charAt(j + 1) != '\'') {
660: isClosed = false;
661: break;
662: }
663: }
664:
665: if (isClosed) {
666: return true;
667: }
668: } else if (c == '/' && i < length - 1
669: && txt.charAt(i + 1) == '*') {
670: // start of another comment block
671: return false;
672: } else if (c == '\n') {
673: quotation = 0;
674: } else if (c == '"' && i < length - 1
675: && txt.charAt(i + 1) != '\'') {
676: quotation = ++quotation % 2;
677: }
678: }
679:
680: return false;
681: }
682:
683: }
684:
685: public static class JavaDeleteCharAction extends
686: ExtDeleteCharAction {
687:
688: public JavaDeleteCharAction(String nm, boolean nextChar) {
689: super (nm, nextChar);
690: }
691:
692: protected void charBackspaced(BaseDocument doc, int dotPos,
693: Caret caret, char ch) throws BadLocationException {
694: BracketCompletion.charBackspaced(doc, dotPos, caret, ch);
695: }
696:
697: @Override
698: public void actionPerformed(ActionEvent evt,
699: JTextComponent target) {
700: target.putClientProperty(JavaDeleteCharAction.class, this );
701:
702: try {
703: super .actionPerformed(evt, target);
704: } finally {
705: target.putClientProperty(JavaDeleteCharAction.class,
706: null);
707: }
708: }
709:
710: public boolean getNextChar() {
711: return nextChar;
712: }
713: }
714:
715: public static class ExpandAllJavadocFolds extends BaseAction {
716: public ExpandAllJavadocFolds() {
717: super (expandAllJavadocFolds);
718: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
719: JavaKit.class)
720: .getString("expand-all-javadoc-folds"));
721: putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(
722: JavaKit.class).getString(
723: "popup-expand-all-javadoc-folds"));
724: }
725:
726: public void actionPerformed(ActionEvent evt,
727: JTextComponent target) {
728: FoldHierarchy hierarchy = FoldHierarchy.get(target);
729: // Hierarchy locking done in the utility method
730: FoldUtilities.expand(hierarchy,
731: JavaFoldManager.JAVADOC_FOLD_TYPE);
732: }
733: }
734:
735: public static class CollapseAllJavadocFolds extends BaseAction {
736: public CollapseAllJavadocFolds() {
737: super (collapseAllJavadocFolds);
738: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
739: JavaKit.class).getString(
740: "collapse-all-javadoc-folds"));
741: putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(
742: JavaKit.class).getString(
743: "popup-collapse-all-javadoc-folds"));
744: }
745:
746: public void actionPerformed(ActionEvent evt,
747: JTextComponent target) {
748: FoldHierarchy hierarchy = FoldHierarchy.get(target);
749: // Hierarchy locking done in the utility method
750: FoldUtilities.collapse(hierarchy,
751: JavaFoldManager.JAVADOC_FOLD_TYPE);
752: }
753: }
754:
755: public static class ExpandAllCodeBlockFolds extends BaseAction {
756: public ExpandAllCodeBlockFolds() {
757: super (expandAllCodeBlockFolds);
758: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
759: JavaKit.class).getString(
760: "expand-all-code-block-folds"));
761: putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(
762: JavaKit.class).getString(
763: "popup-expand-all-code-block-folds"));
764: }
765:
766: public void actionPerformed(ActionEvent evt,
767: JTextComponent target) {
768: FoldHierarchy hierarchy = FoldHierarchy.get(target);
769: // Hierarchy locking done in the utility method
770: List types = new ArrayList();
771: types.add(JavaFoldManager.CODE_BLOCK_FOLD_TYPE);
772: types.add(JavaFoldManager.IMPORTS_FOLD_TYPE);
773: FoldUtilities.expand(hierarchy, types);
774: }
775: }
776:
777: public static class CollapseAllCodeBlockFolds extends BaseAction {
778: public CollapseAllCodeBlockFolds() {
779: super (collapseAllCodeBlockFolds);
780: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
781: JavaKit.class).getString(
782: "collapse-all-code-block-folds"));
783: putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(
784: JavaKit.class).getString(
785: "popup-collapse-all-code-block-folds"));
786: }
787:
788: public void actionPerformed(ActionEvent evt,
789: JTextComponent target) {
790: FoldHierarchy hierarchy = FoldHierarchy.get(target);
791: // Hierarchy locking done in the utility method
792: List types = new ArrayList();
793: types.add(JavaFoldManager.CODE_BLOCK_FOLD_TYPE);
794: types.add(JavaFoldManager.IMPORTS_FOLD_TYPE);
795: FoldUtilities.collapse(hierarchy, types);
796: }
797: }
798:
799: public static class JavaGenerateFoldPopupAction extends
800: GenerateFoldPopupAction {
801:
802: protected void addAdditionalItems(JTextComponent target,
803: JMenu menu) {
804: addAction(target, menu, collapseAllJavadocFolds);
805: addAction(target, menu, expandAllJavadocFolds);
806: setAddSeparatorBeforeNextAction(true);
807: addAction(target, menu, collapseAllCodeBlockFolds);
808: addAction(target, menu, expandAllCodeBlockFolds);
809: }
810:
811: }
812:
813: private static class JavaGoToDeclarationAction extends
814: GotoDeclarationAction {
815: public @Override
816: boolean gotoDeclaration(JTextComponent target) {
817: if (!(target.getDocument() instanceof BaseDocument)) // Fixed #113062
818: return false;
819: GoToSupport.goTo((BaseDocument) target.getDocument(),
820: target.getCaretPosition(), false);
821: return true;
822: }
823: }
824:
825: private static class JavaGoToSourceAction extends BaseAction {
826:
827: static final long serialVersionUID = -6440495023918097760L;
828:
829: public JavaGoToSourceAction() {
830: super (gotoSourceAction, ABBREV_RESET | MAGIC_POSITION_RESET
831: | UNDO_MERGE_RESET | SAVE_POSITION);
832: putValue(TRIMMED_TEXT, LocaleSupport
833: .getString("goto-source-trimmed")); //NOI18N
834: }
835:
836: public void actionPerformed(ActionEvent evt,
837: JTextComponent target) {
838: if (target != null
839: && (target.getDocument() instanceof BaseDocument)) {
840: GoToSupport.goTo((BaseDocument) target.getDocument(),
841: target.getCaretPosition(), true);
842: }
843: }
844:
845: public String getPopupMenuText(JTextComponent target) {
846: return NbBundle.getBundle(JavaKit.class).getString(
847: "goto_source_open_source_not_formatted"); //NOI18N
848: }
849:
850: protected Class getShortDescriptionBundleClass() {
851: return BaseKit.class;
852: }
853: }
854:
855: private static class JavaFixImports extends BaseAction {
856:
857: public JavaFixImports() {
858: super (fixImportsAction, ABBREV_RESET | MAGIC_POSITION_RESET
859: | UNDO_MERGE_RESET);
860: putValue(TRIMMED_TEXT, NbBundle.getBundle(JavaKit.class)
861: .getString("fix-imports-trimmed"));
862: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
863: JavaKit.class).getString("desc-fix-imports")); // NOI18N
864: putValue(POPUP_MENU_TEXT, NbBundle.getBundle(JavaKit.class)
865: .getString("popup-fix-imports")); // NOI18N
866: }
867:
868: public void actionPerformed(ActionEvent evt,
869: JTextComponent target) {
870: if (target != null) {
871: Document doc = target.getDocument();
872: Object source = doc
873: .getProperty(Document.StreamDescriptionProperty);
874:
875: if (source instanceof DataObject) {
876: FileObject fo = ((DataObject) source)
877: .getPrimaryFile();
878:
879: JavaFixAllImports.getDefault().fixAllImports(fo);
880: }
881: }
882: }
883:
884: public static final class GlobalAction extends MainMenuAction {
885: private final JMenuItem menuPresenter;
886:
887: public GlobalAction() {
888: super ();
889: this .menuPresenter = new JMenuItem(getMenuItemText());
890: setMenu();
891: }
892:
893: protected String getMenuItemText() {
894: return NbBundle.getBundle(GlobalAction.class)
895: .getString("fix-imports-main-menu-source-item"); //NOI18N
896: }
897:
898: protected String getActionName() {
899: return fixImportsAction;
900: }
901:
902: public JMenuItem getMenuPresenter() {
903: return menuPresenter;
904: }
905: }
906: } // End of JavaFixImports action
907:
908: private static class JavaGotoHelpAction extends BaseAction {
909:
910: public JavaGotoHelpAction() {
911: super (gotoHelpAction, ABBREV_RESET | MAGIC_POSITION_RESET
912: | UNDO_MERGE_RESET | SAVE_POSITION);
913: putValue("helpID", JavaGotoHelpAction.class.getName()); // NOI18N
914: // fix of #25090; [PENDING] there should be more systematic solution for this problem
915: putValue(SHORT_DESCRIPTION, NbBundle.getBundle(
916: JavaKit.class).getString("java-desc-goto-help"));
917: }
918:
919: public void actionPerformed(ActionEvent evt,
920: JTextComponent target) {
921: if (target != null) {
922: GoToSupport.goToJavadoc(target.getDocument(), target
923: .getCaretPosition());
924: }
925: }
926:
927: public String getPopupMenuText(JTextComponent target) {
928: return NbBundle.getBundle(JavaKit.class).getString(
929: "show_javadoc"); // NOI18N
930: }
931:
932: }
933:
934: }
|