X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java index 2d0b71d..ed60680 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java @@ -11,11 +11,15 @@ Contributors: IBM Corporation - Initial implementation Klaus Hartlage - www.eclipseproject.de **********************************************************************/ +import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; +import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher; +import net.sourceforge.phpdt.ui.actions.GenerateActionGroup; +import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction; import net.sourceforge.phpeclipse.IPreferenceConstants; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner; -import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor; import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.Action; @@ -25,7 +29,11 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension3; +import org.eclipse.jface.text.Region; import org.eclipse.jface.text.source.AnnotationRulerColumn; import org.eclipse.jface.text.source.CompositeRuler; import org.eclipse.jface.text.source.ISourceViewer; @@ -34,32 +42,79 @@ import org.eclipse.jface.text.source.IVerticalRulerColumn; import org.eclipse.jface.text.source.LineNumberRulerColumn; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.texteditor.ContentAssistAction; import org.eclipse.ui.texteditor.DefaultRangeIndicator; +import org.eclipse.ui.texteditor.IEditorStatusLine; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; /** * PHP specific text editor. */ -public class PHPEditor extends TextEditor { +public class PHPEditor extends TextEditor { +// extends StatusTextEditor implements IViewPartInputProvider { // extends TextEditor { - protected PHPActionGroup actionGroup; + // protected PHPActionGroup fActionGroups; /** The outline page */ private PHPContentOutlinePage fOutlinePage; private IPreferenceStore phpPrefStore; + /** The editor's bracket matcher */ + private PHPPairMatcher fBracketMatcher; /** The line number ruler column */ private LineNumberRulerColumn fLineNumberRulerColumn; + protected CompositeActionGroup fActionGroups; + /** The standard action groups added to the menu */ + private GenerateActionGroup fGenerateActionGroup; + private CompositeActionGroup fContextMenuGroup; /** * Default constructor. */ public PHPEditor() { super(); + setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$ + setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$ + } + // + // /** + // * @see IMember#getCompilationUnit() + // */ + // public ICompilationUnit getCompilationUnit() { + // return this; + // } + // /** + // * @see org.phpeclipse.phpdt.internal.compiler.env.ICompilationUnit#getContents() + // */ + // public char[] getContents() { + // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput()); + // + // return doc.get().toCharArray(); + // } + + /** + * Returns this document's complete text. + * + * @return the document's complete text + */ + public String get() { + IDocument doc = + this.getDocumentProvider().getDocument(this.getEditorInput()); + return doc.get(); + } + + /** + * Returns the standard action group of this editor. + */ + protected ActionGroup getActionGroup() { + return fActionGroups; } public PHPContentOutlinePage getfOutlinePage() { @@ -72,13 +127,20 @@ public class PHPEditor extends TextEditor { */ protected void createActions() { super.createActions(); - setAction( - "ContentAssistProposal", - new TextOperationAction( - PHPEditorMessages.getResourceBundle(), - "ContentAssistProposal.", - this, - ISourceViewer.CONTENTASSIST_PROPOSALS)); + + Action action; + // setAction( + // "ContentAssistProposal", + // new TextOperationAction( + // PHPEditorMessages.getResourceBundle(), + // "ContentAssistProposal.", + // this, + // ISourceViewer.CONTENTASSIST_PROPOSALS)); + action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$ + action.setActionDefinitionId( + PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + setAction("ContentAssistProposal", action); //$NON-NLS-1$ + setAction( "ContentAssistTip", new TextOperationAction( @@ -87,19 +149,49 @@ public class PHPEditor extends TextEditor { this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION)); - Action action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); + action = + new TextOperationAction( + PHPEditorMessages.getResourceBundle(), + "Comment.", + this, + ITextOperationTarget.PREFIX); action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT); setAction("Comment", action); - action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); + action = + new TextOperationAction( + PHPEditorMessages.getResourceBundle(), + "Uncomment.", + this, + ITextOperationTarget.STRIP_PREFIX); action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT); setAction("Uncomment", action); - actionGroup = new PHPActionGroup(this, ITextEditorActionConstants.GROUP_EDIT); + action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$ + action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT); + setAction("Format", action); //$NON-NLS-1$ + markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$ markAsStateDependentAction("Comment", true); //$NON-NLS-1$ markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$ - + markAsStateDependentAction("Format", true); //$NON-NLS-1$ + + action = new GotoMatchingBracketAction(this); + action.setActionDefinitionId( + PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET); + setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action); + + fGenerateActionGroup = + new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT); + + fActionGroups = + new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup }); + + // We have to keep the context menu group separate to have better control over positioning + fContextMenuGroup = + new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup }); + // rg, + // new LocalHistoryActionGroup(this, ITextEditorActionConstants.GROUP_EDIT)}); } /** The PHPEditor implementation of this @@ -110,6 +202,10 @@ public class PHPEditor extends TextEditor { PHPEditorEnvironment.disconnect(this); if (fOutlinePage != null) fOutlinePage.setInput(null); + + if (fActionGroups != null) + fActionGroups.dispose(); + super.dispose(); } @@ -160,15 +256,32 @@ public class PHPEditor extends TextEditor { fOutlinePage.setInput(input); } + /* + * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput() + */ +// public Object getViewPartInput() { +// return getEditorInput().getAdapter(IFile.class); +// } + /** The PHPEditor implementation of this * AbstractTextEditor method adds any * PHPEditor specific entries. */ public void editorContextMenuAboutToShow(MenuManager menu) { super.editorContextMenuAboutToShow(menu); - // addAction(menu, "ContentAssistProposal"); //$NON-NLS-1$ - // addAction(menu, "ContentAssistTip"); //$NON-NLS-1$ - actionGroup.fillContextMenu(menu); + + addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$ + + ActionContext context = + new ActionContext(getSelectionProvider().getSelection()); + fContextMenuGroup.setContext(context); + fContextMenuGroup.fillContextMenu(menu); + fContextMenuGroup.setContext(null); + } + + protected void updateStateDependentActions() { + super.updateStateDependentActions(); + fGenerateActionGroup.editorStateChanged(); } /** The PHPEditor implementation of this @@ -188,38 +301,38 @@ public class PHPEditor extends TextEditor { return super.getAdapter(required); } -// public void openContextHelp() { -// IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput()); -// ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection(); -// int pos = selection.getOffset(); -// String word = getFunctionName(doc, pos); -// openContextHelp(word); -// } -// -// private void openContextHelp(String word) { -// open(word); -// } -// -// public static void open(String word) { -// IHelp help = WorkbenchHelp.getHelpSupport(); -// if (help != null) { -// IHelpResource helpResource = new PHPFunctionHelpResource(word); -// WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource); -// } else { -// // showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$ -// } -// } - - private String getFunctionName(IDocument doc, int pos) { - Point word = PHPWordExtractor.findWord(doc, pos); - if (word != null) { - try { - return doc.get(word.x, word.y).replace('_', '-'); - } catch (BadLocationException e) { - } - } - return ""; - } + // public void openContextHelp() { + // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput()); + // ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection(); + // int pos = selection.getOffset(); + // String word = getFunctionName(doc, pos); + // openContextHelp(word); + // } + // + // private void openContextHelp(String word) { + // open(word); + // } + // + // public static void open(String word) { + // IHelp help = WorkbenchHelp.getHelpSupport(); + // if (help != null) { + // IHelpResource helpResource = new PHPFunctionHelpResource(word); + // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource); + // } else { + // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$ + // } + // } + + // private String getFunctionName(IDocument doc, int pos) { + // Point word = PHPWordExtractor.findWord(doc, pos); + // if (word != null) { + // try { + // return doc.get(word.x, word.y).replace('_', '-'); + // } catch (BadLocationException e) { + // } + // } + // return ""; + // } /* * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent) @@ -291,7 +404,10 @@ public class PHPEditor extends TextEditor { IVerticalRuler v = getVerticalRuler(); if (v instanceof CompositeRuler) { CompositeRuler c = (CompositeRuler) v; - c.removeDecorator(1); + try { + c.removeDecorator(1); + } catch (Throwable e) { + } } } @@ -309,20 +425,36 @@ public class PHPEditor extends TextEditor { // foreground color if (phpPrefStore.contains(IPreferenceConstants.LINE_NUMBER_COLOR)) { if (phpPrefStore.isDefault(IPreferenceConstants.LINE_NUMBER_COLOR)) - rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR); + rgb = + PreferenceConverter.getDefaultColor( + phpPrefStore, + IPreferenceConstants.LINE_NUMBER_COLOR); else - rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR); + rgb = + PreferenceConverter.getColor( + phpPrefStore, + IPreferenceConstants.LINE_NUMBER_COLOR); } rulerColumn.setForeground(manager.getColor(rgb)); rgb = null; // background color - if (!phpPrefStore.getBoolean(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) { - if (phpPrefStore.contains(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) { - if (phpPrefStore.isDefault(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) - rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND); + if (!phpPrefStore + .getBoolean( + IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) { + if (phpPrefStore + .contains(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) { + if (phpPrefStore + .isDefault(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) + rgb = + PreferenceConverter.getDefaultColor( + phpPrefStore, + IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND); else - rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND); + rgb = + PreferenceConverter.getColor( + phpPrefStore, + IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND); } rulerColumn.setBackground(manager.getColor(rgb)); } @@ -351,12 +483,12 @@ public class PHPEditor extends TextEditor { } /* (non-Javadoc) - * Method declared on AbstractTextEditor + * Method declared on TextEditor */ protected void initializeEditor() { PHPEditorEnvironment.connect(this); - setSourceViewerConfiguration(new PHPSourceViewerConfiguration()); + setSourceViewerConfiguration(new PHPSourceViewerConfiguration(this)); setRangeIndicator(new DefaultRangeIndicator()); setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$ setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$ @@ -384,4 +516,126 @@ public class PHPEditor extends TextEditor { } }); } + + private static IRegion getSignedSelection(ITextViewer viewer) { + + StyledText text = viewer.getTextWidget(); + int caretOffset = text.getCaretOffset(); + Point selection = text.getSelection(); + + // caret left + int offset, length; + if (caretOffset == selection.x) { + offset = selection.y; + length = selection.x - selection.y; + + // caret right + } else { + offset = selection.x; + length = selection.y - selection.x; + } + + return new Region(offset, length); + } + + private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' }; + + private static boolean isBracket(char character) { + for (int i = 0; i != BRACKETS.length; ++i) + if (character == BRACKETS[i]) + return true; + return false; + } + + private static boolean isSurroundedByBrackets( + IDocument document, + int offset) { + if (offset == 0 || offset == document.getLength()) + return false; + + try { + return isBracket(document.getChar(offset - 1)) + && isBracket(document.getChar(offset)); + + } catch (BadLocationException e) { + return false; + } + } + /** + * Jumps to the matching bracket. + */ + public void gotoMatchingBracket() { + + if (fBracketMatcher == null) + fBracketMatcher = new PHPPairMatcher(BRACKETS); + + ISourceViewer sourceViewer = getSourceViewer(); + IDocument document = sourceViewer.getDocument(); + if (document == null) + return; + + IRegion selection = getSignedSelection(sourceViewer); + + int selectionLength = Math.abs(selection.getLength()); + if (selectionLength > 1) { + setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$ + sourceViewer.getTextWidget().getDisplay().beep(); + return; + } + + // #26314 + int sourceCaretOffset = selection.getOffset() + selection.getLength(); + if (isSurroundedByBrackets(document, sourceCaretOffset)) + sourceCaretOffset -= selection.getLength(); + + IRegion region = fBracketMatcher.match(document, sourceCaretOffset); + if (region == null) { + setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$ + sourceViewer.getTextWidget().getDisplay().beep(); + return; + } + + int offset = region.getOffset(); + int length = region.getLength(); + + if (length < 1) + return; + + int anchor = fBracketMatcher.getAnchor(); + int targetOffset = + (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1; + + boolean visible = false; + if (sourceViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer; + visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1); + } else { + IRegion visibleRegion = sourceViewer.getVisibleRegion(); + visible = + (targetOffset >= visibleRegion.getOffset() + && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength()); + } + + if (!visible) { + setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$ + sourceViewer.getTextWidget().getDisplay().beep(); + return; + } + + if (selection.getLength() < 0) + targetOffset -= selection.getLength(); + + sourceViewer.setSelectedRange(targetOffset, selection.getLength()); + sourceViewer.revealRange(targetOffset, selection.getLength()); + } + /** + * Ses the given message as error message to this editor's status line. + * @param msg message to be set + */ + protected void setStatusLineErrorMessage(String msg) { + IEditorStatusLine statusLine = + (IEditorStatusLine) getAdapter(IEditorStatusLine.class); + if (statusLine != null) + statusLine.setMessage(true, msg, null); + } }