0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.ui.javaeditor;
0011:
0012: import java.util.HashMap;
0013: import java.util.Map;
0014: import java.util.Stack;
0015:
0016: import org.eclipse.core.runtime.CoreException;
0017: import org.eclipse.core.runtime.IProgressMonitor;
0018: import org.eclipse.core.runtime.IStatus;
0019: import org.eclipse.core.runtime.ListenerList;
0020: import org.eclipse.core.runtime.Platform;
0021:
0022: import org.eclipse.core.resources.IFile;
0023:
0024: import org.eclipse.swt.SWT;
0025: import org.eclipse.swt.custom.StyledText;
0026: import org.eclipse.swt.custom.VerifyKeyListener;
0027: import org.eclipse.swt.events.SelectionAdapter;
0028: import org.eclipse.swt.events.SelectionEvent;
0029: import org.eclipse.swt.events.VerifyEvent;
0030: import org.eclipse.swt.graphics.Point;
0031: import org.eclipse.swt.layout.GridData;
0032: import org.eclipse.swt.widgets.Composite;
0033: import org.eclipse.swt.widgets.Control;
0034: import org.eclipse.swt.widgets.Link;
0035: import org.eclipse.swt.widgets.Shell;
0036:
0037: import org.eclipse.jface.action.IAction;
0038: import org.eclipse.jface.action.IMenuManager;
0039: import org.eclipse.jface.dialogs.ErrorDialog;
0040: import org.eclipse.jface.dialogs.MessageDialog;
0041: import org.eclipse.jface.preference.IPreferenceStore;
0042: import org.eclipse.jface.util.PropertyChangeEvent;
0043:
0044: import org.eclipse.jface.text.BadLocationException;
0045: import org.eclipse.jface.text.BadPositionCategoryException;
0046: import org.eclipse.jface.text.DefaultLineTracker;
0047: import org.eclipse.jface.text.DocumentCommand;
0048: import org.eclipse.jface.text.DocumentEvent;
0049: import org.eclipse.jface.text.IDocument;
0050: import org.eclipse.jface.text.IDocumentExtension;
0051: import org.eclipse.jface.text.IDocumentListener;
0052: import org.eclipse.jface.text.IPositionUpdater;
0053: import org.eclipse.jface.text.IRegion;
0054: import org.eclipse.jface.text.ITextOperationTarget;
0055: import org.eclipse.jface.text.ITextViewerExtension;
0056: import org.eclipse.jface.text.ITextViewerExtension7;
0057: import org.eclipse.jface.text.ITypedRegion;
0058: import org.eclipse.jface.text.IWidgetTokenKeeper;
0059: import org.eclipse.jface.text.Position;
0060: import org.eclipse.jface.text.TabsToSpacesConverter;
0061: import org.eclipse.jface.text.TextUtilities;
0062: import org.eclipse.jface.text.contentassist.ContentAssistant;
0063: import org.eclipse.jface.text.contentassist.IContentAssistant;
0064: import org.eclipse.jface.text.formatter.FormattingContextProperties;
0065: import org.eclipse.jface.text.formatter.IFormattingContext;
0066: import org.eclipse.jface.text.link.ILinkedModeListener;
0067: import org.eclipse.jface.text.link.LinkedModeModel;
0068: import org.eclipse.jface.text.link.LinkedModeUI;
0069: import org.eclipse.jface.text.link.LinkedPosition;
0070: import org.eclipse.jface.text.link.LinkedPositionGroup;
0071: import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
0072: import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy;
0073: import org.eclipse.jface.text.source.IOverviewRuler;
0074: import org.eclipse.jface.text.source.ISourceViewer;
0075: import org.eclipse.jface.text.source.IVerticalRuler;
0076: import org.eclipse.jface.text.source.SourceViewerConfiguration;
0077:
0078: import org.eclipse.ui.IEditorInput;
0079: import org.eclipse.ui.IEditorPart;
0080: import org.eclipse.ui.IFileEditorInput;
0081: import org.eclipse.ui.IWorkbenchPage;
0082: import org.eclipse.ui.IWorkbenchWindow;
0083: import org.eclipse.ui.PlatformUI;
0084: import org.eclipse.ui.actions.ActionContext;
0085: import org.eclipse.ui.actions.ActionGroup;
0086: import org.eclipse.ui.dialogs.PreferencesUtil;
0087: import org.eclipse.ui.texteditor.ContentAssistAction;
0088: import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
0089: import org.eclipse.ui.texteditor.IDocumentProvider;
0090: import org.eclipse.ui.texteditor.ITextEditorActionConstants;
0091: import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
0092: import org.eclipse.ui.texteditor.ResourceAction;
0093: import org.eclipse.ui.texteditor.TextOperationAction;
0094: import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
0095:
0096: import org.eclipse.jdt.core.ICompilationUnit;
0097: import org.eclipse.jdt.core.IJavaElement;
0098: import org.eclipse.jdt.core.IJavaProject;
0099: import org.eclipse.jdt.core.IMember;
0100: import org.eclipse.jdt.core.ISourceRange;
0101: import org.eclipse.jdt.core.ISourceReference;
0102: import org.eclipse.jdt.core.JavaCore;
0103: import org.eclipse.jdt.core.JavaModelException;
0104: import org.eclipse.jdt.core.dom.CompilationUnit;
0105: import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
0106:
0107: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0108:
0109: import org.eclipse.jdt.ui.IWorkingCopyManager;
0110: import org.eclipse.jdt.ui.JavaUI;
0111: import org.eclipse.jdt.ui.PreferenceConstants;
0112: import org.eclipse.jdt.ui.actions.GenerateActionGroup;
0113: import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
0114: import org.eclipse.jdt.ui.actions.RefactorActionGroup;
0115: import org.eclipse.jdt.ui.text.IJavaPartitions;
0116:
0117: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
0118: import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
0119: import org.eclipse.jdt.internal.ui.JavaPlugin;
0120: import org.eclipse.jdt.internal.ui.actions.AddBlockCommentAction;
0121: import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
0122: import org.eclipse.jdt.internal.ui.actions.IndentAction;
0123: import org.eclipse.jdt.internal.ui.actions.RemoveBlockCommentAction;
0124: import org.eclipse.jdt.internal.ui.actions.SurroundWithActionGroup;
0125: import org.eclipse.jdt.internal.ui.compare.LocalHistoryActionGroup;
0126: import org.eclipse.jdt.internal.ui.text.ContentAssistPreference;
0127: import org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner;
0128: import org.eclipse.jdt.internal.ui.text.SmartBackspaceManager;
0129: import org.eclipse.jdt.internal.ui.text.Symbols;
0130: import org.eclipse.jdt.internal.ui.text.comment.CommentFormattingContext;
0131: import org.eclipse.jdt.internal.ui.text.correction.CorrectionCommandInstaller;
0132: import org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener;
0133:
0134: /**
0135: * Java specific text editor.
0136: */
0137: public class CompilationUnitEditor extends JavaEditor implements
0138: IJavaReconcilingListener {
0139: private static final boolean CODE_ASSIST_DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jdt.ui/debug/ResultCollector")); //$NON-NLS-1$//$NON-NLS-2$
0140:
0141: /**
0142: * Text operation code for requesting common prefix completion.
0143: */
0144: public static final int CONTENTASSIST_COMPLETE_PREFIX = 60;
0145:
0146: interface ITextConverter {
0147: void customizeDocumentCommand(IDocument document,
0148: DocumentCommand command);
0149: }
0150:
0151: class AdaptedSourceViewer extends JavaSourceViewer {
0152:
0153: public AdaptedSourceViewer(Composite parent,
0154: IVerticalRuler verticalRuler,
0155: IOverviewRuler overviewRuler,
0156: boolean showAnnotationsOverview, int styles,
0157: IPreferenceStore store) {
0158: super (parent, verticalRuler, overviewRuler,
0159: showAnnotationsOverview, styles, store);
0160: }
0161:
0162: public IContentAssistant getContentAssistant() {
0163: return fContentAssistant;
0164: }
0165:
0166: /*
0167: * @see ITextOperationTarget#doOperation(int)
0168: */
0169: public void doOperation(int operation) {
0170:
0171: if (getTextWidget() == null)
0172: return;
0173:
0174: switch (operation) {
0175: case CONTENTASSIST_PROPOSALS:
0176: long time = CODE_ASSIST_DEBUG ? System
0177: .currentTimeMillis() : 0;
0178: String msg = fContentAssistant
0179: .showPossibleCompletions();
0180: if (CODE_ASSIST_DEBUG) {
0181: long delta = System.currentTimeMillis() - time;
0182: System.err.println("Code Assist (total): " + delta); //$NON-NLS-1$
0183: }
0184: setStatusLineErrorMessage(msg);
0185: return;
0186: case QUICK_ASSIST:
0187: /*
0188: * XXX: We can get rid of this once the SourceViewer has a way to update the status line
0189: * https://bugs.eclipse.org/bugs/show_bug.cgi?id=133787
0190: */
0191: msg = fQuickAssistAssistant.showPossibleQuickAssists();
0192: setStatusLineErrorMessage(msg);
0193: return;
0194: }
0195:
0196: super .doOperation(operation);
0197: }
0198:
0199: /*
0200: * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
0201: */
0202: public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
0203: if (PlatformUI.getWorkbench().getHelpSystem()
0204: .isContextHelpDisplayed())
0205: return false;
0206: return super .requestWidgetToken(requester);
0207: }
0208:
0209: /*
0210: * @see IWidgetTokenOwnerExtension#requestWidgetToken(IWidgetTokenKeeper, int)
0211: * @since 3.0
0212: */
0213: public boolean requestWidgetToken(IWidgetTokenKeeper requester,
0214: int priority) {
0215: if (PlatformUI.getWorkbench().getHelpSystem()
0216: .isContextHelpDisplayed())
0217: return false;
0218: return super .requestWidgetToken(requester, priority);
0219: }
0220:
0221: /*
0222: * @see org.eclipse.jface.text.source.SourceViewer#createFormattingContext()
0223: * @since 3.0
0224: */
0225: public IFormattingContext createFormattingContext() {
0226: IFormattingContext context = new CommentFormattingContext();
0227:
0228: Map preferences;
0229: IJavaElement inputJavaElement = getInputJavaElement();
0230: IJavaProject javaProject = inputJavaElement != null ? inputJavaElement
0231: .getJavaProject()
0232: : null;
0233: if (javaProject == null)
0234: preferences = new HashMap(JavaCore.getOptions());
0235: else
0236: preferences = new HashMap(javaProject.getOptions(true));
0237:
0238: context.setProperty(
0239: FormattingContextProperties.CONTEXT_PREFERENCES,
0240: preferences);
0241:
0242: return context;
0243: }
0244: }
0245:
0246: private class ExitPolicy implements IExitPolicy {
0247:
0248: final char fExitCharacter;
0249: final char fEscapeCharacter;
0250: final Stack fStack;
0251: final int fSize;
0252:
0253: public ExitPolicy(char exitCharacter, char escapeCharacter,
0254: Stack stack) {
0255: fExitCharacter = exitCharacter;
0256: fEscapeCharacter = escapeCharacter;
0257: fStack = stack;
0258: fSize = fStack.size();
0259: }
0260:
0261: /*
0262: * @see org.eclipse.jdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.eclipse.jdt.internal.ui.text.link.LinkedPositionManager, org.eclipse.swt.events.VerifyEvent, int, int)
0263: */
0264: public ExitFlags doExit(LinkedModeModel model,
0265: VerifyEvent event, int offset, int length) {
0266:
0267: if (fSize == fStack.size() && !isMasked(offset)) {
0268: if (event.character == fExitCharacter) {
0269: BracketLevel level = (BracketLevel) fStack.peek();
0270: if (level.fFirstPosition.offset > offset
0271: || level.fSecondPosition.offset < offset)
0272: return null;
0273: if (level.fSecondPosition.offset == offset
0274: && length == 0)
0275: // don't enter the character if if its the closing peer
0276: return new ExitFlags(
0277: ILinkedModeListener.UPDATE_CARET, false);
0278: }
0279: // when entering an anonymous class between the parenthesis', we don't want
0280: // to jump after the closing parenthesis when return is pressed
0281: if (event.character == SWT.CR && offset > 0) {
0282: IDocument document = getSourceViewer()
0283: .getDocument();
0284: try {
0285: if (document.getChar(offset - 1) == '{')
0286: return new ExitFlags(
0287: ILinkedModeListener.EXIT_ALL, true);
0288: } catch (BadLocationException e) {
0289: }
0290: }
0291: }
0292: return null;
0293: }
0294:
0295: private boolean isMasked(int offset) {
0296: IDocument document = getSourceViewer().getDocument();
0297: try {
0298: return fEscapeCharacter == document.getChar(offset - 1);
0299: } catch (BadLocationException e) {
0300: }
0301: return false;
0302: }
0303: }
0304:
0305: private static class BracketLevel {
0306: int fOffset;
0307: int fLength;
0308: LinkedModeUI fUI;
0309: Position fFirstPosition;
0310: Position fSecondPosition;
0311: }
0312:
0313: /**
0314: * Position updater that takes any changes at the borders of a position to not belong to the position.
0315: *
0316: * @since 3.0
0317: */
0318: private static class ExclusivePositionUpdater implements
0319: IPositionUpdater {
0320:
0321: /** The position category. */
0322: private final String fCategory;
0323:
0324: /**
0325: * Creates a new updater for the given <code>category</code>.
0326: *
0327: * @param category the new category.
0328: */
0329: public ExclusivePositionUpdater(String category) {
0330: fCategory = category;
0331: }
0332:
0333: /*
0334: * @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
0335: */
0336: public void update(DocumentEvent event) {
0337:
0338: int eventOffset = event.getOffset();
0339: int eventOldLength = event.getLength();
0340: int eventNewLength = event.getText() == null ? 0 : event
0341: .getText().length();
0342: int deltaLength = eventNewLength - eventOldLength;
0343:
0344: try {
0345: Position[] positions = event.getDocument()
0346: .getPositions(fCategory);
0347:
0348: for (int i = 0; i != positions.length; i++) {
0349:
0350: Position position = positions[i];
0351:
0352: if (position.isDeleted())
0353: continue;
0354:
0355: int offset = position.getOffset();
0356: int length = position.getLength();
0357: int end = offset + length;
0358:
0359: if (offset >= eventOffset + eventOldLength)
0360: // position comes
0361: // after change - shift
0362: position.setOffset(offset + deltaLength);
0363: else if (end <= eventOffset) {
0364: // position comes way before change -
0365: // leave alone
0366: } else if (offset <= eventOffset
0367: && end >= eventOffset + eventOldLength) {
0368: // event completely internal to the position - adjust length
0369: position.setLength(length + deltaLength);
0370: } else if (offset < eventOffset) {
0371: // event extends over end of position - adjust length
0372: int newEnd = eventOffset;
0373: position.setLength(newEnd - offset);
0374: } else if (end > eventOffset + eventOldLength) {
0375: // event extends from before position into it - adjust offset
0376: // and length
0377: // offset becomes end of event, length adjusted accordingly
0378: int newOffset = eventOffset + eventNewLength;
0379: position.setOffset(newOffset);
0380: position.setLength(end - newOffset);
0381: } else {
0382: // event consumes the position - delete it
0383: position.delete();
0384: }
0385: }
0386: } catch (BadPositionCategoryException e) {
0387: // ignore and return
0388: }
0389: }
0390:
0391: /**
0392: * Returns the position category.
0393: *
0394: * @return the position category
0395: */
0396: public String getCategory() {
0397: return fCategory;
0398: }
0399:
0400: }
0401:
0402: private class BracketInserter implements VerifyKeyListener,
0403: ILinkedModeListener {
0404:
0405: private boolean fCloseBrackets = true;
0406: private boolean fCloseStrings = true;
0407: private boolean fCloseAngularBrackets = true;
0408: private final String CATEGORY = toString();
0409: private IPositionUpdater fUpdater = new ExclusivePositionUpdater(
0410: CATEGORY);
0411: private Stack fBracketLevelStack = new Stack();
0412:
0413: public void setCloseBracketsEnabled(boolean enabled) {
0414: fCloseBrackets = enabled;
0415: }
0416:
0417: public void setCloseStringsEnabled(boolean enabled) {
0418: fCloseStrings = enabled;
0419: }
0420:
0421: public void setCloseAngularBracketsEnabled(boolean enabled) {
0422: fCloseAngularBrackets = enabled;
0423: }
0424:
0425: private boolean isAngularIntroducer(String identifier) {
0426: return identifier.length() > 0
0427: && (Character.isUpperCase(identifier.charAt(0))
0428: || identifier.startsWith("final") //$NON-NLS-1$
0429: || identifier.startsWith("public") //$NON-NLS-1$
0430: || identifier.startsWith("public") //$NON-NLS-1$
0431: || identifier.startsWith("protected") //$NON-NLS-1$
0432: || identifier.startsWith("private")); //$NON-NLS-1$
0433: }
0434:
0435: /*
0436: * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
0437: */
0438: public void verifyKey(VerifyEvent event) {
0439:
0440: // early pruning to slow down normal typing as little as possible
0441: if (!event.doit || getInsertMode() != SMART_INSERT)
0442: return;
0443: switch (event.character) {
0444: case '(':
0445: case '<':
0446: case '[':
0447: case '\'':
0448: case '\"':
0449: break;
0450: default:
0451: return;
0452: }
0453:
0454: final ISourceViewer sourceViewer = getSourceViewer();
0455: IDocument document = sourceViewer.getDocument();
0456:
0457: final Point selection = sourceViewer.getSelectedRange();
0458: final int offset = selection.x;
0459: final int length = selection.y;
0460:
0461: try {
0462: IRegion startLine = document
0463: .getLineInformationOfOffset(offset);
0464: IRegion endLine = document
0465: .getLineInformationOfOffset(offset + length);
0466:
0467: JavaHeuristicScanner scanner = new JavaHeuristicScanner(
0468: document);
0469: int nextToken = scanner.nextToken(offset + length,
0470: endLine.getOffset() + endLine.getLength());
0471: String next = nextToken == Symbols.TokenEOF ? null
0472: : document.get(offset,
0473: scanner.getPosition() - offset).trim();
0474: int prevToken = scanner.previousToken(offset - 1,
0475: startLine.getOffset());
0476: int prevTokenOffset = scanner.getPosition() + 1;
0477: String previous = prevToken == Symbols.TokenEOF ? null
0478: : document.get(prevTokenOffset,
0479: offset - prevTokenOffset).trim();
0480:
0481: switch (event.character) {
0482: case '(':
0483: if (!fCloseBrackets
0484: || nextToken == Symbols.TokenLPAREN
0485: || nextToken == Symbols.TokenIDENT
0486: || next != null && next.length() > 1)
0487: return;
0488: break;
0489:
0490: case '<':
0491: if (!(fCloseAngularBrackets && fCloseBrackets)
0492: || nextToken == Symbols.TokenLESSTHAN
0493: || prevToken != Symbols.TokenLBRACE
0494: && prevToken != Symbols.TokenRBRACE
0495: && prevToken != Symbols.TokenSEMICOLON
0496: && prevToken != Symbols.TokenSYNCHRONIZED
0497: && prevToken != Symbols.TokenSTATIC
0498: && (prevToken != Symbols.TokenIDENT || !isAngularIntroducer(previous))
0499: && prevToken != Symbols.TokenEOF)
0500: return;
0501: break;
0502:
0503: case '[':
0504: if (!fCloseBrackets
0505: || nextToken == Symbols.TokenIDENT
0506: || next != null && next.length() > 1)
0507: return;
0508: break;
0509:
0510: case '\'':
0511: case '"':
0512: if (!fCloseStrings
0513: || nextToken == Symbols.TokenIDENT
0514: || prevToken == Symbols.TokenIDENT
0515: || next != null && next.length() > 1
0516: || previous != null
0517: && previous.length() > 1)
0518: return;
0519: break;
0520:
0521: default:
0522: return;
0523: }
0524:
0525: ITypedRegion partition = TextUtilities.getPartition(
0526: document, IJavaPartitions.JAVA_PARTITIONING,
0527: offset, true);
0528: if (!IDocument.DEFAULT_CONTENT_TYPE.equals(partition
0529: .getType()))
0530: return;
0531:
0532: if (!validateEditorInputState())
0533: return;
0534:
0535: final char character = event.character;
0536: final char closingCharacter = getPeerCharacter(character);
0537: final StringBuffer buffer = new StringBuffer();
0538: buffer.append(character);
0539: buffer.append(closingCharacter);
0540:
0541: document.replace(offset, length, buffer.toString());
0542:
0543: BracketLevel level = new BracketLevel();
0544: fBracketLevelStack.push(level);
0545:
0546: LinkedPositionGroup group = new LinkedPositionGroup();
0547: group.addPosition(new LinkedPosition(document,
0548: offset + 1, 0, LinkedPositionGroup.NO_STOP));
0549:
0550: LinkedModeModel model = new LinkedModeModel();
0551: model.addLinkingListener(this );
0552: model.addGroup(group);
0553: model.forceInstall();
0554:
0555: level.fOffset = offset;
0556: level.fLength = 2;
0557:
0558: // set up position tracking for our magic peers
0559: if (fBracketLevelStack.size() == 1) {
0560: document.addPositionCategory(CATEGORY);
0561: document.addPositionUpdater(fUpdater);
0562: }
0563: level.fFirstPosition = new Position(offset, 1);
0564: level.fSecondPosition = new Position(offset + 1, 1);
0565: document.addPosition(CATEGORY, level.fFirstPosition);
0566: document.addPosition(CATEGORY, level.fSecondPosition);
0567:
0568: level.fUI = new EditorLinkedModeUI(model, sourceViewer);
0569: level.fUI.setSimpleMode(true);
0570: level.fUI.setExitPolicy(new ExitPolicy(
0571: closingCharacter,
0572: getEscapeCharacter(closingCharacter),
0573: fBracketLevelStack));
0574: level.fUI.setExitPosition(sourceViewer, offset + 2, 0,
0575: Integer.MAX_VALUE);
0576: level.fUI.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
0577: level.fUI.enter();
0578:
0579: IRegion newSelection = level.fUI.getSelectedRegion();
0580: sourceViewer.setSelectedRange(newSelection.getOffset(),
0581: newSelection.getLength());
0582:
0583: event.doit = false;
0584:
0585: } catch (BadLocationException e) {
0586: JavaPlugin.log(e);
0587: } catch (BadPositionCategoryException e) {
0588: JavaPlugin.log(e);
0589: }
0590: }
0591:
0592: /*
0593: * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel, int)
0594: */
0595: public void left(LinkedModeModel environment, int flags) {
0596:
0597: final BracketLevel level = (BracketLevel) fBracketLevelStack
0598: .pop();
0599:
0600: if (flags != ILinkedModeListener.EXTERNAL_MODIFICATION)
0601: return;
0602:
0603: // remove brackets
0604: final ISourceViewer sourceViewer = getSourceViewer();
0605: final IDocument document = sourceViewer.getDocument();
0606: if (document instanceof IDocumentExtension) {
0607: IDocumentExtension extension = (IDocumentExtension) document;
0608: extension.registerPostNotificationReplace(null,
0609: new IDocumentExtension.IReplace() {
0610:
0611: public void perform(IDocument d,
0612: IDocumentListener owner) {
0613: if ((level.fFirstPosition.isDeleted || level.fFirstPosition.length == 0)
0614: && !level.fSecondPosition.isDeleted
0615: && level.fSecondPosition.offset == level.fFirstPosition.offset) {
0616: try {
0617: document
0618: .replace(
0619: level.fSecondPosition.offset,
0620: level.fSecondPosition.length,
0621: ""); //$NON-NLS-1$
0622: } catch (BadLocationException e) {
0623: JavaPlugin.log(e);
0624: }
0625: }
0626:
0627: if (fBracketLevelStack.size() == 0) {
0628: document
0629: .removePositionUpdater(fUpdater);
0630: try {
0631: document
0632: .removePositionCategory(CATEGORY);
0633: } catch (BadPositionCategoryException e) {
0634: JavaPlugin.log(e);
0635: }
0636: }
0637: }
0638: });
0639: }
0640:
0641: }
0642:
0643: /*
0644: * @see org.eclipse.jface.text.link.ILinkedModeListener#suspend(org.eclipse.jface.text.link.LinkedModeModel)
0645: */
0646: public void suspend(LinkedModeModel environment) {
0647: }
0648:
0649: /*
0650: * @see org.eclipse.jface.text.link.ILinkedModeListener#resume(org.eclipse.jface.text.link.LinkedModeModel, int)
0651: */
0652: public void resume(LinkedModeModel environment, int flags) {
0653: }
0654: }
0655:
0656: /**
0657: * Remembers data related to the current selection to be able to
0658: * restore it later.
0659: *
0660: * @since 3.0
0661: */
0662: private class RememberedSelection {
0663: /** The remembered selection start. */
0664: private RememberedOffset fStartOffset = new RememberedOffset();
0665: /** The remembered selection end. */
0666: private RememberedOffset fEndOffset = new RememberedOffset();
0667:
0668: /**
0669: * Remember current selection.
0670: */
0671: public void remember() {
0672: /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257
0673: * This method may be called inside an asynchronous call posted
0674: * to the UI thread, so protect against intermediate disposal
0675: * of the editor.
0676: */
0677: ISourceViewer viewer = getSourceViewer();
0678: if (viewer != null) {
0679: Point selection = viewer.getSelectedRange();
0680: int startOffset = selection.x;
0681: int endOffset = startOffset + selection.y;
0682:
0683: fStartOffset.setOffset(startOffset);
0684: fEndOffset.setOffset(endOffset);
0685: }
0686: }
0687:
0688: /**
0689: * Restore remembered selection.
0690: */
0691: public void restore() {
0692: /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257
0693: * This method may be called inside an asynchronous call posted
0694: * to the UI thread, so protect against intermediate disposal
0695: * of the editor.
0696: */
0697: if (getSourceViewer() == null)
0698: return;
0699:
0700: try {
0701:
0702: int startOffset, endOffset;
0703: int revealStartOffset, revealEndOffset;
0704: if (showsHighlightRangeOnly()) {
0705: IJavaElement newStartElement = fStartOffset
0706: .getElement();
0707: startOffset = fStartOffset
0708: .getRememberedOffset(newStartElement);
0709: revealStartOffset = fStartOffset.getRevealOffset(
0710: newStartElement, startOffset);
0711: if (revealStartOffset == -1)
0712: startOffset = -1;
0713:
0714: IJavaElement newEndElement = fEndOffset
0715: .getElement();
0716: endOffset = fEndOffset
0717: .getRememberedOffset(newEndElement);
0718: revealEndOffset = fEndOffset.getRevealOffset(
0719: newEndElement, endOffset);
0720: if (revealEndOffset == -1)
0721: endOffset = -1;
0722: } else {
0723: startOffset = fStartOffset.getOffset();
0724: revealStartOffset = startOffset;
0725: endOffset = fEndOffset.getOffset();
0726: revealEndOffset = endOffset;
0727: }
0728:
0729: if (startOffset == -1) {
0730: startOffset = endOffset; // fallback to caret offset
0731: revealStartOffset = revealEndOffset;
0732: }
0733:
0734: if (endOffset == -1) {
0735: endOffset = startOffset; // fallback to other offset
0736: revealEndOffset = revealStartOffset;
0737: }
0738:
0739: IJavaElement element;
0740: if (endOffset == -1) {
0741: // fallback to element selection
0742: element = fEndOffset.getElement();
0743: if (element == null)
0744: element = fStartOffset.getElement();
0745: if (element != null)
0746: setSelection(element);
0747: return;
0748: }
0749:
0750: if (isValidSelection(revealStartOffset, revealEndOffset
0751: - revealStartOffset)
0752: && isValidSelection(startOffset, endOffset
0753: - startOffset))
0754: selectAndReveal(startOffset, endOffset
0755: - startOffset, revealStartOffset,
0756: revealEndOffset - revealStartOffset);
0757: } finally {
0758: fStartOffset.clear();
0759: fEndOffset.clear();
0760: }
0761: }
0762:
0763: private boolean isValidSelection(int offset, int length) {
0764: IDocumentProvider provider = getDocumentProvider();
0765: if (provider != null) {
0766: IDocument document = provider
0767: .getDocument(getEditorInput());
0768: if (document != null) {
0769: int end = offset + length;
0770: int documentLength = document.getLength();
0771: return 0 <= offset && offset <= documentLength
0772: && 0 <= end && end <= documentLength
0773: && length >= 0;
0774: }
0775: }
0776: return false;
0777: }
0778:
0779: }
0780:
0781: /**
0782: * Remembers additional data for a given
0783: * offset to be able restore it later.
0784: *
0785: * @since 3.0
0786: */
0787: private class RememberedOffset {
0788: /** Remembered line for the given offset */
0789: private int fLine;
0790: /** Remembered column for the given offset*/
0791: private int fColumn;
0792: /** Remembered Java element for the given offset*/
0793: private IJavaElement fElement;
0794: /** Remembered Java element line for the given offset*/
0795: private int fElementLine;
0796:
0797: /**
0798: * Store visual properties of the given offset.
0799: *
0800: * @param offset Offset in the document
0801: */
0802: public void setOffset(int offset) {
0803: try {
0804: IDocument document = getSourceViewer().getDocument();
0805: fLine = document.getLineOfOffset(offset);
0806: fColumn = offset - document.getLineOffset(fLine);
0807: fElement = getElementAt(offset, true);
0808: fElementLine = getElementLine(document, fElement);
0809: } catch (BadLocationException e) {
0810: // should not happen
0811: JavaPlugin.log(e);
0812: clear();
0813: } catch (JavaModelException e) {
0814: // should not happen
0815: JavaPlugin.log(e.getStatus());
0816: clear();
0817: }
0818: }
0819:
0820: /**
0821: * Computes the element line of a java element (the start of the element, or the line with
0822: * the element's name range).
0823: *
0824: * @param document the displayed document for line information
0825: * @param element the java element, may be <code>null</code>
0826: * @return the element's start line, or -1
0827: * @throws BadLocationException
0828: * @throws JavaModelException
0829: * @since 3.2
0830: */
0831: private int getElementLine(IDocument document,
0832: IJavaElement element) throws BadLocationException,
0833: JavaModelException {
0834: if (element instanceof IMember) {
0835: ISourceRange range = ((IMember) element).getNameRange();
0836: if (range != null)
0837: return document.getLineOfOffset(range.getOffset());
0838: }
0839: int elementOffset = getOffset(element);
0840: if (elementOffset != -1)
0841: return document.getLineOfOffset(elementOffset);
0842: return -1;
0843: }
0844:
0845: /**
0846: * Return offset recomputed from stored visual properties.
0847: *
0848: * @return Offset in the document
0849: */
0850: public int getOffset() {
0851: IJavaElement newElement = getElement();
0852:
0853: int offset = getRememberedOffset(newElement);
0854:
0855: if (offset == -1
0856: || newElement != null
0857: && !containsOffset(newElement, offset)
0858: && (offset == 0 || !containsOffset(newElement,
0859: offset - 1)))
0860: return -1;
0861:
0862: return offset;
0863: }
0864:
0865: /**
0866: * Return offset recomputed from stored visual properties.
0867: *
0868: * @param newElement Enclosing element
0869: * @return Offset in the document
0870: */
0871: public int getRememberedOffset(IJavaElement newElement) {
0872: try {
0873: IDocument document = getSourceViewer().getDocument();
0874: int newElementLine = getElementLine(document,
0875: newElement);
0876: int newLine = fLine;
0877: if (newElementLine != -1 && fElementLine != -1)
0878: newLine += newElementLine - fElementLine;
0879:
0880: if (newLine < 0
0881: || newLine >= document.getNumberOfLines())
0882: return -1;
0883: int maxColumn = document.getLineLength(newLine);
0884: String lineDelimiter = document
0885: .getLineDelimiter(newLine);
0886: if (lineDelimiter != null)
0887: maxColumn = maxColumn - lineDelimiter.length();
0888: int offset;
0889: if (fColumn > maxColumn)
0890: offset = document.getLineOffset(newLine)
0891: + maxColumn;
0892: else
0893: offset = document.getLineOffset(newLine) + fColumn;
0894:
0895: return offset;
0896: } catch (BadLocationException e) {
0897: // should not happen
0898: JavaPlugin.log(e);
0899: return -1;
0900: } catch (JavaModelException e) {
0901: // should not happen
0902: JavaPlugin.log(e.getStatus());
0903: return -1;
0904: }
0905: }
0906:
0907: /**
0908: * Returns the offset used to reveal the given element based on the given selection offset.
0909: * @param element the element
0910: * @param offset the selection offset
0911: * @return the offset to reveal the given element based on the given selection offset
0912: */
0913: public int getRevealOffset(IJavaElement element, int offset) {
0914: if (element == null || offset == -1)
0915: return -1;
0916:
0917: if (containsOffset(element, offset)) {
0918: if (offset > 0) {
0919: IJavaElement alternateElement = getElementAt(
0920: offset, false);
0921: if (element.getHandleIdentifier().equals(
0922: alternateElement.getParent()
0923: .getHandleIdentifier()))
0924: return offset - 1; // Solves test case 2 from https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
0925: }
0926: return offset;
0927: } else if (offset > 0
0928: && containsOffset(element, offset - 1))
0929: return offset - 1; // Solves test case 1 from https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
0930:
0931: return -1;
0932: }
0933:
0934: /**
0935: * Return Java element recomputed from stored visual properties.
0936: *
0937: * @return Java element
0938: */
0939: public IJavaElement getElement() {
0940: if (fElement == null)
0941: return null;
0942:
0943: return findElement(fElement);
0944: }
0945:
0946: /**
0947: * Clears the stored position
0948: */
0949: public void clear() {
0950: fLine = -1;
0951: fColumn = -1;
0952: fElement = null;
0953: fElementLine = -1;
0954: }
0955:
0956: /**
0957: * Does the given Java element contain the given offset?
0958: * @param element Java element
0959: * @param offset Offset
0960: * @return <code>true</code> iff the Java element contains the offset
0961: */
0962: private boolean containsOffset(IJavaElement element, int offset) {
0963: int elementOffset = getOffset(element);
0964: int elementLength = getLength(element);
0965: return (elementOffset > -1 && elementLength > -1) ? (offset >= elementOffset && offset < elementOffset
0966: + elementLength)
0967: : false;
0968: }
0969:
0970: /**
0971: * Returns the offset of the given Java element.
0972: *
0973: * @param element Java element
0974: * @return Offset of the given Java element
0975: */
0976: private int getOffset(IJavaElement element) {
0977: if (element instanceof ISourceReference) {
0978: ISourceReference sr = (ISourceReference) element;
0979: try {
0980: ISourceRange srcRange = sr.getSourceRange();
0981: if (srcRange != null)
0982: return srcRange.getOffset();
0983: } catch (JavaModelException e) {
0984: }
0985: }
0986: return -1;
0987: }
0988:
0989: /**
0990: * Returns the length of the given Java element.
0991: *
0992: * @param element Java element
0993: * @return Length of the given Java element
0994: */
0995: private int getLength(IJavaElement element) {
0996: if (element instanceof ISourceReference) {
0997: ISourceReference sr = (ISourceReference) element;
0998: try {
0999: ISourceRange srcRange = sr.getSourceRange();
1000: if (srcRange != null)
1001: return srcRange.getLength();
1002: } catch (JavaModelException e) {
1003: }
1004: }
1005: return -1;
1006: }
1007:
1008: /**
1009: * Returns the updated java element for the old java element.
1010: *
1011: * @param element Old Java element
1012: * @return Updated Java element
1013: */
1014: private IJavaElement findElement(IJavaElement element) {
1015:
1016: if (element == null)
1017: return null;
1018:
1019: IWorkingCopyManager manager = JavaPlugin.getDefault()
1020: .getWorkingCopyManager();
1021: ICompilationUnit unit = manager
1022: .getWorkingCopy(getEditorInput());
1023:
1024: if (unit != null) {
1025: try {
1026: JavaModelUtil.reconcile(unit);
1027: IJavaElement[] findings = unit
1028: .findElements(element);
1029: if (findings != null && findings.length > 0)
1030: return findings[0];
1031:
1032: } catch (JavaModelException x) {
1033: JavaPlugin.log(x.getStatus());
1034: // nothing found, be tolerant and go on
1035: }
1036: }
1037:
1038: return null;
1039: }
1040:
1041: }
1042:
1043: /** Preference key for code formatter tab size */
1044: private final static String CODE_FORMATTER_TAB_SIZE = DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE;
1045: /** Preference key for inserting spaces rather than tabs */
1046: private final static String SPACES_FOR_TABS = DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR;
1047: /** Preference key for automatically closing strings */
1048: private final static String CLOSE_STRINGS = PreferenceConstants.EDITOR_CLOSE_STRINGS;
1049: /** Preference key for automatically closing brackets and parenthesis */
1050: private final static String CLOSE_BRACKETS = PreferenceConstants.EDITOR_CLOSE_BRACKETS;
1051:
1052: /** The editor's save policy */
1053: protected ISavePolicy fSavePolicy;
1054: /** Listener to annotation model changes that updates the error tick in the tab image */
1055: private JavaEditorErrorTickUpdater fJavaEditorErrorTickUpdater;
1056: /**
1057: * The remembered selection.
1058: * @since 3.0
1059: */
1060: private RememberedSelection fRememberedSelection = new RememberedSelection();
1061: /** The bracket inserter. */
1062: private BracketInserter fBracketInserter = new BracketInserter();
1063:
1064: /** The standard action groups added to the menu */
1065: private GenerateActionGroup fGenerateActionGroup;
1066: private CompositeActionGroup fContextMenuGroup;
1067:
1068: private CorrectionCommandInstaller fCorrectionCommands;
1069:
1070: /**
1071: * Reconciling listeners.
1072: * @since 3.0
1073: */
1074: private ListenerList fReconcilingListeners = new ListenerList(
1075: ListenerList.IDENTITY);
1076:
1077: /**
1078: * Mutex for the reconciler. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
1079: * for a description of the problem.
1080: * <p>
1081: * XXX remove once the underlying problem (https://bugs.eclipse.org/bugs/show_bug.cgi?id=66176) is solved.
1082: * </p>
1083: */
1084: private final Object fReconcilerLock = new Object();
1085:
1086: /**
1087: * Creates a new compilation unit editor.
1088: */
1089: public CompilationUnitEditor() {
1090: super ();
1091: setDocumentProvider(JavaPlugin.getDefault()
1092: .getCompilationUnitDocumentProvider());
1093: setEditorContextMenuId("#CompilationUnitEditorContext"); //$NON-NLS-1$
1094: setRulerContextMenuId("#CompilationUnitRulerContext"); //$NON-NLS-1$
1095: setOutlinerContextMenuId("#CompilationUnitOutlinerContext"); //$NON-NLS-1$
1096: // don't set help contextId, we install our own help context
1097: fSavePolicy = null;
1098:
1099: fJavaEditorErrorTickUpdater = new JavaEditorErrorTickUpdater(
1100: this );
1101: fCorrectionCommands = null;
1102: }
1103:
1104: /*
1105: * @see AbstractTextEditor#createActions()
1106: */
1107: protected void createActions() {
1108:
1109: super .createActions();
1110:
1111: IAction action = new ContentAssistAction(JavaEditorMessages
1112: .getBundleForConstructedKeys(),
1113: "ContentAssistProposal.", this ); //$NON-NLS-1$
1114: action
1115: .setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
1116: setAction("ContentAssistProposal", action); //$NON-NLS-1$
1117: markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
1118: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1119: IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
1120:
1121: action = new TextOperationAction(
1122: JavaEditorMessages.getBundleForConstructedKeys(),
1123: "ContentAssistContextInformation.", this , ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
1124: action
1125: .setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
1126: setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
1127: markAsStateDependentAction(
1128: "ContentAssistContextInformation", true); //$NON-NLS-1$
1129: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1130: IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
1131:
1132: action = new TextOperationAction(JavaEditorMessages
1133: .getBundleForConstructedKeys(),
1134: "Comment.", this , ITextOperationTarget.PREFIX); //$NON-NLS-1$
1135: action
1136: .setActionDefinitionId(IJavaEditorActionDefinitionIds.COMMENT);
1137: setAction("Comment", action); //$NON-NLS-1$
1138: markAsStateDependentAction("Comment", true); //$NON-NLS-1$
1139: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1140: IJavaHelpContextIds.COMMENT_ACTION);
1141:
1142: action = new TextOperationAction(JavaEditorMessages
1143: .getBundleForConstructedKeys(),
1144: "Uncomment.", this , ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
1145: action
1146: .setActionDefinitionId(IJavaEditorActionDefinitionIds.UNCOMMENT);
1147: setAction("Uncomment", action); //$NON-NLS-1$
1148: markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
1149: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1150: IJavaHelpContextIds.UNCOMMENT_ACTION);
1151:
1152: action = new ToggleCommentAction(JavaEditorMessages
1153: .getBundleForConstructedKeys(), "ToggleComment.", this ); //$NON-NLS-1$
1154: action
1155: .setActionDefinitionId(IJavaEditorActionDefinitionIds.TOGGLE_COMMENT);
1156: setAction("ToggleComment", action); //$NON-NLS-1$
1157: markAsStateDependentAction("ToggleComment", true); //$NON-NLS-1$
1158: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1159: IJavaHelpContextIds.TOGGLE_COMMENT_ACTION);
1160: configureToggleCommentAction();
1161:
1162: action = new TextOperationAction(JavaEditorMessages
1163: .getBundleForConstructedKeys(),
1164: "Format.", this , ISourceViewer.FORMAT); //$NON-NLS-1$
1165: action
1166: .setActionDefinitionId(IJavaEditorActionDefinitionIds.FORMAT);
1167: setAction("Format", action); //$NON-NLS-1$
1168: markAsStateDependentAction("Format", true); //$NON-NLS-1$
1169: markAsSelectionDependentAction("Format", true); //$NON-NLS-1$
1170: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1171: IJavaHelpContextIds.FORMAT_ACTION);
1172:
1173: action = new AddBlockCommentAction(JavaEditorMessages
1174: .getBundleForConstructedKeys(),
1175: "AddBlockComment.", this ); //$NON-NLS-1$
1176: action
1177: .setActionDefinitionId(IJavaEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
1178: setAction("AddBlockComment", action); //$NON-NLS-1$
1179: markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
1180: markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$
1181: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1182: IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
1183:
1184: action = new RemoveBlockCommentAction(JavaEditorMessages
1185: .getBundleForConstructedKeys(),
1186: "RemoveBlockComment.", this ); //$NON-NLS-1$
1187: action
1188: .setActionDefinitionId(IJavaEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);
1189: setAction("RemoveBlockComment", action); //$NON-NLS-1$
1190: markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
1191: markAsSelectionDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
1192: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1193: IJavaHelpContextIds.REMOVE_BLOCK_COMMENT_ACTION);
1194:
1195: action = new IndentAction(JavaEditorMessages
1196: .getBundleForConstructedKeys(), "Indent.", this , false); //$NON-NLS-1$
1197: action
1198: .setActionDefinitionId(IJavaEditorActionDefinitionIds.INDENT);
1199: setAction("Indent", action); //$NON-NLS-1$
1200: markAsStateDependentAction("Indent", true); //$NON-NLS-1$
1201: markAsSelectionDependentAction("Indent", true); //$NON-NLS-1$
1202: PlatformUI.getWorkbench().getHelpSystem().setHelp(action,
1203: IJavaHelpContextIds.INDENT_ACTION);
1204:
1205: action = new IndentAction(JavaEditorMessages
1206: .getBundleForConstructedKeys(), "Indent.", this , true); //$NON-NLS-1$
1207: setAction("IndentOnTab", action); //$NON-NLS-1$
1208: markAsStateDependentAction("IndentOnTab", true); //$NON-NLS-1$
1209: markAsSelectionDependentAction("IndentOnTab", true); //$NON-NLS-1$
1210:
1211: // override the text editor actions with indenting move line actions
1212: JavaMoveLinesAction[] moveLinesActions = JavaMoveLinesAction
1213: .createMoveCopyActionSet(JavaEditorMessages
1214: .getBundleForConstructedKeys(), this );
1215: ResourceAction rAction = moveLinesActions[0];
1216: rAction
1217: .setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION);
1218: rAction
1219: .setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_UP);
1220: setAction(ITextEditorActionConstants.MOVE_LINE_UP, rAction);
1221:
1222: rAction = moveLinesActions[1];
1223: rAction
1224: .setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION);
1225: rAction
1226: .setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_DOWN);
1227: setAction(ITextEditorActionConstants.MOVE_LINE_DOWN, rAction);
1228:
1229: rAction = moveLinesActions[2];
1230: rAction
1231: .setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION);
1232: rAction
1233: .setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_UP);
1234: setAction(ITextEditorActionConstants.COPY_LINE_UP, rAction);
1235:
1236: rAction = moveLinesActions[3];
1237: rAction
1238: .setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION);
1239: rAction
1240: .setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_DOWN);
1241: setAction(ITextEditorActionConstants.COPY_LINE_DOWN, rAction);
1242:
1243: if (getPreferenceStore().getBoolean(
1244: PreferenceConstants.EDITOR_SMART_TAB)) {
1245: // don't replace Shift Right - have to make sure their enablement is mutually exclusive
1246: // removeActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT);
1247: setActionActivationCode("IndentOnTab", '\t', -1, SWT.NONE); //$NON-NLS-1$
1248: }
1249:
1250: fGenerateActionGroup = new GenerateActionGroup(this ,
1251: ITextEditorActionConstants.GROUP_EDIT);
1252: ActionGroup rg = new RefactorActionGroup(this ,
1253: ITextEditorActionConstants.GROUP_EDIT, false);
1254: ActionGroup surroundWith = new SurroundWithActionGroup(this ,
1255: ITextEditorActionConstants.GROUP_EDIT);
1256:
1257: fActionGroups.addGroup(surroundWith);
1258: fActionGroups.addGroup(rg);
1259: fActionGroups.addGroup(fGenerateActionGroup);
1260:
1261: // We have to keep the context menu group separate to have better control over positioning
1262: fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] {
1263: fGenerateActionGroup,
1264: rg,
1265: surroundWith,
1266: new LocalHistoryActionGroup(this ,
1267: ITextEditorActionConstants.GROUP_EDIT) });
1268:
1269: fCorrectionCommands = new CorrectionCommandInstaller(); // allow shortcuts for quick fix/assist
1270: fCorrectionCommands.registerCommands(this );
1271: }
1272:
1273: /*
1274: * @see JavaEditor#getElementAt(int)
1275: */
1276: protected IJavaElement getElementAt(int offset) {
1277: return getElementAt(offset, true);
1278: }
1279:
1280: /**
1281: * Returns the most narrow element including the given offset. If <code>reconcile</code>
1282: * is <code>true</code> the editor's input element is reconciled in advance. If it is
1283: * <code>false</code> this method only returns a result if the editor's input element
1284: * does not need to be reconciled.
1285: *
1286: * @param offset the offset included by the retrieved element
1287: * @param reconcile <code>true</code> if working copy should be reconciled
1288: * @return the most narrow element which includes the given offset
1289: */
1290: protected IJavaElement getElementAt(int offset, boolean reconcile) {
1291: ICompilationUnit unit = (ICompilationUnit) getInputJavaElement();
1292:
1293: if (unit != null) {
1294: try {
1295: if (reconcile) {
1296: JavaModelUtil.reconcile(unit);
1297: return unit.getElementAt(offset);
1298: } else if (unit.isConsistent())
1299: return unit.getElementAt(offset);
1300:
1301: } catch (JavaModelException x) {
1302: if (!x.isDoesNotExist())
1303: JavaPlugin.log(x.getStatus());
1304: // nothing found, be tolerant and go on
1305: }
1306: }
1307:
1308: return null;
1309: }
1310:
1311: /*
1312: * @see JavaEditor#getCorrespondingElement(IJavaElement)
1313: */
1314: protected IJavaElement getCorrespondingElement(IJavaElement element) {
1315: // XXX: With new working copy story: original == working copy.
1316: // Note that the previous code could result in a reconcile as side effect. Should check if that
1317: // is still required.
1318: return element;
1319: }
1320:
1321: /*
1322: * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
1323: */
1324: public void editorContextMenuAboutToShow(IMenuManager menu) {
1325: super .editorContextMenuAboutToShow(menu);
1326:
1327: ActionContext context = new ActionContext(
1328: getSelectionProvider().getSelection());
1329: fContextMenuGroup.setContext(context);
1330: fContextMenuGroup.fillContextMenu(menu);
1331: fContextMenuGroup.setContext(null);
1332: }
1333:
1334: /*
1335: * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean, org.eclipse.core.runtime.IProgressMonitor)
1336: */
1337: protected void performSave(boolean overwrite,
1338: IProgressMonitor progressMonitor) {
1339: IDocumentProvider p = getDocumentProvider();
1340: if (p instanceof ICompilationUnitDocumentProvider) {
1341: ICompilationUnitDocumentProvider cp = (ICompilationUnitDocumentProvider) p;
1342: cp.setSavePolicy(fSavePolicy);
1343: }
1344: try {
1345: super .performSave(overwrite, progressMonitor);
1346: } finally {
1347: if (p instanceof ICompilationUnitDocumentProvider) {
1348: ICompilationUnitDocumentProvider cp = (ICompilationUnitDocumentProvider) p;
1349: cp.setSavePolicy(null);
1350: }
1351: }
1352: }
1353:
1354: /*
1355: * @see AbstractTextEditor#doSave(IProgressMonitor)
1356: */
1357: public void doSave(IProgressMonitor progressMonitor) {
1358:
1359: IDocumentProvider p = getDocumentProvider();
1360: if (p == null) {
1361: // editor has been closed
1362: return;
1363: }
1364:
1365: if (p.isDeleted(getEditorInput())) {
1366:
1367: if (isSaveAsAllowed()) {
1368:
1369: /*
1370: * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
1371: * Changed Behavior to make sure that if called inside a regular save (because
1372: * of deletion of input element) there is a way to report back to the caller.
1373: */
1374: performSaveAs(progressMonitor);
1375:
1376: } else {
1377:
1378: /*
1379: * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there
1380: * Missing resources.
1381: */
1382: Shell shell = getSite().getShell();
1383: MessageDialog
1384: .openError(
1385: shell,
1386: JavaEditorMessages.CompilationUnitEditor_error_saving_title1,
1387: JavaEditorMessages.CompilationUnitEditor_error_saving_message1);
1388: }
1389:
1390: } else {
1391:
1392: setStatusLineErrorMessage(null);
1393:
1394: updateState(getEditorInput());
1395: validateState(getEditorInput());
1396:
1397: IWorkingCopyManager manager = JavaPlugin.getDefault()
1398: .getWorkingCopyManager();
1399: ICompilationUnit unit = manager
1400: .getWorkingCopy(getEditorInput());
1401:
1402: if (unit != null) {
1403: synchronized (unit) {
1404: performSave(false, progressMonitor);
1405: }
1406: } else
1407: performSave(false, progressMonitor);
1408: }
1409: }
1410:
1411: /*
1412: * @see org.eclipse.ui.texteditor.AbstractTextEditor#openSaveErrorDialog(java.lang.String, java.lang.String, org.eclipse.core.runtime.CoreException)
1413: * @since 3.3
1414: */
1415: protected void openSaveErrorDialog(String title, String message,
1416: CoreException exception) {
1417: IStatus status = exception.getStatus();
1418: if (JavaUI.ID_PLUGIN.equals(status.getPlugin())
1419: && status.getCode() == IJavaStatusConstants.EDITOR_POST_SAVE_NOTIFICATION) {
1420: int mask = IStatus.OK | IStatus.INFO | IStatus.WARNING
1421: | IStatus.ERROR;
1422: ErrorDialog dialog = new ErrorDialog(getSite().getShell(),
1423: title, message, status, mask) {
1424: protected Control createDialogArea(Composite parent) {
1425: parent = (Composite) super .createDialogArea(parent);
1426: Link link = new Link(parent, SWT.NONE);
1427: link
1428: .setText(JavaEditorMessages.CompilationUnitEditor_error_saving_saveParticipant);
1429: link.addSelectionListener(new SelectionAdapter() {
1430: public void widgetSelected(SelectionEvent e) {
1431: PreferencesUtil
1432: .createPreferenceDialogOn(
1433: getShell(),
1434: "org.eclipse.jdt.ui.preferences.SaveParticipantPreferencePage", null, null).open(); //$NON-NLS-1$
1435: }
1436: });
1437: GridData gridData = new GridData(SWT.FILL,
1438: SWT.BEGINNING, true, false);
1439: link.setLayoutData(gridData);
1440: return parent;
1441: }
1442: };
1443: dialog.open();
1444: } else
1445: super .openSaveErrorDialog(title, message, exception);
1446: }
1447:
1448: public boolean isSaveAsAllowed() {
1449: return true;
1450: }
1451:
1452: /*
1453: * @see AbstractTextEditor#doSetInput(IEditorInput)
1454: */
1455: protected void doSetInput(IEditorInput input) throws CoreException {
1456: super .doSetInput(input);
1457: configureToggleCommentAction();
1458: if (fJavaEditorErrorTickUpdater != null)
1459: fJavaEditorErrorTickUpdater
1460: .updateEditorImage(getInputJavaElement());
1461: }
1462:
1463: /*
1464: * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#installOverrideIndicator(boolean)
1465: * @since 3.0
1466: */
1467: protected void installOverrideIndicator(boolean provideAST) {
1468: super .installOverrideIndicator(provideAST);
1469:
1470: if (fOverrideIndicatorManager == null)
1471: return;
1472:
1473: addReconcileListener(fOverrideIndicatorManager);
1474: }
1475:
1476: /*
1477: * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#uninstallOverrideIndicator()
1478: * @since 3.0
1479: */
1480: protected void uninstallOverrideIndicator() {
1481: if (fOverrideIndicatorManager != null)
1482: removeReconcileListener(fOverrideIndicatorManager);
1483: super .uninstallOverrideIndicator();
1484: }
1485:
1486: /**
1487: * Configures the toggle comment action
1488: *
1489: * @since 3.0
1490: */
1491: private void configureToggleCommentAction() {
1492: IAction action = getAction("ToggleComment"); //$NON-NLS-1$
1493: if (action instanceof ToggleCommentAction) {
1494: ISourceViewer sourceViewer = getSourceViewer();
1495: SourceViewerConfiguration configuration = getSourceViewerConfiguration();
1496: ((ToggleCommentAction) action).configure(sourceViewer,
1497: configuration);
1498: }
1499: }
1500:
1501: /*
1502: * @see org.eclipse.ui.texteditor.AbstractTextEditor#installTabsToSpacesConverter()
1503: * @since 3.3
1504: */
1505: protected void installTabsToSpacesConverter() {
1506: ISourceViewer sourceViewer = getSourceViewer();
1507: SourceViewerConfiguration config = getSourceViewerConfiguration();
1508: if (config != null
1509: && sourceViewer instanceof ITextViewerExtension7) {
1510: int tabWidth = config.getTabWidth(sourceViewer);
1511: TabsToSpacesConverter tabToSpacesConverter = new TabsToSpacesConverter();
1512: tabToSpacesConverter.setNumberOfSpacesPerTab(tabWidth);
1513: IDocumentProvider provider = getDocumentProvider();
1514: if (provider instanceof ICompilationUnitDocumentProvider) {
1515: ICompilationUnitDocumentProvider cup = (ICompilationUnitDocumentProvider) provider;
1516: tabToSpacesConverter.setLineTracker(cup
1517: .createLineTracker(getEditorInput()));
1518: } else
1519: tabToSpacesConverter
1520: .setLineTracker(new DefaultLineTracker());
1521: ((ITextViewerExtension7) sourceViewer)
1522: .setTabsToSpacesConverter(tabToSpacesConverter);
1523: updateIndentPrefixes();
1524: }
1525: }
1526:
1527: /*
1528: * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isTabsToSpacesConversionEnabled()
1529: * @since 3.3
1530: */
1531: protected boolean isTabsToSpacesConversionEnabled() {
1532: IJavaElement element = getInputJavaElement();
1533: IJavaProject project = element == null ? null : element
1534: .getJavaProject();
1535: String option;
1536: if (project == null)
1537: option = JavaCore.getOption(SPACES_FOR_TABS);
1538: else
1539: option = project.getOption(SPACES_FOR_TABS, true);
1540: return JavaCore.SPACE.equals(option);
1541: }
1542:
1543: public void dispose() {
1544:
1545: ISourceViewer sourceViewer = getSourceViewer();
1546: if (sourceViewer instanceof ITextViewerExtension)
1547: ((ITextViewerExtension) sourceViewer)
1548: .removeVerifyKeyListener(fBracketInserter);
1549:
1550: if (fJavaEditorErrorTickUpdater != null) {
1551: fJavaEditorErrorTickUpdater.dispose();
1552: fJavaEditorErrorTickUpdater = null;
1553: }
1554:
1555: if (fCorrectionCommands != null) {
1556: fCorrectionCommands.deregisterCommands();
1557: fCorrectionCommands = null;
1558: }
1559:
1560: super .dispose();
1561: }
1562:
1563: /*
1564: * @see AbstractTextEditor#createPartControl(Composite)
1565: */
1566: public void createPartControl(Composite parent) {
1567:
1568: super .createPartControl(parent);
1569:
1570: IPreferenceStore preferenceStore = getPreferenceStore();
1571: boolean closeBrackets = preferenceStore
1572: .getBoolean(CLOSE_BRACKETS);
1573: boolean closeStrings = preferenceStore
1574: .getBoolean(CLOSE_STRINGS);
1575: boolean closeAngularBrackets = JavaCore.VERSION_1_5
1576: .compareTo(preferenceStore
1577: .getString(JavaCore.COMPILER_SOURCE)) <= 0;
1578:
1579: fBracketInserter.setCloseBracketsEnabled(closeBrackets);
1580: fBracketInserter.setCloseStringsEnabled(closeStrings);
1581: fBracketInserter
1582: .setCloseAngularBracketsEnabled(closeAngularBrackets);
1583:
1584: ISourceViewer sourceViewer = getSourceViewer();
1585: if (sourceViewer instanceof ITextViewerExtension)
1586: ((ITextViewerExtension) sourceViewer)
1587: .prependVerifyKeyListener(fBracketInserter);
1588:
1589: if (isMarkingOccurrences())
1590: installOccurrencesFinder(false);
1591: }
1592:
1593: private static char getEscapeCharacter(char character) {
1594: switch (character) {
1595: case '"':
1596: case '\'':
1597: return '\\';
1598: default:
1599: return 0;
1600: }
1601: }
1602:
1603: private static char getPeerCharacter(char character) {
1604: switch (character) {
1605: case '(':
1606: return ')';
1607:
1608: case ')':
1609: return '(';
1610:
1611: case '<':
1612: return '>';
1613:
1614: case '>':
1615: return '<';
1616:
1617: case '[':
1618: return ']';
1619:
1620: case ']':
1621: return '[';
1622:
1623: case '"':
1624: return character;
1625:
1626: case '\'':
1627: return character;
1628:
1629: default:
1630: throw new IllegalArgumentException();
1631: }
1632: }
1633:
1634: /*
1635: * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1636: */
1637: protected void handlePreferenceStoreChanged(
1638: PropertyChangeEvent event) {
1639:
1640: try {
1641:
1642: AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1643: if (asv != null) {
1644:
1645: String p = event.getProperty();
1646:
1647: if (CLOSE_BRACKETS.equals(p)) {
1648: fBracketInserter
1649: .setCloseBracketsEnabled(getPreferenceStore()
1650: .getBoolean(p));
1651: return;
1652: }
1653:
1654: if (CLOSE_STRINGS.equals(p)) {
1655: fBracketInserter
1656: .setCloseStringsEnabled(getPreferenceStore()
1657: .getBoolean(p));
1658: return;
1659: }
1660:
1661: if (JavaCore.COMPILER_SOURCE.equals(p)) {
1662: boolean closeAngularBrackets = JavaCore.VERSION_1_5
1663: .compareTo(getPreferenceStore()
1664: .getString(p)) <= 0;
1665: fBracketInserter
1666: .setCloseAngularBracketsEnabled(closeAngularBrackets);
1667: }
1668:
1669: if (SPACES_FOR_TABS.equals(p)) {
1670: if (isTabsToSpacesConversionEnabled())
1671: installTabsToSpacesConverter();
1672: else
1673: uninstallTabsToSpacesConverter();
1674: return;
1675: }
1676:
1677: if (PreferenceConstants.EDITOR_SMART_TAB.equals(p)) {
1678: if (getPreferenceStore().getBoolean(
1679: PreferenceConstants.EDITOR_SMART_TAB)) {
1680: setActionActivationCode(
1681: "IndentOnTab", '\t', -1, SWT.NONE); //$NON-NLS-1$
1682: } else {
1683: removeActionActivationCode("IndentOnTab"); //$NON-NLS-1$
1684: }
1685: }
1686:
1687: IContentAssistant c = asv.getContentAssistant();
1688: if (c instanceof ContentAssistant)
1689: ContentAssistPreference.changeConfiguration(
1690: (ContentAssistant) c, getPreferenceStore(),
1691: event);
1692:
1693: if (CODE_FORMATTER_TAB_SIZE.equals(p)
1694: && isTabsToSpacesConversionEnabled()) {
1695: uninstallTabsToSpacesConverter();
1696: installTabsToSpacesConverter();
1697: }
1698: }
1699:
1700: } finally {
1701: super .handlePreferenceStoreChanged(event);
1702: }
1703: }
1704:
1705: /*
1706: * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#createJavaSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, org.eclipse.jface.text.source.IOverviewRuler, boolean, int)
1707: */
1708: protected ISourceViewer createJavaSourceViewer(Composite parent,
1709: IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
1710: boolean isOverviewRulerVisible, int styles,
1711: IPreferenceStore store) {
1712: return new AdaptedSourceViewer(parent, verticalRuler,
1713: overviewRuler, isOverviewRulerVisible, styles, store);
1714: }
1715:
1716: /*
1717: * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
1718: * @since 3.0
1719: */
1720: public void aboutToBeReconciled() {
1721:
1722: // Notify AST provider
1723: JavaPlugin.getDefault().getASTProvider().aboutToBeReconciled(
1724: getInputJavaElement());
1725:
1726: // Notify listeners
1727: Object[] listeners = fReconcilingListeners.getListeners();
1728: for (int i = 0, length = listeners.length; i < length; ++i)
1729: ((IJavaReconcilingListener) listeners[i])
1730: .aboutToBeReconciled();
1731: }
1732:
1733: /*
1734: * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit, boolean, IProgressMonitor)
1735: * @since 3.0
1736: */
1737: public void reconciled(CompilationUnit ast, boolean forced,
1738: IProgressMonitor progressMonitor) {
1739:
1740: // see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=58245
1741: JavaPlugin javaPlugin = JavaPlugin.getDefault();
1742: if (javaPlugin == null)
1743: return;
1744:
1745: // Always notify AST provider
1746: javaPlugin.getASTProvider().reconciled(ast,
1747: getInputJavaElement(), progressMonitor);
1748:
1749: // Notify listeners
1750: Object[] listeners = fReconcilingListeners.getListeners();
1751: for (int i = 0, length = listeners.length; i < length; ++i)
1752: ((IJavaReconcilingListener) listeners[i]).reconciled(ast,
1753: forced, progressMonitor);
1754:
1755: // Update Java Outline page selection
1756: if (!forced && !progressMonitor.isCanceled()) {
1757: Shell shell = getSite().getShell();
1758: if (shell != null && !shell.isDisposed()) {
1759: shell.getDisplay().asyncExec(new Runnable() {
1760: public void run() {
1761: selectionChanged();
1762: }
1763: });
1764: }
1765: }
1766: }
1767:
1768: /**
1769: * Tells whether this is the active editor in the active page.
1770: *
1771: * @return <code>true</code> if this is the active editor in the active page
1772: * @see IWorkbenchPage#getActiveEditor
1773: */
1774: protected final boolean isActiveEditor() {
1775: IWorkbenchWindow window = getSite().getWorkbenchWindow();
1776: IWorkbenchPage page = window.getActivePage();
1777: if (page == null)
1778: return false;
1779: IEditorPart activeEditor = page.getActiveEditor();
1780: return activeEditor != null && activeEditor.equals(this );
1781: }
1782:
1783: /**
1784: * Adds the given listener.
1785: * Has no effect if an identical listener was not already registered.
1786: *
1787: * @param listener The reconcile listener to be added
1788: * @since 3.0
1789: */
1790: final void addReconcileListener(IJavaReconcilingListener listener) {
1791: synchronized (fReconcilingListeners) {
1792: fReconcilingListeners.add(listener);
1793: }
1794: }
1795:
1796: /**
1797: * Removes the given listener.
1798: * Has no effect if an identical listener was not already registered.
1799: *
1800: * @param listener the reconcile listener to be removed
1801: * @since 3.0
1802: */
1803: final void removeReconcileListener(IJavaReconcilingListener listener) {
1804: synchronized (fReconcilingListeners) {
1805: fReconcilingListeners.remove(listener);
1806: }
1807: }
1808:
1809: protected void updateStateDependentActions() {
1810: super .updateStateDependentActions();
1811: fGenerateActionGroup.editorStateChanged();
1812: }
1813:
1814: /*
1815: * @see AbstractTextEditor#rememberSelection()
1816: */
1817: protected void rememberSelection() {
1818: fRememberedSelection.remember();
1819: }
1820:
1821: /*
1822: * @see AbstractTextEditor#restoreSelection()
1823: */
1824: protected void restoreSelection() {
1825: fRememberedSelection.restore();
1826: }
1827:
1828: /*
1829: * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1830: */
1831: protected boolean canHandleMove(IEditorInput originalElement,
1832: IEditorInput movedElement) {
1833:
1834: String oldExtension = ""; //$NON-NLS-1$
1835: if (originalElement instanceof IFileEditorInput) {
1836: IFile file = ((IFileEditorInput) originalElement).getFile();
1837: if (file != null) {
1838: String ext = file.getFileExtension();
1839: if (ext != null)
1840: oldExtension = ext;
1841: }
1842: }
1843:
1844: String newExtension = ""; //$NON-NLS-1$
1845: if (movedElement instanceof IFileEditorInput) {
1846: IFile file = ((IFileEditorInput) movedElement).getFile();
1847: if (file != null)
1848: newExtension = file.getFileExtension();
1849: }
1850:
1851: return oldExtension.equals(newExtension);
1852: }
1853:
1854: /*
1855: * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#getAdapter(java.lang.Class)
1856: */
1857: public Object getAdapter(Class required) {
1858: if (SmartBackspaceManager.class.equals(required)) {
1859: if (getSourceViewer() instanceof JavaSourceViewer) {
1860: return ((JavaSourceViewer) getSourceViewer())
1861: .getBackspaceManager();
1862: }
1863: }
1864:
1865: return super .getAdapter(required);
1866: }
1867:
1868: /**
1869: * Returns the mutex for the reconciler. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
1870: * for a description of the problem.
1871: * <p>
1872: * XXX remove once the underlying problem (https://bugs.eclipse.org/bugs/show_bug.cgi?id=66176) is solved.
1873: * </p>
1874: * @return the lock reconcilers may use to synchronize on
1875: */
1876: public Object getReconcilerLock() {
1877: return fReconcilerLock;
1878: }
1879:
1880: /*
1881: * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#createNavigationActions()
1882: */
1883: protected void createNavigationActions() {
1884: super .createNavigationActions();
1885:
1886: final StyledText textWidget = getSourceViewer().getTextWidget();
1887:
1888: IAction action = new DeletePreviousSubWordAction();
1889: action
1890: .setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD);
1891: setAction(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD,
1892: action);
1893: textWidget.setKeyBinding(SWT.CTRL | SWT.BS, SWT.NULL);
1894: markAsStateDependentAction(
1895: ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD,
1896: true);
1897:
1898: action = new DeleteNextSubWordAction();
1899: action
1900: .setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD);
1901: setAction(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD,
1902: action);
1903: textWidget.setKeyBinding(SWT.CTRL | SWT.DEL, SWT.NULL);
1904: markAsStateDependentAction(
1905: ITextEditorActionDefinitionIds.DELETE_NEXT_WORD, true);
1906: }
1907:
1908: }
|