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 d7b5126..585993d 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java @@ -9,8 +9,12 @@ package net.sourceforge.phpeclipse.phpeditor; Contributors: IBM Corporation - Initial implementation - Klaus Hartlage - www.eclipseproject.de + www.phpeclipse.de **********************************************************************/ +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.BreakIterator; +import java.text.CharacterIterator; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -29,21 +33,29 @@ import net.sourceforge.phpdt.core.ISourceRange; import net.sourceforge.phpdt.core.ISourceReference; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup; +import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter; import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl; +import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator; import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter; import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions; +import net.sourceforge.phpdt.internal.ui.text.JavaWordIterator; import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher; import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter; +import net.sourceforge.phpdt.internal.ui.text.java.JavaExpandHover; import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider; import net.sourceforge.phpdt.ui.IContextMenuConstants; import net.sourceforge.phpdt.ui.JavaUI; import net.sourceforge.phpdt.ui.PreferenceConstants; import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction; +import net.sourceforge.phpdt.ui.actions.OpenEditorActionGroup; import net.sourceforge.phpdt.ui.text.JavaTextTools; +import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration; import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider; import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.ui.editor.ShowExternalPreviewAction; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; @@ -68,25 +80,33 @@ import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ISynchronizable; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextPresentationListener; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension2; import org.eclipse.jface.text.ITextViewerExtension3; +import org.eclipse.jface.text.ITextViewerExtension4; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextPresentation; import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.information.IInformationProvider; import org.eclipse.jface.text.information.InformationPresenter; import org.eclipse.jface.text.reconciler.IReconciler; import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationRulerColumn; +import org.eclipse.jface.text.source.CompositeRuler; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IAnnotationModelExtension; import org.eclipse.jface.text.source.IOverviewRuler; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.ISourceViewerExtension2; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.OverviewRuler; import org.eclipse.jface.text.source.SourceViewerConfiguration; @@ -95,6 +115,8 @@ import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.ListenerList; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IPostSelectionProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; @@ -105,6 +127,7 @@ import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BidiSegmentEvent; import org.eclipse.swt.custom.BidiSegmentListener; +import org.eclipse.swt.custom.ST; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.FocusEvent; @@ -129,6 +152,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPartService; +import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; @@ -142,13 +166,15 @@ import org.eclipse.ui.part.IShowInTargetList; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.ChainedPreferenceStore; -import org.eclipse.ui.texteditor.DefaultRangeIndicator; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IEditorStatusLine; import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; +import org.eclipse.ui.texteditor.IUpdate; import org.eclipse.ui.texteditor.MarkerAnnotation; -import org.eclipse.ui.texteditor.ResourceAction; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.TextEditorAction; +import org.eclipse.ui.texteditor.TextNavigationAction; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; @@ -224,37 +250,36 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I /** * "Smart" runnable for updating the outline page's selection. */ - class OutlinePageSelectionUpdater implements Runnable { - - /** Has the runnable already been posted? */ - private boolean fPosted = false; - - public OutlinePageSelectionUpdater() { - } - - /* - * @see Runnable#run() - */ - public void run() { - synchronizeOutlinePageSelection(); - fPosted = false; - } - - /** - * Posts this runnable into the event queue. - */ - public void post() { - if (fPosted) - return; - - Shell shell = getSite().getShell(); - if (shell != null & !shell.isDisposed()) { - fPosted = true; - shell.getDisplay().asyncExec(this); - } - } - }; - + // class OutlinePageSelectionUpdater implements Runnable { + // + // /** Has the runnable already been posted? */ + // private boolean fPosted = false; + // + // public OutlinePageSelectionUpdater() { + // } + // + // /* + // * @see Runnable#run() + // */ + // public void run() { + // synchronizeOutlinePageSelection(); + // fPosted = false; + // } + // + // /** + // * Posts this runnable into the event queue. + // */ + // public void post() { + // if (fPosted) + // return; + // + // Shell shell = getSite().getShell(); + // if (shell != null & !shell.isDisposed()) { + // fPosted = true; + // shell.getDisplay().asyncExec(this); + // } + // } + // }; class SelectionChangedListener implements ISelectionChangedListener { public void selectionChanged(SelectionChangedEvent event) { doSelectionChanged(event); @@ -651,8 +676,672 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I /* * Link mode. */ + // class MouseClickListener implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener, + // IPropertyChangeListener, IDocumentListener, ITextInputListener { + // + // /** The session is active. */ + // private boolean fActive; + // + // /** The currently active style range. */ + // private IRegion fActiveRegion; + // + // /** The currently active style range as position. */ + // private Position fRememberedPosition; + // + // /** The hand cursor. */ + // private Cursor fCursor; + // + // /** The link color. */ + // private Color fColor; + // + // /** The key modifier mask. */ + // private int fKeyModifierMask; + // + // public void deactivate() { + // deactivate(false); + // } + // + // public void deactivate(boolean redrawAll) { + // if (!fActive) + // return; + // + // repairRepresentation(redrawAll); + // fActive = false; + // } + // + // public void install() { + // + // ISourceViewer sourceViewer = getSourceViewer(); + // if (sourceViewer == null) + // return; + // + // StyledText text = sourceViewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // + // updateColor(sourceViewer); + // + // sourceViewer.addTextInputListener(this); + // + // IDocument document = sourceViewer.getDocument(); + // if (document != null) + // document.addDocumentListener(this); + // + // text.addKeyListener(this); + // text.addMouseListener(this); + // text.addMouseMoveListener(this); + // text.addFocusListener(this); + // text.addPaintListener(this); + // + // updateKeyModifierMask(); + // + // IPreferenceStore preferenceStore = getPreferenceStore(); + // preferenceStore.addPropertyChangeListener(this); + // } + // + // private void updateKeyModifierMask() { + // String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER); + // fKeyModifierMask = computeStateMask(modifiers); + // if (fKeyModifierMask == -1) { + // // Fallback to stored state mask + // fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK); + // } + // ; + // } + // + // private int computeStateMask(String modifiers) { + // if (modifiers == null) + // return -1; + // + // if (modifiers.length() == 0) + // return SWT.NONE; + // + // int stateMask = 0; + // StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$ + // while (modifierTokenizer.hasMoreTokens()) { + // int modifier = EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken()); + // if (modifier == 0 || (stateMask & modifier) == modifier) + // return -1; + // stateMask = stateMask | modifier; + // } + // return stateMask; + // } + // + // public void uninstall() { + // + // if (fColor != null) { + // fColor.dispose(); + // fColor = null; + // } + // + // if (fCursor != null) { + // fCursor.dispose(); + // fCursor = null; + // } + // + // ISourceViewer sourceViewer = getSourceViewer(); + // if (sourceViewer == null) + // return; + // + // sourceViewer.removeTextInputListener(this); + // + // IDocument document = sourceViewer.getDocument(); + // if (document != null) + // document.removeDocumentListener(this); + // + // IPreferenceStore preferenceStore = getPreferenceStore(); + // if (preferenceStore != null) + // preferenceStore.removePropertyChangeListener(this); + // + // StyledText text = sourceViewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // + // text.removeKeyListener(this); + // text.removeMouseListener(this); + // text.removeMouseMoveListener(this); + // text.removeFocusListener(this); + // text.removePaintListener(this); + // } + // + // /* + // * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + // */ + // public void propertyChange(PropertyChangeEvent event) { + // if (event.getProperty().equals(PHPEditor.LINK_COLOR)) { + // ISourceViewer viewer = getSourceViewer(); + // if (viewer != null) + // updateColor(viewer); + // } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) { + // updateKeyModifierMask(); + // } + // } + // + // private void updateColor(ISourceViewer viewer) { + // if (fColor != null) + // fColor.dispose(); + // + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // + // Display display = text.getDisplay(); + // fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display); + // } + // + // /** + // * Creates a color from the information stored in the given preference store. Returns null if there is no such + // * information available. + // */ + // private Color createColor(IPreferenceStore store, String key, Display display) { + // + // RGB rgb = null; + // + // if (store.contains(key)) { + // + // if (store.isDefault(key)) + // rgb = PreferenceConverter.getDefaultColor(store, key); + // else + // rgb = PreferenceConverter.getColor(store, key); + // + // if (rgb != null) + // return new Color(display, rgb); + // } + // + // return null; + // } + // + // private void repairRepresentation() { + // repairRepresentation(false); + // } + // + // private void repairRepresentation(boolean redrawAll) { + // + // if (fActiveRegion == null) + // return; + // + // ISourceViewer viewer = getSourceViewer(); + // if (viewer != null) { + // resetCursor(viewer); + // + // int offset = fActiveRegion.getOffset(); + // int length = fActiveRegion.getLength(); + // + // // remove style + // if (!redrawAll && viewer instanceof ITextViewerExtension2) + // ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length); + // else + // viewer.invalidateTextPresentation(); + // + // // remove underline + // if (viewer instanceof ITextViewerExtension3) { + // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + // offset = extension.modelOffset2WidgetOffset(offset); + // } else { + // offset -= viewer.getVisibleRegion().getOffset(); + // } + // + // StyledText text = viewer.getTextWidget(); + // try { + // text.redrawRange(offset, length, true); + // } catch (IllegalArgumentException x) { + // PHPeclipsePlugin.log(x); + // } + // } + // + // fActiveRegion = null; + // } + // + // // will eventually be replaced by a method provided by jdt.core + // private IRegion selectWord(IDocument document, int anchor) { + // + // try { + // int offset = anchor; + // char c; + // + // while (offset >= 0) { + // c = document.getChar(offset); + // if (!Scanner.isPHPIdentifierPart(c)) + // break; + // --offset; + // } + // + // int start = offset; + // + // offset = anchor; + // int length = document.getLength(); + // + // while (offset < length) { + // c = document.getChar(offset); + // if (!Scanner.isPHPIdentifierPart(c)) + // break; + // ++offset; + // } + // + // int end = offset; + // + // if (start == end) + // return new Region(start, 0); + // else + // return new Region(start + 1, end - start - 1); + // + // } catch (BadLocationException x) { + // return null; + // } + // } + // + // IRegion getCurrentTextRegion(ISourceViewer viewer) { + // + // int offset = getCurrentTextOffset(viewer); + // if (offset == -1) + // return null; + // + // return null; + // // IJavaElement input= SelectionConverter.getInput(PHPEditor.this); + // // if (input == null) + // // return null; + // // + // // try { + // // + // // IJavaElement[] elements= null; + // // synchronized (input) { + // // elements= ((ICodeAssist) input).codeSelect(offset, 0); + // // } + // // + // // if (elements == null || elements.length == 0) + // // return null; + // // + // // return selectWord(viewer.getDocument(), offset); + // // + // // } catch (JavaModelException e) { + // // return null; + // // } + // } + // + // private int getCurrentTextOffset(ISourceViewer viewer) { + // + // try { + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return -1; + // + // Display display = text.getDisplay(); + // Point absolutePosition = display.getCursorLocation(); + // Point relativePosition = text.toControl(absolutePosition); + // + // int widgetOffset = text.getOffsetAtLocation(relativePosition); + // if (viewer instanceof ITextViewerExtension3) { + // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + // return extension.widgetOffset2ModelOffset(widgetOffset); + // } else { + // return widgetOffset + viewer.getVisibleRegion().getOffset(); + // } + // + // } catch (IllegalArgumentException e) { + // return -1; + // } + // } + // + // private void highlightRegion(ISourceViewer viewer, IRegion region) { + // + // if (region.equals(fActiveRegion)) + // return; + // + // repairRepresentation(); + // + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // + // // highlight region + // int offset = 0; + // int length = 0; + // + // if (viewer instanceof ITextViewerExtension3) { + // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + // IRegion widgetRange = extension.modelRange2WidgetRange(region); + // if (widgetRange == null) + // return; + // + // offset = widgetRange.getOffset(); + // length = widgetRange.getLength(); + // + // } else { + // offset = region.getOffset() - viewer.getVisibleRegion().getOffset(); + // length = region.getLength(); + // } + // + // StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset); + // Color foregroundColor = fColor; + // Color backgroundColor = oldStyleRange == null ? text.getBackground() : oldStyleRange.background; + // StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor); + // text.setStyleRange(styleRange); + // + // // underline + // text.redrawRange(offset, length, true); + // + // fActiveRegion = region; + // } + // + // private void activateCursor(ISourceViewer viewer) { + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // Display display = text.getDisplay(); + // if (fCursor == null) + // fCursor = new Cursor(display, SWT.CURSOR_HAND); + // text.setCursor(fCursor); + // } + // + // private void resetCursor(ISourceViewer viewer) { + // StyledText text = viewer.getTextWidget(); + // if (text != null && !text.isDisposed()) + // text.setCursor(null); + // + // if (fCursor != null) { + // fCursor.dispose(); + // fCursor = null; + // } + // } + // + // /* + // * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) + // */ + // public void keyPressed(KeyEvent event) { + // + // if (fActive) { + // deactivate(); + // return; + // } + // + // if (event.keyCode != fKeyModifierMask) { + // deactivate(); + // return; + // } + // + // fActive = true; + // + // // removed for #25871 + // // + // // ISourceViewer viewer= getSourceViewer(); + // // if (viewer == null) + // // return; + // // + // // IRegion region= getCurrentTextRegion(viewer); + // // if (region == null) + // // return; + // // + // // highlightRegion(viewer, region); + // // activateCursor(viewer); + // } + // + // /* + // * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) + // */ + // public void keyReleased(KeyEvent event) { + // + // if (!fActive) + // return; + // + // deactivate(); + // } + // + // /* + // * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent) + // */ + // public void mouseDoubleClick(MouseEvent e) { + // } + // + // /* + // * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent) + // */ + // public void mouseDown(MouseEvent event) { + // + // if (!fActive) + // return; + // + // if (event.stateMask != fKeyModifierMask) { + // deactivate(); + // return; + // } + // + // if (event.button != 1) { + // deactivate(); + // return; + // } + // } + // + // /* + // * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent) + // */ + // public void mouseUp(MouseEvent e) { + // + // if (!fActive) + // return; + // + // if (e.button != 1) { + // deactivate(); + // return; + // } + // + // boolean wasActive = fCursor != null; + // + // deactivate(); + // + // if (wasActive) { + // IAction action = getAction("OpenEditor"); //$NON-NLS-1$ + // if (action != null) + // action.run(); + // } + // } + // + // /* + // * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent) + // */ + // public void mouseMove(MouseEvent event) { + // + // if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) { + // deactivate(); + // return; + // } + // + // if (!fActive) { + // if (event.stateMask != fKeyModifierMask) + // return; + // // modifier was already pressed + // fActive = true; + // } + // + // ISourceViewer viewer = getSourceViewer(); + // if (viewer == null) { + // deactivate(); + // return; + // } + // + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) { + // deactivate(); + // return; + // } + // + // if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0) { + // deactivate(); + // return; + // } + // + // IRegion region = getCurrentTextRegion(viewer); + // if (region == null || region.getLength() == 0) { + // repairRepresentation(); + // return; + // } + // + // highlightRegion(viewer, region); + // activateCursor(viewer); + // } + // + // /* + // * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent) + // */ + // public void focusGained(FocusEvent e) { + // } + // + // /* + // * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) + // */ + // public void focusLost(FocusEvent event) { + // deactivate(); + // } + // + // /* + // * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) + // */ + // public void documentAboutToBeChanged(DocumentEvent event) { + // if (fActive && fActiveRegion != null) { + // fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength()); + // try { + // event.getDocument().addPosition(fRememberedPosition); + // } catch (BadLocationException x) { + // fRememberedPosition = null; + // } + // } + // } + // + // /* + // * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) + // */ + // public void documentChanged(DocumentEvent event) { + // if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) { + // event.getDocument().removePosition(fRememberedPosition); + // fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength()); + // } + // fRememberedPosition = null; + // + // ISourceViewer viewer = getSourceViewer(); + // if (viewer != null) { + // StyledText widget = viewer.getTextWidget(); + // if (widget != null && !widget.isDisposed()) { + // widget.getDisplay().asyncExec(new Runnable() { + // public void run() { + // deactivate(); + // } + // }); + // } + // } + // } + // + // /* + // * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, + // * org.eclipse.jface.text.IDocument) + // */ + // public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + // if (oldInput == null) + // return; + // deactivate(); + // oldInput.removeDocumentListener(this); + // } + // + // /* + // * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, + // * org.eclipse.jface.text.IDocument) + // */ + // public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + // if (newInput == null) + // return; + // newInput.addDocumentListener(this); + // } + // + // /* + // * @see PaintListener#paintControl(PaintEvent) + // */ + // public void paintControl(PaintEvent event) { + // if (fActiveRegion == null) + // return; + // + // ISourceViewer viewer = getSourceViewer(); + // if (viewer == null) + // return; + // + // StyledText text = viewer.getTextWidget(); + // if (text == null || text.isDisposed()) + // return; + // + // int offset = 0; + // int length = 0; + // + // if (viewer instanceof ITextViewerExtension3) { + // + // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + // IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length)); + // if (widgetRange == null) + // return; + // + // offset = widgetRange.getOffset(); + // length = widgetRange.getLength(); + // + // } else { + // + // IRegion region = viewer.getVisibleRegion(); + // if (!includes(region, fActiveRegion)) + // return; + // + // offset = fActiveRegion.getOffset() - region.getOffset(); + // length = fActiveRegion.getLength(); + // } + // + // // support for bidi + // Point minLocation = getMinimumLocation(text, offset, length); + // Point maxLocation = getMaximumLocation(text, offset, length); + // + // int x1 = minLocation.x; + // int x2 = minLocation.x + maxLocation.x - minLocation.x - 1; + // int y = minLocation.y + text.getLineHeight() - 1; + // + // GC gc = event.gc; + // if (fColor != null && !fColor.isDisposed()) + // gc.setForeground(fColor); + // gc.drawLine(x1, y, x2, y); + // } + // + // private boolean includes(IRegion region, IRegion position) { + // return position.getOffset() >= region.getOffset() + // && position.getOffset() + position.getLength() <= region.getOffset() + region.getLength(); + // } + // + // private Point getMinimumLocation(StyledText text, int offset, int length) { + // Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + // + // for (int i = 0; i <= length; i++) { + // Point location = text.getLocationAtOffset(offset + i); + // + // if (location.x < minLocation.x) + // minLocation.x = location.x; + // if (location.y < minLocation.y) + // minLocation.y = location.y; + // } + // + // return minLocation; + // } + // + // private Point getMaximumLocation(StyledText text, int offset, int length) { + // Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + // + // for (int i = 0; i <= length; i++) { + // Point location = text.getLocationAtOffset(offset + i); + // + // if (location.x > maxLocation.x) + // maxLocation.x = location.x; + // if (location.y > maxLocation.y) + // maxLocation.y = location.y; + // } + // + // return maxLocation; + // } + // }; + /* + * Link mode. + */ class MouseClickListener implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener, - IPropertyChangeListener, IDocumentListener, ITextInputListener { + IPropertyChangeListener, IDocumentListener, ITextInputListener, ITextPresentationListener { /** The session is active. */ private boolean fActive; @@ -685,7 +1374,6 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } public void install() { - ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer == null) return; @@ -708,6 +1396,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I text.addFocusListener(this); text.addPaintListener(this); + ((ITextViewerExtension4) sourceViewer).addTextPresentationListener(this); + updateKeyModifierMask(); IPreferenceStore preferenceStore = getPreferenceStore(); @@ -718,10 +1408,9 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER); fKeyModifierMask = computeStateMask(modifiers); if (fKeyModifierMask == -1) { - // Fallback to stored state mask + // Fall back to stored state mask fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK); } - ; } private int computeStateMask(String modifiers) { @@ -755,19 +1444,23 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } ISourceViewer sourceViewer = getSourceViewer(); - if (sourceViewer == null) - return; - - sourceViewer.removeTextInputListener(this); + if (sourceViewer != null) + sourceViewer.removeTextInputListener(this); - IDocument document = sourceViewer.getDocument(); - if (document != null) - document.removeDocumentListener(this); + IDocumentProvider documentProvider = getDocumentProvider(); + if (documentProvider != null) { + IDocument document = documentProvider.getDocument(getEditorInput()); + if (document != null) + document.removeDocumentListener(this); + } IPreferenceStore preferenceStore = getPreferenceStore(); if (preferenceStore != null) preferenceStore.removePropertyChangeListener(this); + if (sourceViewer == null) + return; + StyledText text = sourceViewer.getTextWidget(); if (text == null || text.isDisposed()) return; @@ -777,6 +1470,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I text.removeMouseMoveListener(this); text.removeFocusListener(this); text.removePaintListener(this); + + ((ITextViewerExtension4) sourceViewer).removeTextPresentationListener(this); } /* @@ -805,8 +1500,15 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } /** - * Creates a color from the information stored in the given preference store. Returns null if there is no such - * information available. + * Creates a color from the information stored in the given preference store. + * + * @param store + * the preference store + * @param key + * the key + * @param display + * the display + * @return the color or null if there is no such information available */ private Color createColor(IPreferenceStore store, String key, Display display) { @@ -835,36 +1537,36 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (fActiveRegion == null) return; + int offset = fActiveRegion.getOffset(); + int length = fActiveRegion.getLength(); + fActiveRegion = null; + ISourceViewer viewer = getSourceViewer(); if (viewer != null) { - resetCursor(viewer); - int offset = fActiveRegion.getOffset(); - int length = fActiveRegion.getLength(); + resetCursor(viewer); - // remove style + // Invalidate ==> remove applied text presentation if (!redrawAll && viewer instanceof ITextViewerExtension2) ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length); else viewer.invalidateTextPresentation(); - // remove underline - if (viewer instanceof ITextViewerExtension3) { - ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + // Remove underline + if (viewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; offset = extension.modelOffset2WidgetOffset(offset); } else { offset -= viewer.getVisibleRegion().getOffset(); } - - StyledText text = viewer.getTextWidget(); try { - text.redrawRange(offset, length, true); + StyledText text = viewer.getTextWidget(); + + text.redrawRange(offset, length, false); } catch (IllegalArgumentException x) { - PHPeclipsePlugin.log(x); + // JavaPlugin.log(x); } } - - fActiveRegion = null; } // will eventually be replaced by a method provided by jdt.core @@ -876,7 +1578,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I while (offset >= 0) { c = document.getChar(offset); - if (!Character.isJavaIdentifierPart(c)) + if (!Scanner.isPHPIdentifierPart(c) && c != '$') break; --offset; } @@ -888,7 +1590,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I while (offset < length) { c = document.getChar(offset); - if (!Character.isJavaIdentifierPart(c)) + if (!Scanner.isPHPIdentifierPart(c) && c != '$') break; ++offset; } @@ -911,26 +1613,25 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (offset == -1) return null; - return null; - // IJavaElement input= SelectionConverter.getInput(PHPEditor.this); - // if (input == null) - // return null; - // - // try { - // - // IJavaElement[] elements= null; - // synchronized (input) { - // elements= ((ICodeAssist) input).codeSelect(offset, 0); - // } - // - // if (elements == null || elements.length == 0) - // return null; - // - // return selectWord(viewer.getDocument(), offset); - // - // } catch (JavaModelException e) { - // return null; - // } + IJavaElement input = SelectionConverter.getInput(PHPEditor.this); + if (input == null) + return null; + + // try { + + // IJavaElement[] elements= null; + // synchronized (input) { + // elements= ((ICodeAssist) input).codeSelect(offset, 0); + // } + // + // if (elements == null || elements.length == 0) + // return null; + + return selectWord(viewer.getDocument(), offset); + + // } catch (JavaModelException e) { + // return null; + // } } private int getCurrentTextOffset(ISourceViewer viewer) { @@ -945,8 +1646,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I Point relativePosition = text.toControl(absolutePosition); int widgetOffset = text.getOffsetAtLocation(relativePosition); - if (viewer instanceof ITextViewerExtension3) { - ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + if (viewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; return extension.widgetOffset2ModelOffset(widgetOffset); } else { return widgetOffset + viewer.getVisibleRegion().getOffset(); @@ -957,6 +1658,15 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } } + public void applyTextPresentation(TextPresentation textPresentation) { + if (fActiveRegion == null) + return; + IRegion region = textPresentation.getExtent(); + if (fActiveRegion.getOffset() + fActiveRegion.getLength() >= region.getOffset() + && region.getOffset() + region.getLength() > fActiveRegion.getOffset()) + textPresentation.mergeStyleRange(new StyleRange(fActiveRegion.getOffset(), fActiveRegion.getLength(), fColor, null)); + } + private void highlightRegion(ISourceViewer viewer, IRegion region) { if (region.equals(fActiveRegion)) @@ -968,12 +1678,11 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (text == null || text.isDisposed()) return; - // highlight region + // Underline int offset = 0; int length = 0; - - if (viewer instanceof ITextViewerExtension3) { - ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; + if (viewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; IRegion widgetRange = extension.modelRange2WidgetRange(region); if (widgetRange == null) return; @@ -985,17 +1694,14 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I offset = region.getOffset() - viewer.getVisibleRegion().getOffset(); length = region.getLength(); } + text.redrawRange(offset, length, false); - StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset); - Color foregroundColor = fColor; - Color backgroundColor = oldStyleRange == null ? text.getBackground() : oldStyleRange.background; - StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor); - text.setStyleRange(styleRange); - - // underline - text.redrawRange(offset, length, true); - + // Invalidate region ==> apply text presentation fActiveRegion = region; + if (viewer instanceof ITextViewerExtension2) + ((ITextViewerExtension2) viewer).invalidateTextPresentation(region.getOffset(), region.getLength()); + else + viewer.invalidateTextPresentation(); } private void activateCursor(ISourceViewer viewer) { @@ -1036,18 +1742,18 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I fActive = true; - // removed for #25871 + // removed for #25871 // - // ISourceViewer viewer= getSourceViewer(); - // if (viewer == null) - // return; + // ISourceViewer viewer= getSourceViewer(); + // if (viewer == null) + // return; // - // IRegion region= getCurrentTextRegion(viewer); - // if (region == null) - // return; + // IRegion region= getCurrentTextRegion(viewer); + // if (region == null) + // return; // - // highlightRegion(viewer, region); - // activateCursor(viewer); + // highlightRegion(viewer, region); + // activateCursor(viewer); } /* @@ -1185,21 +1891,29 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) */ public void documentChanged(DocumentEvent event) { - if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) { - event.getDocument().removePosition(fRememberedPosition); - fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength()); - } - fRememberedPosition = null; + if (fRememberedPosition != null) { + if (!fRememberedPosition.isDeleted()) { - ISourceViewer viewer = getSourceViewer(); - if (viewer != null) { - StyledText widget = viewer.getTextWidget(); - if (widget != null && !widget.isDisposed()) { - widget.getDisplay().asyncExec(new Runnable() { - public void run() { - deactivate(); + event.getDocument().removePosition(fRememberedPosition); + fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength()); + fRememberedPosition = null; + + ISourceViewer viewer = getSourceViewer(); + if (viewer != null) { + StyledText widget = viewer.getTextWidget(); + if (widget != null && !widget.isDisposed()) { + widget.getDisplay().asyncExec(new Runnable() { + public void run() { + deactivate(); + } + }); } - }); + } + + } else { + fActiveRegion = null; + fRememberedPosition = null; + deactivate(); } } } @@ -1243,10 +1957,10 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I int offset = 0; int length = 0; - if (viewer instanceof ITextViewerExtension3) { + if (viewer instanceof ITextViewerExtension5) { - ITextViewerExtension3 extension = (ITextViewerExtension3) viewer; - IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length)); + ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; + IRegion widgetRange = extension.modelRange2WidgetRange(fActiveRegion); if (widgetRange == null) return; @@ -1311,7 +2025,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return maxLocation; } - }; + } /** * This action dispatches into two behaviours: If there is no current text hover, the javadoc is displayed using information @@ -1426,6 +2140,416 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } }; + /** + * This action implements smart home. + * + * Instead of going to the start of a line it does the following: + * - if smart home/end is enabled and the caret is after the line's first non-whitespace then the caret is moved directly before + * it, taking JavaDoc and multi-line comments into account. - if the caret is before the line's first non-whitespace the caret is + * moved to the beginning of the line - if the caret is at the beginning of the line see first case. + * + * @since 3.0 + */ + protected class SmartLineStartAction extends LineStartAction { + + /** + * Creates a new smart line start action + * + * @param textWidget + * the styled text widget + * @param doSelect + * a boolean flag which tells if the text up to the beginning of the line should be selected + */ + public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) { + super(textWidget, doSelect); + } + + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#getLineStartPosition(java.lang.String, int, + * java.lang.String) + */ + protected int getLineStartPosition(final IDocument document, final String line, final int length, final int offset) { + + String type = IDocument.DEFAULT_CONTENT_TYPE; + try { + type = TextUtilities.getContentType(document, IPHPPartitions.PHP_PARTITIONING, offset, true); + } catch (BadLocationException exception) { + // Should not happen + } + + int index = super.getLineStartPosition(document, line, length, offset); + if (type.equals(IPHPPartitions.PHP_PHPDOC_COMMENT) || type.equals(IPHPPartitions.PHP_MULTILINE_COMMENT)) { + if (index < length - 1 && line.charAt(index) == '*' && line.charAt(index + 1) != '/') { + do { + ++index; + } while (index < length && Character.isWhitespace(line.charAt(index))); + } + } else { + if (index < length - 1 && line.charAt(index) == '/' && line.charAt(index + 1) == '/') { + index++; + do { + ++index; + } while (index < length && Character.isWhitespace(line.charAt(index))); + } + } + return index; + } + } + + /** + * Text navigation action to navigate to the next sub-word. + * + * @since 3.0 + */ + protected abstract class NextSubWordAction extends TextNavigationAction { + + protected JavaWordIterator fIterator = new JavaWordIterator(); + + /** + * Creates a new next sub-word action. + * + * @param code + * Action code for the default operation. Must be an action code from + * @see org.eclipse.swt.custom.ST. + */ + protected NextSubWordAction(int code) { + super(getSourceViewer().getTextWidget(), code); + } + + /* + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + // Check whether we are in a java code partition and the preference is enabled + final IPreferenceStore store = getPreferenceStore(); + if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) { + super.run(); + return; + } + + final ISourceViewer viewer = getSourceViewer(); + final IDocument document = viewer.getDocument(); + fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); + int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); + if (position == -1) + return; + + int next = findNextPosition(position); + if (next != BreakIterator.DONE) { + setCaretPosition(next); + getTextWidget().showSelection(); + fireSelectionChanged(); + } + + } + + /** + * Finds the next position after the given position. + * + * @param position + * the current position + * @return the next position + */ + protected int findNextPosition(int position) { + ISourceViewer viewer = getSourceViewer(); + int widget = -1; + while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize + position = fIterator.following(position); + if (position != BreakIterator.DONE) + widget = modelOffset2WidgetOffset(viewer, position); + } + return position; + } + + /** + * Sets the caret position to the sub-word boundary given with position. + * + * @param position + * Position where the action should move the caret + */ + protected abstract void setCaretPosition(int position); + } + + /** + * Text navigation action to navigate to the next sub-word. + * + * @since 3.0 + */ + protected class NavigateNextSubWordAction extends NextSubWordAction { + + /** + * Creates a new navigate next sub-word action. + */ + public NavigateNextSubWordAction() { + super(ST.WORD_NEXT); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); + } + } + + /** + * Text operation action to delete the next sub-word. + * + * @since 3.0 + */ + protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate { + + /** + * Creates a new delete next sub-word action. + */ + public DeleteNextSubWordAction() { + super(ST.DELETE_WORD_NEXT); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + if (!validateEditorInputState()) + return; + + final ISourceViewer viewer = getSourceViewer(); + final int caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); + + try { + viewer.getDocument().replace(caret, position - caret, ""); //$NON-NLS-1$ + } catch (BadLocationException exception) { + // Should not happen + } + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int) + */ + protected int findNextPosition(int position) { + return fIterator.following(position); + } + + /* + * @see org.eclipse.ui.texteditor.IUpdate#update() + */ + public void update() { + setEnabled(isEditorInputModifiable()); + } + } + + /** + * Text operation action to select the next sub-word. + * + * @since 3.0 + */ + protected class SelectNextSubWordAction extends NextSubWordAction { + + /** + * Creates a new select next sub-word action. + */ + public SelectNextSubWordAction() { + super(ST.SELECT_WORD_NEXT); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + final ISourceViewer viewer = getSourceViewer(); + + final StyledText text = viewer.getTextWidget(); + if (text != null && !text.isDisposed()) { + + final Point selection = text.getSelection(); + final int caret = text.getCaretOffset(); + final int offset = modelOffset2WidgetOffset(viewer, position); + + if (caret == selection.x) + text.setSelectionRange(selection.y, offset - selection.y); + else + text.setSelectionRange(selection.x, offset - selection.x); + } + } + } + + /** + * Text navigation action to navigate to the previous sub-word. + * + * @since 3.0 + */ + protected abstract class PreviousSubWordAction extends TextNavigationAction { + + protected JavaWordIterator fIterator = new JavaWordIterator(); + + /** + * Creates a new previous sub-word action. + * + * @param code + * Action code for the default operation. Must be an action code from + * @see org.eclipse.swt.custom.ST. + */ + protected PreviousSubWordAction(final int code) { + super(getSourceViewer().getTextWidget(), code); + } + + /* + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + // Check whether we are in a java code partition and the preference is enabled + final IPreferenceStore store = getPreferenceStore(); + if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) { + super.run(); + return; + } + + final ISourceViewer viewer = getSourceViewer(); + final IDocument document = viewer.getDocument(); + fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); + int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); + if (position == -1) + return; + + int previous = findPreviousPosition(position); + if (previous != BreakIterator.DONE) { + setCaretPosition(previous); + getTextWidget().showSelection(); + fireSelectionChanged(); + } + + } + + /** + * Finds the previous position before the given position. + * + * @param position + * the current position + * @return the previous position + */ + protected int findPreviousPosition(int position) { + ISourceViewer viewer = getSourceViewer(); + int widget = -1; + while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize + position = fIterator.preceding(position); + if (position != BreakIterator.DONE) + widget = modelOffset2WidgetOffset(viewer, position); + } + return position; + } + + /** + * Sets the caret position to the sub-word boundary given with position. + * + * @param position + * Position where the action should move the caret + */ + protected abstract void setCaretPosition(int position); + } + + /** + * Text navigation action to navigate to the previous sub-word. + * + * @since 3.0 + */ + protected class NavigatePreviousSubWordAction extends PreviousSubWordAction { + + /** + * Creates a new navigate previous sub-word action. + */ + public NavigatePreviousSubWordAction() { + super(ST.WORD_PREVIOUS); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); + } + } + + /** + * Text operation action to delete the previous sub-word. + * + * @since 3.0 + */ + protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate { + + /** + * Creates a new delete previous sub-word action. + */ + public DeletePreviousSubWordAction() { + super(ST.DELETE_WORD_PREVIOUS); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + if (!validateEditorInputState()) + return; + + final ISourceViewer viewer = getSourceViewer(); + final int caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); + + try { + viewer.getDocument().replace(position, caret - position, ""); //$NON-NLS-1$ + } catch (BadLocationException exception) { + // Should not happen + } + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int) + */ + protected int findPreviousPosition(int position) { + return fIterator.preceding(position); + } + + /* + * @see org.eclipse.ui.texteditor.IUpdate#update() + */ + public void update() { + setEnabled(isEditorInputModifiable()); + } + } + + /** + * Text operation action to select the previous sub-word. + * + * @since 3.0 + */ + protected class SelectPreviousSubWordAction extends PreviousSubWordAction { + + /** + * Creates a new select previous sub-word action. + */ + public SelectPreviousSubWordAction() { + super(ST.SELECT_WORD_PREVIOUS); + } + + /* + * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) + */ + protected void setCaretPosition(final int position) { + final ISourceViewer viewer = getSourceViewer(); + + final StyledText text = viewer.getTextWidget(); + if (text != null && !text.isDisposed()) { + + final Point selection = text.getSelection(); + final int caret = text.getCaretOffset(); + final int offset = modelOffset2WidgetOffset(viewer, position); + + if (caret == selection.x) + text.setSelectionRange(selection.y, offset - selection.y); + else + text.setSelectionRange(selection.x, offset - selection.x); + } + } + } + // static protected class AnnotationAccess implements IAnnotationAccess { // /* // * @see @@ -1623,21 +2747,13 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I protected String fOutlinerContextMenuId; /** - * The editor selection changed listener. - * - * @since 3.0 - */ - // private EditorSelectionChangedListener fEditorSelectionChangedListener; - /** * Indicates whether this editor should react on outline page selection changes */ private int fIgnoreOutlinePageSelection; /** The outline page selection updater */ - private OutlinePageSelectionUpdater fUpdater; - + // private OutlinePageSelectionUpdater fUpdater; // protected PHPSyntaxParserThread fValidationThread = null; - // private IPreferenceStore fPHPPrefStore; /** The selection changed listener */ // protected ISelectionChangedListener fSelectionChangedListener = new @@ -1663,6 +2779,20 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I /** The mouse listener */ private MouseClickListener fMouseListener; + /** + * Indicates whether this editor is about to update any annotation views. + * + * @since 3.0 + */ + private boolean fIsUpdatingAnnotationViews = false; + + /** + * The marker that served as last target for a goto marker request. + * + * @since 3.0 + */ + private IMarker fLastMarkerTarget = null; + protected CompositeActionGroup fActionGroups; protected CompositeActionGroup fContextMenuGroup; @@ -1682,6 +2812,12 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I private IJavaFoldingStructureProvider fProjectionModelUpdater; /** + * The override and implements indicator manager for this editor. + * + * @since 3.0 + */ + // protected OverrideIndicatorManager fOverrideIndicatorManager; + /** * The action group for folding. * * @since 3.0 @@ -1740,18 +2876,19 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I */ protected void initializeEditor() { //jsurfer old code - JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); - setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this)); //, IJavaPartitions.JAVA_PARTITIONING)); - setRangeIndicator(new DefaultRangeIndicator()); - // IPreferenceStore store= - // PHPeclipsePlugin.getDefault().getPreferenceStore(); - // setPreferenceStore(store); + // JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + // setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this, IPHPPartitions.PHP_PARTITIONING)); //, + // IJavaPartitions.JAVA_PARTITIONING)); IPreferenceStore store = createCombinedPreferenceStore(null); setPreferenceStore(store); - + JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this, + IPHPPartitions.PHP_PARTITIONING)); + // TODO changed in 3.x ? - if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE)) - fUpdater = new OutlinePageSelectionUpdater(); + // setRangeIndicator(new DefaultRangeIndicator()); + // if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE)) + // fUpdater = new OutlinePageSelectionUpdater(); // jsurfer end // IPreferenceStore store= createCombinedPreferenceStore(null); @@ -1887,10 +3024,120 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I fEditorSelectionChangedListener = new EditorSelectionChangedListener(); fEditorSelectionChangedListener.install(getSelectionProvider()); + if (isBrowserLikeLinks()) + enableBrowserLikeLinks(); + if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE)) enableOverwriteMode(false); - // getEditorSite().getShell().addShellListener(fActivationListener); + setWordWrap(); + // getEditorSite().getShell().addShellListener(fActivationListener); + } + + private void setWordWrap() { + if (getSourceViewer() != null) { + getSourceViewer().getTextWidget().setWordWrap( + PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_WRAP_WORDS)); + } + } + + protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) { + + support.setCharacterPairMatcher(fBracketMatcher); + support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR); + + super.configureSourceViewerDecorationSupport(support); + } + + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#gotoMarker(org.eclipse.core.resources.IMarker) + */ + public void gotoMarker(IMarker marker) { + fLastMarkerTarget = marker; + if (!fIsUpdatingAnnotationViews) { + super.gotoMarker(marker); + } + } + + /** + * Jumps to the next enabled annotation according to the given direction. An annotation type is enabled if it is configured to be + * in the Next/Previous tool bar drop down menu and if it is checked. + * + * @param forward + * true if search direction is forward, false if backward + */ + public void gotoAnnotation(boolean forward) { + ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); + Position position = new Position(0, 0); + if (false /* delayed - see bug 18316 */) { + getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); + selectAndReveal(position.getOffset(), position.getLength()); + } else /* no delay - see bug 18316 */{ + Annotation annotation = getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position); + setStatusLineErrorMessage(null); + setStatusLineMessage(null); + if (annotation != null) { + updateAnnotationViews(annotation); + selectAndReveal(position.getOffset(), position.getLength()); + setStatusLineMessage(annotation.getText()); + } + } + } + + /** + * Returns the lock object for the given annotation model. + * + * @param annotationModel + * the annotation model + * @return the annotation model's lock object + * @since 3.0 + */ + private Object getLockObject(IAnnotationModel annotationModel) { + if (annotationModel instanceof ISynchronizable) + return ((ISynchronizable) annotationModel).getLockObject(); + else + return annotationModel; + } + + /** + * Updates the annotation views that show the given annotation. + * + * @param annotation + * the annotation + */ + private void updateAnnotationViews(Annotation annotation) { + IMarker marker = null; + if (annotation instanceof MarkerAnnotation) + marker = ((MarkerAnnotation) annotation).getMarker(); + else if (annotation instanceof IJavaAnnotation) { + Iterator e = ((IJavaAnnotation) annotation).getOverlaidIterator(); + if (e != null) { + while (e.hasNext()) { + Object o = e.next(); + if (o instanceof MarkerAnnotation) { + marker = ((MarkerAnnotation) o).getMarker(); + break; + } + } + } + } + + if (marker != null && !marker.equals(fLastMarkerTarget)) { + try { + boolean isProblem = marker.isSubtypeOf(IMarker.PROBLEM); + IWorkbenchPage page = getSite().getPage(); + IViewPart view = page.findView(isProblem ? IPageLayout.ID_PROBLEM_VIEW : IPageLayout.ID_TASK_LIST); //$NON-NLS-1$ //$NON-NLS-2$ + if (view != null) { + Method method = view.getClass().getMethod("setSelection", new Class[] { IStructuredSelection.class, boolean.class }); //$NON-NLS-1$ + method.invoke(view, new Object[] { new StructuredSelection(marker), Boolean.TRUE }); + } + } catch (CoreException x) { + } catch (NoSuchMethodException x) { + } catch (IllegalAccessException x) { + } catch (InvocationTargetException x) { + } + // ignore exceptions, don't update any of the lists, just set status line + } } /** @@ -1928,14 +3175,24 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I protected void createActions() { super.createActions(); + ActionGroup oeg, ovg, jsg, sg; + fActionGroups = new CompositeActionGroup(new ActionGroup[] { oeg = new OpenEditorActionGroup(this), + // sg= new ShowActionGroup(this), + // ovg= new OpenViewActionGroup(this), + // jsg= new JavaSearchActionGroup(this) + }); + fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] { oeg }); + //, ovg, sg, jsg}); + fFoldingGroup = new FoldingActionGroup(this, getViewer()); - ResourceAction resAction = new TextOperationAction(PHPEditorMessages.getResourceBundle(), - "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$ - resAction = new InformationDispatchAction(PHPEditorMessages.getResourceBundle(), - "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$ - resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC); - setAction("ShowJavaDoc", resAction); //$NON-NLS-1$ +// ResourceAction resAction = new TextOperationAction(PHPEditorMessages.getResourceBundle(), +// "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$ +// resAction = new InformationDispatchAction(PHPEditorMessages.getResourceBundle(), +// "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$ +// resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC); +// setAction("ShowJavaDoc", resAction); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(resAction, // IJavaHelpContextIds.SHOW_JAVADOC_ACTION); @@ -2018,16 +3275,16 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I super.doSetInput(input); if (getSourceViewer() instanceof JavaSourceViewer) { - JavaSourceViewer viewer= (JavaSourceViewer)getSourceViewer(); - if (viewer.getReconciler() == null) { - IReconciler reconciler= getSourceViewerConfiguration().getReconciler(viewer); - if (reconciler != null) { - reconciler.install(viewer); - viewer.setReconciler(reconciler); - } - } - } - + JavaSourceViewer viewer = (JavaSourceViewer) getSourceViewer(); + if (viewer.getReconciler() == null) { + IReconciler reconciler = getSourceViewerConfiguration().getReconciler(viewer); + if (reconciler != null) { + reconciler.install(viewer); + viewer.setReconciler(reconciler); + } + } + } + if (fEncodingSupport != null) fEncodingSupport.reset(); @@ -2036,8 +3293,8 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (fProjectionModelUpdater != null) fProjectionModelUpdater.initialize(); -// if (isShowingOverrideIndicators()) -// installOverrideIndicator(false); + // if (isShowingOverrideIndicators()) + // installOverrideIndicator(false); } /* @@ -2190,18 +3447,36 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I */ // protected void doSetInput(IEditorInput input) throws CoreException { // super.doSetInput(input); - // // if (fEncodingSupport != null) // fEncodingSupport.reset(); - // if (fOutlinePage != null) - // fOutlinePage.setInput(input); - // // setOutlinePageInput(fOutlinePage, input); + // setOutlinePageInput(fOutlinePage, input); // } + /* + * @see AbstractTextEditor#doSetInput + */ protected void doSetInput(IEditorInput input) throws CoreException { - super.doSetInput(input); - if (fEncodingSupport != null) - fEncodingSupport.reset(); - setOutlinePageInput(fOutlinePage, input); + ISourceViewer sourceViewer = getSourceViewer(); + if (!(sourceViewer instanceof ISourceViewerExtension2)) { + setPreferenceStore(createCombinedPreferenceStore(input)); + internalDoSetInput(input); + return; + } + + // uninstall & unregister preference store listener + if (isBrowserLikeLinks()) + disableBrowserLikeLinks(); + getSourceViewerDecorationSupport(sourceViewer).uninstall(); + ((ISourceViewerExtension2) sourceViewer).unconfigure(); + + setPreferenceStore(createCombinedPreferenceStore(input)); + + // install & register preference store listener + sourceViewer.configure(getSourceViewerConfiguration()); + getSourceViewerDecorationSupport(sourceViewer).install(getPreferenceStore()); + if (isBrowserLikeLinks()) + enableBrowserLikeLinks(); + + internalDoSetInput(input); } /* @@ -2619,7 +3894,12 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (value instanceof Integer) { sourceViewer.getTextWidget().setTabs(((Integer) value).intValue()); } else if (value instanceof String) { - sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value)); + try { + sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value)); + } catch (NumberFormatException e) { + // bug #1038071 - set default tab: + sourceViewer.getTextWidget().setTabs(80); + } } return; } @@ -2659,14 +3939,11 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return; } - // if - // (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) - // { - // if ((event.getNewValue() instanceof Boolean) && - // ((Boolean)event.getNewValue()).booleanValue()) - // fEditorSelectionChangedListener.selectionChanged(); - // return; - // } + if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) { + if ((event.getNewValue() instanceof Boolean) && ((Boolean) event.getNewValue()).booleanValue()) + selectionChanged(); + return; + } if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) { if (event.getNewValue() instanceof Boolean) { @@ -2706,6 +3983,20 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I // } // } // } + + ((PHPSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event); + + // if (affectsOverrideIndicatorAnnotations(event)) { + // if (isShowingOverrideIndicators()) { + // if (fOverrideIndicatorManager == null) + // installOverrideIndicator(true); + // } else { + // if (fOverrideIndicatorManager != null) + // uninstallOverrideIndicator(); + // } + // return; + // } + if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) { if (sourceViewer instanceof ProjectionViewer) { ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer; @@ -2841,6 +4132,9 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I .getNewValue()))) sourceViewer.invalidateTextPresentation(); } + if (PreferenceConstants.EDITOR_WRAP_WORDS.equals(event.getProperty())) { + setWordWrap(); + } } /** @@ -2868,12 +4162,11 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I /* * @see AbstractTextEditor#handleCursorPositionChanged() */ - protected void handleCursorPositionChanged() { - super.handleCursorPositionChanged(); - if (!isEditingScriptRunning() && fUpdater != null) - fUpdater.post(); - } - + // protected void handleCursorPositionChanged() { + // super.handleCursorPositionChanged(); + // if (!isEditingScriptRunning() && fUpdater != null) + // fUpdater.post(); + // } /* * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced() */ @@ -2940,39 +4233,40 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I // ruler.addDecorator(1, createLineNumberRulerColumn()); // return ruler; // } -// 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); -// } - protected IRegion getSignedSelection(ISourceViewer sourceViewer) { - StyledText text= sourceViewer.getTextWidget(); - Point selection= text.getSelectionRange(); - - if (text.getCaretOffset() == selection.x) { - selection.x= selection.x + selection.y; - selection.y= -selection.y; - } - - selection.x= widgetOffset2ModelOffset(sourceViewer, selection.x); - - return new Region(selection.x, selection.y); - } + // 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); + // } + protected IRegion getSignedSelection(ISourceViewer sourceViewer) { + StyledText text = sourceViewer.getTextWidget(); + Point selection = text.getSelectionRange(); + + if (text.getCaretOffset() == selection.x) { + selection.x = selection.x + selection.y; + selection.y = -selection.y; + } + + selection.x = widgetOffset2ModelOffset(sourceViewer, selection.x); + + return new Region(selection.x, selection.y); + } + /** Preference key for matching brackets */ protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS; @@ -2980,20 +4274,15 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR; /** Preference key for highlighting current line */ - protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE; - + // protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE; /** Preference key for highlight color of current line */ - protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR; - + // protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR; /** Preference key for showing print marging ruler */ - protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN; - + // protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN; /** Preference key for print margin ruler color */ - protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR; - + // protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR; /** Preference key for print margin ruler column */ - protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN; - + // protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN; /** Preference key for error indication */ // protected final static String ERROR_INDICATION = // PreferenceConstants.EDITOR_PROBLEM_INDICATION; @@ -3148,6 +4437,23 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I */ abstract protected IJavaElement getInputJavaElement(); + protected void updateStatusLine() { + ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); + Annotation annotation = getAnnotation(selection.getOffset(), selection.getLength()); + setStatusLineErrorMessage(null); + setStatusLineMessage(null); + if (annotation != null) { + try { + fIsUpdatingAnnotationViews = true; + updateAnnotationViews(annotation); + } finally { + fIsUpdatingAnnotationViews = false; + } + if (annotation instanceof IJavaAnnotation && ((IJavaAnnotation) annotation).isProblem()) + setStatusLineMessage(annotation.getText()); + } + } + /** * Jumps to the matching bracket. */ @@ -3223,6 +4529,146 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } /** + * Sets the given message as message to this editor's status line. + * + * @param msg + * message to be set + * @since 3.0 + */ + protected void setStatusLineMessage(String msg) { + IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); + if (statusLine != null) + statusLine.setMessage(false, msg, null); + } + + /** + * Returns the annotation closest to the given range respecting the given direction. If an annotation is found, the annotations + * current position is copied into the provided annotation position. + * + * @param offset + * the region offset + * @param length + * the region length + * @param forward + * true for forwards, false for backward + * @param annotationPosition + * the position of the found annotation + * @return the found annotation + */ + private Annotation getNextAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) { + + Annotation nextAnnotation = null; + Position nextAnnotationPosition = null; + Annotation containingAnnotation = null; + Position containingAnnotationPosition = null; + boolean currentAnnotation = false; + + IDocument document = getDocumentProvider().getDocument(getEditorInput()); + int endOfDocument = document.getLength(); + int distance = Integer.MAX_VALUE; + + IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); + Iterator e = new JavaAnnotationIterator(model, true, true); + while (e.hasNext()) { + Annotation a = (Annotation) e.next(); + if ((a instanceof IJavaAnnotation) && ((IJavaAnnotation) a).hasOverlay() || !isNavigationTarget(a)) + continue; + + Position p = model.getPosition(a); + if (p == null) + continue; + + if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || p.includes(offset)) { + if (containingAnnotation == null + || (forward && p.length >= containingAnnotationPosition.length || !forward + && p.length >= containingAnnotationPosition.length)) { + containingAnnotation = a; + containingAnnotationPosition = p; + currentAnnotation = p.length == length; + } + } else { + int currentDistance = 0; + + if (forward) { + currentDistance = p.getOffset() - offset; + if (currentDistance < 0) + currentDistance = endOfDocument + currentDistance; + + if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) { + distance = currentDistance; + nextAnnotation = a; + nextAnnotationPosition = p; + } + } else { + currentDistance = offset + length - (p.getOffset() + p.length); + if (currentDistance < 0) + currentDistance = endOfDocument + currentDistance; + + if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) { + distance = currentDistance; + nextAnnotation = a; + nextAnnotationPosition = p; + } + } + } + } + if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) { + annotationPosition.setOffset(containingAnnotationPosition.getOffset()); + annotationPosition.setLength(containingAnnotationPosition.getLength()); + return containingAnnotation; + } + if (nextAnnotationPosition != null) { + annotationPosition.setOffset(nextAnnotationPosition.getOffset()); + annotationPosition.setLength(nextAnnotationPosition.getLength()); + } + + return nextAnnotation; + } + + /** + * Returns the annotation overlapping with the given range or null. + * + * @param offset + * the region offset + * @param length + * the region length + * @return the found annotation or null + * @since 3.0 + */ + private Annotation getAnnotation(int offset, int length) { + IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); + Iterator e = new JavaAnnotationIterator(model, true, true); + while (e.hasNext()) { + Annotation a = (Annotation) e.next(); + if (!isNavigationTarget(a)) + continue; + + Position p = model.getPosition(a); + if (p != null && p.overlapsWith(offset, length)) + return a; + } + + return null; + } + + /** + * Returns whether the given annotation is configured as a target for the "Go to Next/Previous Annotation" actions + * + * @param annotation + * the annotation + * @return true if this is a target, false otherwise + * @since 3.0 + */ + private boolean isNavigationTarget(Annotation annotation) { + Preferences preferences = EditorsUI.getPluginPreferences(); + AnnotationPreference preference = getAnnotationPreferenceLookup().getAnnotationPreference(annotation); + // See bug 41689 + // String key= forward ? preference.getIsGoToNextNavigationTargetKey() : preference.getIsGoToPreviousNavigationTargetKey(); + String key = preference == null ? null : preference.getIsGoToNextNavigationTargetKey(); + return (key != null && preferences.getBoolean(key)); + } + + /** * Returns a segmentation of the line of the given document appropriate for bidi rendering. The default implementation returns * only the string literals of a php code line as segments. * @@ -3388,6 +4834,19 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return viewer; } + /* + * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent) + */ + protected boolean affectsTextPresentation(PropertyChangeEvent event) { + return ((PHPSourceViewerConfiguration) getSourceViewerConfiguration()).affectsTextPresentation(event) + || super.affectsTextPresentation(event); + } + + // + // protected boolean affectsTextPresentation(PropertyChangeEvent event) { + // JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + // return textTools.affectsBehavior(event); + // } /** * Creates and returns the preference store for this Java editor with the given input. * @@ -3423,23 +4882,6 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()])); } - /* - * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int) - */ - // protected ISourceViewer createJavaSourceViewer(Composite parent, - // IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean - // isOverviewRulerVisible, int styles) { - // return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), - // isOverviewRulerVisible(), styles); - // } - /* - * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent) - */ - protected boolean affectsTextPresentation(PropertyChangeEvent event) { - JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); - return textTools.affectsBehavior(event); - } - /** * Jumps to the error next according to the given direction. */ @@ -3556,42 +4998,57 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I } } - // protected void uninstallOverrideIndicator() { - // if (fOverrideIndicatorManager != null) { - // fOverrideIndicatorManager.removeAnnotations(); - // fOverrideIndicatorManager= null; - // } - //} + protected void uninstallOverrideIndicator() { + // if (fOverrideIndicatorManager != null) { + // fOverrideIndicatorManager.removeAnnotations(); + // fOverrideIndicatorManager= null; + // } + } protected void installOverrideIndicator(boolean waitForReconcilation) { - // uninstallOverrideIndicator(); + uninstallOverrideIndicator(); IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); - // IJavaElement inputElement= getInputJavaElement(); + final IJavaElement inputElement = getInputJavaElement(); - // if (model == null || inputElement == null) - // return; + if (model == null || inputElement == null) + return; - // CompilationUnit ast= - // PHPeclipsePlugin.getDefault().getASTProvider().getAST(inputElement, - // true, null); - // fOverrideIndicatorManager= new OverrideIndicatorManager(model, - // inputElement, ast); + // fOverrideIndicatorManager= new OverrideIndicatorManager(model, inputElement, null); + // + // if (provideAST) { + // Job job= new Job(JavaEditorMessages.getString("OverrideIndicatorManager.intallJob")) { //$NON-NLS-1$ + // /* + // * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + // * @since 3.0 + // */ + // protected IStatus run(IProgressMonitor monitor) { + // CompilationUnit ast= JavaPlugin.getDefault().getASTProvider().getAST(inputElement, true, null); + // if (fOverrideIndicatorManager != null) // editor might have been closed in the meanwhile + // fOverrideIndicatorManager.reconciled(ast, true, monitor); + // return Status.OK_STATUS; + // } + // }; + // job.setPriority(Job.DECORATE); + // job.setSystem(true); + // job.schedule(); + // } } /** - * Tells whether override indicators are shown. - * - * @return true if the override indicators are shown - * @since 3.0 - */ -// protected boolean isShowingOverrideIndicators() { -// AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE); -// IPreferenceStore store= getPreferenceStore(); -// return getBoolean(store, preference.getHighlightPreferenceKey()) -// || getBoolean(store, preference.getVerticalRulerPreferenceKey()) -// || getBoolean(store, preference.getOverviewRulerPreferenceKey()) -// || getBoolean(store, preference.getTextPreferenceKey()); -// } + * Tells whether override indicators are shown. + * + * @return true if the override indicators are shown + * @since 3.0 + */ + // protected boolean isShowingOverrideIndicators() { + // AnnotationPreference preference= + // getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE); + // IPreferenceStore store= getPreferenceStore(); + // return getBoolean(store, preference.getHighlightPreferenceKey()) + // || getBoolean(store, preference.getVerticalRulerPreferenceKey()) + // || getBoolean(store, preference.getOverviewRulerPreferenceKey()) + // || getBoolean(store, preference.getTextPreferenceKey()); + // } /** * Returns the boolean preference for the given key. * @@ -3606,6 +5063,88 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return key != null && store.getBoolean(key); } + protected boolean isPrefQuickDiffAlwaysOn() { + return false; // never show change ruler for the non-editable java editor. Overridden in subclasses like PHPUnitEditor + } + + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions() + */ + protected void createNavigationActions() { + super.createNavigationActions(); + + final StyledText textWidget = getSourceViewer().getTextWidget(); + + IAction action = new SmartLineStartAction(textWidget, false); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START); + setAction(ITextEditorActionDefinitionIds.LINE_START, action); + + action = new SmartLineStartAction(textWidget, true); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START); + setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action); + + action = new NavigatePreviousSubWordAction(); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS); + setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action); + textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL); + + action = new NavigateNextSubWordAction(); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT); + setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action); + textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL); + + action = new SelectPreviousSubWordAction(); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS); + setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action); + textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL); + + action = new SelectNextSubWordAction(); + action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT); + setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action); + textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL); + } + + /* + * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createCompositeRuler() + */ + protected CompositeRuler createCompositeRuler() { + if (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER)) + return super.createCompositeRuler(); + + CompositeRuler ruler = new CompositeRuler(); + AnnotationRulerColumn column = new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess()); + column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new IDoubleClickListener() { + + public void doubleClick(DoubleClickEvent event) { + // for now: just invoke ruler double click action + triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK); + } + + private void triggerAction(String actionID) { + IAction action = getAction(actionID); + if (action != null) { + if (action instanceof IUpdate) + ((IUpdate) action).update(); + // hack to propagate line change + if (action instanceof ISelectionListener) { + ((ISelectionListener) action).selectionChanged(null, null); + } + if (action.isEnabled()) + action.run(); + } + } + + })); + ruler.addDecorator(0, column); + + if (isLineNumberRulerVisible()) + ruler.addDecorator(1, createLineNumberRulerColumn()); + else if (isPrefQuickDiffAlwaysOn()) + ruler.addDecorator(1, createChangeRulerColumn()); + + return ruler; + } + /** * Returns the folding action group, or null if there is none. * @@ -3616,6 +5155,34 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I return fFoldingGroup; } + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert() + */ + protected void performRevert() { + ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer(); + projectionViewer.setRedraw(false); + try { + + boolean projectionMode = projectionViewer.isProjectionMode(); + if (projectionMode) { + projectionViewer.disableProjection(); + if (fProjectionModelUpdater != null) + fProjectionModelUpdater.uninstall(); + } + + super.performRevert(); + + if (projectionMode) { + if (fProjectionModelUpdater != null) + fProjectionModelUpdater.install(this, projectionViewer); + projectionViewer.enableProjection(); + } + + } finally { + projectionViewer.setRedraw(true); + } + } + /** * React to changed selection. * @@ -3628,7 +5195,7 @@ public abstract class PHPEditor extends AbstractDecoratedTextEditor implements I if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE)) synchronizeOutlinePage(element); setSelection(element, false); - // updateStatusLine(); + updateStatusLine(); } private boolean isJavaOutlinePageActive() {