X-Git-Url: http://secure.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 adcf53d..29f1f20 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java @@ -11,77 +11,1137 @@ Contributors: IBM Corporation - Initial implementation Klaus Hartlage - www.eclipseproject.de **********************************************************************/ -import net.sourceforge.phpeclipse.IPreferenceConstants; +import java.util.ArrayList; +import java.util.List; +import java.util.ResourceBundle; +import java.util.StringTokenizer; + +import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; +import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter; +import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher; +import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider; +import net.sourceforge.phpdt.ui.IContextMenuConstants; +import net.sourceforge.phpdt.ui.PreferenceConstants; +import net.sourceforge.phpdt.ui.actions.GenerateActionGroup; +import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction; +import net.sourceforge.phpdt.ui.text.IColorManager; +import net.sourceforge.phpdt.ui.text.JavaTextTools; 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 net.sourceforge.phpeclipse.phpeditor.php.IPHPPartitionScannerConstants; + +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.help.IHelp; -import org.eclipse.help.IHelpResource; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Preferences; import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultInformationControl; +import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; +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.ITextHover; +import org.eclipse.jface.text.ITextInputListener; import org.eclipse.jface.text.ITextOperationTarget; -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.ITypedRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.information.IInformationProvider; +import org.eclipse.jface.text.information.InformationPresenter; +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.IAnnotationAccess; +import org.eclipse.jface.text.source.IOverviewRuler; +import org.eclipse.jface.text.source.ISharedTextColors; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.ISourceViewerExtension; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.IVerticalRulerColumn; import org.eclipse.jface.text.source.LineNumberRulerColumn; +import org.eclipse.jface.text.source.OverviewRuler; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BidiSegmentEvent; +import org.eclipse.swt.custom.BidiSegmentListener; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.editors.text.TextEditor; -import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.IPartService; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.editors.text.DefaultEncodingSupport; +import org.eclipse.ui.editors.text.IEncodingSupport; +import org.eclipse.ui.texteditor.AddTaskAction; +import org.eclipse.ui.texteditor.ContentAssistAction; import org.eclipse.ui.texteditor.DefaultRangeIndicator; +import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; +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.ResourceAction; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; +import org.eclipse.ui.texteditor.StatusTextEditor; +import org.eclipse.ui.texteditor.TextEditorAction; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; + /** * PHP specific text editor. */ -public class PHPEditor extends TextEditor { +public abstract class PHPEditor extends StatusTextEditor implements IViewPartInputProvider { // extends TextEditor { + class SelectionChangedListener implements ISelectionChangedListener { + public void selectionChanged(SelectionChangedEvent event) { + doSelectionChanged(event); + } + }; + + /* + * 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 (!Character.isJavaIdentifierPart(c)) + break; + --offset; + } + + int start = offset; + + offset = anchor; + int length = document.getLength(); + + while (offset < length) { + c = document.getChar(offset); + if (!Character.isJavaIdentifierPart(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; + } + }; + + /** + * This action dispatches into two behaviours: If there is no current text + * hover, the javadoc is displayed using information presenter. If there is + * a current text hover, it is converted into a information presenter in + * order to make it sticky. + */ + class InformationDispatchAction extends TextEditorAction { + + /** The wrapped text operation action. */ + private final TextOperationAction fTextOperationAction; + + /** + * Creates a dispatch action. + */ + public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) { + super(resourceBundle, prefix, PHPEditor.this); + if (textOperationAction == null) + throw new IllegalArgumentException(); + fTextOperationAction = textOperationAction; + } + + /* + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + + ISourceViewer sourceViewer = getSourceViewer(); + if (sourceViewer == null) { + fTextOperationAction.run(); + return; + } + + if (!(sourceViewer instanceof ITextViewerExtension2)) { + fTextOperationAction.run(); + return; + } + + ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer; + + // does a text hover exist? + ITextHover textHover = textViewerExtension2.getCurrentTextHover(); + if (textHover == null) { + fTextOperationAction.run(); + return; + } + + Point hoverEventLocation = textViewerExtension2.getHoverEventLocation(); + int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y); + if (offset == -1) { + fTextOperationAction.run(); + return; + } - protected PHPActionGroup actionGroup; + try { + // get the text hover content + IDocument document = sourceViewer.getDocument(); + String contentType = document.getContentType(offset); + + final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset); + if (hoverRegion == null) + return; + + final String hoverInfo = textHover.getHoverInfo(sourceViewer, hoverRegion); + + // with information provider + IInformationProvider informationProvider = new IInformationProvider() { + /* + * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int) + */ + public IRegion getSubject(ITextViewer textViewer, int offset) { + return hoverRegion; + } + /* + * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) + */ + public String getInformation(ITextViewer textViewer, IRegion subject) { + return hoverInfo; + } + }; + + fInformationPresenter.setOffset(offset); + fInformationPresenter.setInformationProvider(informationProvider, contentType); + fInformationPresenter.showInformation(); + + } catch (BadLocationException e) { + } + } + + // modified version from TextViewer + private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) { + + StyledText styledText = textViewer.getTextWidget(); + IDocument document = textViewer.getDocument(); + + if (document == null) + return -1; + + try { + int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y)); + if (textViewer instanceof ITextViewerExtension3) { + ITextViewerExtension3 extension = (ITextViewerExtension3) textViewer; + return extension.widgetOffset2ModelOffset(widgetLocation); + } else { + IRegion visibleRegion = textViewer.getVisibleRegion(); + return widgetLocation + visibleRegion.getOffset(); + } + } catch (IllegalArgumentException e) { + return -1; + } + + } + }; + + static protected class AnnotationAccess implements IAnnotationAccess { + /* + * @see org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation) + */ + public Object getType(Annotation annotation) { + if (annotation instanceof IJavaAnnotation) { + IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation; + if (javaAnnotation.isRelevant()) + return javaAnnotation.getAnnotationType(); + } + return null; + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation) + */ + public boolean isMultiLine(Annotation annotation) { + return true; + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation) + */ + public boolean isTemporary(Annotation annotation) { + if (annotation instanceof IJavaAnnotation) { + IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation; + if (javaAnnotation.isRelevant()) + return javaAnnotation.isTemporary(); + } + return false; + } + }; + + private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener { + /* + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) { + handlePreferencePropertyChanged(event); + } + }; + /** Preference key for showing the line number ruler */ + private final static String LINE_NUMBER_RULER = PreferenceConstants.EDITOR_LINE_NUMBER_RULER; + /** Preference key for the foreground color of the line numbers */ + private final static String LINE_NUMBER_COLOR = PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR; + /** Preference key for the link color */ + private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR; + + // protected PHPActionGroup fActionGroups; /** The outline page */ - private PHPContentOutlinePage fOutlinePage; - private IPreferenceStore phpPrefStore; + private AbstractContentOutlinePage fOutlinePage; + + // protected PHPSyntaxParserThread fValidationThread = null; + + // private IPreferenceStore fPHPPrefStore; + /** The selection changed listener */ + protected ISelectionChangedListener fSelectionChangedListener = new SelectionChangedListener(); + /** The editor's bracket matcher */ + private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS); /** The line number ruler column */ private LineNumberRulerColumn fLineNumberRulerColumn; + /** This editor's encoding support */ + private DefaultEncodingSupport fEncodingSupport; + /** The mouse listener */ + private MouseClickListener fMouseListener; + + protected CompositeActionGroup fActionGroups; + /** The standard action groups added to the menu */ + protected GenerateActionGroup fGenerateActionGroup; + protected CompositeActionGroup fContextMenuGroup; + + /** The information presenter. */ + private InformationPresenter fInformationPresenter; + /** The annotation access */ + protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess(); + /** The overview ruler */ + protected OverviewRuler isOverviewRulerVisible; + /** The source viewer decoration support */ + protected SourceViewerDecorationSupport fSourceViewerDecorationSupport; + /** The overview ruler */ + protected OverviewRuler fOverviewRuler; + + /** The preference property change listener for java core. */ + private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener(); /** * Default constructor. */ public PHPEditor() { super(); + JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this)); + setRangeIndicator(new DefaultRangeIndicator()); + setPreferenceStore(PHPeclipsePlugin.getDefault().getPreferenceStore()); + + // don't activate this scope without synchronizing plugin.xml !!! + // setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$ + + // if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE)) + // fUpdater= new OutlinePageSelectionUpdater(); + } + // + // /** + // * @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(); + // } + /* + * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions() + */ + protected void updatePropertyDependentActions() { + super.updatePropertyDependentActions(); + if (fEncodingSupport != null) + fEncodingSupport.reset(); + } + + /* + * Update the hovering behavior depending on the preferences. + */ + private void updateHoverBehavior() { + SourceViewerConfiguration configuration = getSourceViewerConfiguration(); + String[] types = configuration.getConfiguredContentTypes(getSourceViewer()); + + for (int i = 0; i < types.length; i++) { + + String t = types[i]; + + int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t); + + ISourceViewer sourceViewer = getSourceViewer(); + if (sourceViewer instanceof ITextViewerExtension2) { + if (stateMasks != null) { + for (int j = 0; j < stateMasks.length; j++) { + int stateMask = stateMasks[j]; + ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask); + ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask); + } + } else { + ITextHover textHover = configuration.getTextHover(sourceViewer, t); + ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK); + } + } else + sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t); + } + } + + /* + * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput() + */ + public Object getViewPartInput() { + return getEditorInput().getAdapter(IResource.class); + } + + /* + * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt. + * widgets.Composite) + */ + public void createPartControl(Composite parent) { + super.createPartControl(parent); + + fSourceViewerDecorationSupport.install(getPreferenceStore()); + + Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences(); + preferences.addPropertyChangeListener(fPropertyChangeListener); + + IInformationControlCreator informationControlCreator = new IInformationControlCreator() { + public IInformationControl createInformationControl(Shell parent) { + boolean cutDown = false; + int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL); + return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown)); + } + }; + + fInformationPresenter = new InformationPresenter(informationControlCreator); + fInformationPresenter.setSizeConstraints(60, 10, true, true); + fInformationPresenter.install(getSourceViewer()); + } + + /** + * 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() { - return fOutlinePage; + public AbstractContentOutlinePage getfOutlinePage() { + return fOutlinePage; } - /** The JavaEditor implementation of this + + /** The PHPEditor implementation of this * AbstractTextEditor method extend the * actions to add those specific to the receiver */ protected void createActions() { super.createActions(); - setAction( - "ContentAssistProposal", - new TextOperationAction( - PHPEditorMessages.getResourceBundle(), - "ContentAssistProposal.", - this, - ISourceViewer.CONTENTASSIST_PROPOSALS)); + + ResourceAction resAction = new AddTaskAction(PHPEditorMessages.getResourceBundle(), "AddTask.", this); //$NON-NLS-1$ + resAction.setHelpContextId(IAbstractTextEditorHelpContextIds.ADD_TASK_ACTION); + resAction.setActionDefinitionId(ITextEditorActionDefinitionIds.ADD_TASK); + setAction(ITextEditorActionConstants.ADD_TASK, resAction); + + 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(PHPEditorActionDefinitionIds.SHOW_JAVADOC); + setAction("ShowJavaDoc", resAction); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(resAction, IJavaHelpContextIds.SHOW_JAVADOC_ACTION); + + Action action; + setAction( "ContentAssistTip", new TextOperationAction( @@ -90,26 +1150,93 @@ public class PHPEditor extends TextEditor { this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION)); - Action action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); + action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$ + action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + setAction("ContentAssistProposal", action); //$NON-NLS-1$ + markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.CONTENT_ASSIST_ACTION); + + fEncodingSupport = new DefaultEncodingSupport(); + fEncodingSupport.initialize(this); + + action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$ action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT); - setAction("Comment", action); + setAction("Comment", action); //$NON-NLS-1$ + markAsStateDependentAction("Comment", true); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION); - action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); + action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$ action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT); - setAction("Uncomment", action); + setAction("Uncomment", action); //$NON-NLS-1$ + markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION); + + action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$ + action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT); + setAction("Format", action); //$NON-NLS-1$ + markAsStateDependentAction("Format", true); //$NON-NLS-1$ + markAsSelectionDependentAction("Format", true); //$NON-NLS-1$ + // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION); - actionGroup = new PHPActionGroup(this, ITextEditorActionConstants.GROUP_EDIT); + 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)}); + + // if (fValidationThread == null) { + // fValidationThread = + // new PHPSyntaxParserThread(this, getSourceViewer()); + // //Thread defaults + // + // fValidationThread.start(); + // } + // + // fValidationThread.setText(getSourceViewer().getTextWidget().getText()); } - /** The JavaEditor implementation of this + /** The PHPEditor implementation of this * AbstractTextEditor method performs any extra - * disposal actions required by the java editor. + * disposal actions required by the php editor. */ public void dispose() { - PHPEditorEnvironment.disconnect(this); + // PHPEditorEnvironment.disconnect(this); if (fOutlinePage != null) fOutlinePage.setInput(null); + + if (fActionGroups != null) + fActionGroups.dispose(); + + if (isBrowserLikeLinks()) + disableBrowserLikeLinks(); + + if (fEncodingSupport != null) { + fEncodingSupport.dispose(); + fEncodingSupport = null; + } + + if (fPropertyChangeListener != null) { + Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences(); + preferences.removePropertyChangeListener(fPropertyChangeListener); + fPropertyChangeListener = null; + } + + if (fSourceViewerDecorationSupport != null) { + fSourceViewerDecorationSupport.dispose(); + fSourceViewerDecorationSupport = null; + } + + if (fBracketMatcher != null) { + fBracketMatcher.dispose(); + fBracketMatcher = null; + } super.dispose(); } @@ -130,12 +1257,20 @@ public class PHPEditor extends TextEditor { public void doSave(IProgressMonitor monitor) { super.doSave(monitor); // compile or not, according to the user preferences - IPreferenceStore store = phpPrefStore; - if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) { - IAction a = PHPParserAction.getInstance(); - if (a != null) - a.run(); - } + // IPreferenceStore store = getPreferenceStore(); + + // the parse on save was changed to the eclipse "builders" concept + // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) { + // IAction a = PHPParserAction.getInstance(); + // if (a != null) + // a.run(); + // } + + // if (SWT.getPlatform().equals("win32")) { + // IAction a = ShowExternalPreviewAction.getInstance(); + // if (a != null) + // a.run(); + // } if (fOutlinePage != null) fOutlinePage.update(); } @@ -149,29 +1284,115 @@ public class PHPEditor extends TextEditor { if (fOutlinePage != null) fOutlinePage.update(); } + /* + * @see StatusTextEditor#getStatusHeader(IStatus) + */ + protected String getStatusHeader(IStatus status) { + if (fEncodingSupport != null) { + String message = fEncodingSupport.getStatusHeader(status); + if (message != null) + return message; + } + return super.getStatusHeader(status); + } + /* + * @see StatusTextEditor#getStatusBanner(IStatus) + */ + protected String getStatusBanner(IStatus status) { + if (fEncodingSupport != null) { + String message = fEncodingSupport.getStatusBanner(status); + if (message != null) + return message; + } + return super.getStatusBanner(status); + } + + /* + * @see StatusTextEditor#getStatusMessage(IStatus) + */ + protected String getStatusMessage(IStatus status) { + if (fEncodingSupport != null) { + String message = fEncodingSupport.getStatusMessage(status); + if (message != null) + return message; + } + return super.getStatusMessage(status); + } /** The PHPEditor implementation of this * AbstractTextEditor method performs sets the * input of the outline page after AbstractTextEditor has set input. */ - public void doSetInput(IEditorInput input) throws CoreException { + protected void doSetInput(IEditorInput input) throws CoreException { super.doSetInput(input); + + if (fEncodingSupport != null) + fEncodingSupport.reset(); if (fOutlinePage != null) fOutlinePage.setInput(input); + // setOutlinePageInput(fOutlinePage, input); } - /** The JavaEditor implementation of this + /* + * @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 - * JavaEditor specific entries. + * 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); + menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN)); + menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW)); + + ActionContext context = new ActionContext(getSelectionProvider().getSelection()); + fContextMenuGroup.setContext(context); + fContextMenuGroup.fillContextMenu(menu); + fContextMenuGroup.setContext(null); + // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$ + // + // ActionContext context = + // new ActionContext(getSelectionProvider().getSelection()); + // fContextMenuGroup.setContext(context); + // fContextMenuGroup.fillContextMenu(menu); + // fContextMenuGroup.setContext(null); + } + + /** + * Creates the outline page used with this editor. + */ + protected AbstractContentOutlinePage createOutlinePage() { + + AbstractContentOutlinePage page = new PHPContentOutlinePage(getDocumentProvider(), this); + + page.addSelectionChangedListener(fSelectionChangedListener); + // setOutlinePageInput(page, getEditorInput()); + if (getEditorInput() != null) + fOutlinePage.setInput(getEditorInput()); + + return page; + } + + /** + * Informs the editor that its outliner has been closed. + */ + public void outlinePageClosed() { + if (fOutlinePage != null) { + fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener); + fOutlinePage = null; + resetHighlightRange(); + } + } + protected void updateStateDependentActions() { + super.updateStateDependentActions(); + fGenerateActionGroup.editorStateChanged(); } - /** The JavaEditor implementation of this + /** The PHPEditor implementation of this * AbstractTextEditor method performs gets * the java content outline page if request is for a an * outline page. @@ -185,45 +1406,81 @@ public class PHPEditor extends TextEditor { } return fOutlinePage; } + + if (IEncodingSupport.class.equals(required)) + return fEncodingSupport; + 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); - } + protected void doSelectionChanged(SelectionChangedEvent event) { - private void openContextHelp(String word) { - open(word); - } + // ISourceReference reference= null; + // + // ISelection selection= event.getSelection(); + // Iterator iter= ((IStructuredSelection) selection).iterator(); + // while (iter.hasNext()) { + // Object o= iter.next(); + // if (o instanceof ISourceReference) { + // reference= (ISourceReference) o; + // break; + // } + // } + if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null) + PHPeclipsePlugin.getActivePage().bringToTop(this); - 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$ - } + // try { + // editingScriptStarted(); + // setSelection(reference, !isActivePart()); + // } finally { + // editingScriptEnded(); + // } } - 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 ""; + protected boolean isActivePart() { + IWorkbenchWindow window = getSite().getWorkbenchWindow(); + IPartService service = window.getPartService(); + IWorkbenchPart part = service.getActivePart(); + return part != null && part.equals(this); } + + // 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) - */ + * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent) + */ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { try { @@ -234,17 +1491,25 @@ public class PHPEditor extends TextEditor { String property = event.getProperty(); - // if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) { - // Object value= event.getNewValue(); - // if (value instanceof Integer) { - // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue()); - // } else if (value instanceof String) { - // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value)); - // } - // return; - // } - - if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) { + if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) { + Object value = event.getNewValue(); + if (value instanceof Integer) { + sourceViewer.getTextWidget().setTabs(((Integer) value).intValue()); + } else if (value instanceof String) { + sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value)); + } + return; + } + + if (OVERVIEW_RULER.equals(property)) { + if (isOverviewRulerVisible()) + showOverviewRuler(); + else + hideOverviewRuler(); + return; + } + + if (LINE_NUMBER_RULER.equals(property)) { if (isLineNumberRulerVisible()) showLineNumberRuler(); else @@ -253,17 +1518,77 @@ public class PHPEditor extends TextEditor { } if (fLineNumberRulerColumn != null - && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property) + && (LINE_NUMBER_COLOR.equals(property) || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) || PREFERENCE_COLOR_BACKGROUND.equals(property))) { initializeLineNumberRulerColumn(fLineNumberRulerColumn); } + if (isJavaEditorHoverProperty(property)) { + updateHoverBehavior(); + } + } finally { super.handlePreferenceStoreChanged(event); } } + + // /* + // * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent) + // */ + // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { + // + // try { + // + // ISourceViewer sourceViewer = getSourceViewer(); + // if (sourceViewer == null) + // return; + // + // String property = event.getProperty(); + // + // // if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) { + // // Object value= event.getNewValue(); + // // if (value instanceof Integer) { + // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue()); + // // } else if (value instanceof String) { + // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value)); + // // } + // // return; + // // } + // + // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) { + // if (isLineNumberRulerVisible()) + // showLineNumberRuler(); + // else + // hideLineNumberRuler(); + // return; + // } + // + // if (fLineNumberRulerColumn != null + // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property) + // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) + // || PREFERENCE_COLOR_BACKGROUND.equals(property))) { + // + // initializeLineNumberRulerColumn(fLineNumberRulerColumn); + // } + // + // } finally { + // super.handlePreferenceStoreChanged(event); + // } + // } + + private boolean isJavaEditorHoverProperty(String property) { + return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property) + || PreferenceConstants.EDITOR_NONE_HOVER.equals(property) + || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property) + || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property) + || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property) + || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property) + || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property) + || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property); + } + /** * Shows the line number ruler column. */ @@ -274,15 +1599,58 @@ public class PHPEditor extends TextEditor { c.addDecorator(1, createLineNumberRulerColumn()); } } + /** + * Return whether the browser like links should be enabled + * according to the preference store settings. + * @return true if the browser like links should be enabled + */ + private boolean isBrowserLikeLinks() { + IPreferenceStore store = getPreferenceStore(); + return store.getBoolean(BROWSER_LIKE_LINKS); + } /** - * Return whether the line number ruler column should be - * visible according to the preference store settings. - * @return true if the line numbers should be visible - */ + * Enables browser like links. + */ + private void enableBrowserLikeLinks() { + if (fMouseListener == null) { + fMouseListener = new MouseClickListener(); + fMouseListener.install(); + } + } + + /** + * Disables browser like links. + */ + private void disableBrowserLikeLinks() { + if (fMouseListener != null) { + fMouseListener.uninstall(); + fMouseListener = null; + } + } + /** + * Handles a property change event describing a change + * of the java core's preferences and updates the preference + * related editor properties. + * + * @param event the property change event + */ + protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) { + // if (COMPILER_TASK_TAGS.equals(event.getProperty())) { + // ISourceViewer sourceViewer= getSourceViewer(); + // if (sourceViewer != null && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue()))) + // sourceViewer.invalidateTextPresentation(); + // } + } + + /** + * Return whether the line number ruler column should be + * visible according to the preference store settings. + * @return true if the line numbers should be visible + */ private boolean isLineNumberRulerVisible() { - // IPreferenceStore store= getPreferenceStore(); - return phpPrefStore.getBoolean(IPreferenceConstants.LINE_NUMBER_RULER); + IPreferenceStore store = getPreferenceStore(); + return store.getBoolean(LINE_NUMBER_RULER); } /** * Hides the line number ruler column. @@ -291,42 +1659,45 @@ 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) { + } } } /** - * Initializes the given line number ruler column from the preference store. - * @param rulerColumn the ruler column to be initialized - */ + * Initializes the given line number ruler column from the preference store. + * @param rulerColumn the ruler column to be initialized + */ protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) { - // JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools(); - PHPColorProvider manager = PHPEditorEnvironment.getPHPColorProvider(); + JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + IColorManager manager = textTools.getColorManager(); - if (phpPrefStore != null) { + IPreferenceStore store = getPreferenceStore(); + if (store != null) { RGB rgb = null; // foreground color - if (phpPrefStore.contains(IPreferenceConstants.LINE_NUMBER_COLOR)) { - if (phpPrefStore.isDefault(IPreferenceConstants.LINE_NUMBER_COLOR)) - rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR); + if (store.contains(LINE_NUMBER_COLOR)) { + if (store.isDefault(LINE_NUMBER_COLOR)) + rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR); else - rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR); + rgb = PreferenceConverter.getColor(store, 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 (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) { + if (store.contains(PREFERENCE_COLOR_BACKGROUND)) { + if (store.isDefault(PREFERENCE_COLOR_BACKGROUND)) + rgb = PreferenceConverter.getDefaultColor(store, PREFERENCE_COLOR_BACKGROUND); else - rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND); + rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND); } - rulerColumn.setBackground(manager.getColor(rgb)); } - + rulerColumn.setBackground(manager.getColor(rgb)); } } @@ -350,38 +1721,392 @@ public class PHPEditor extends TextEditor { return ruler; } - /* (non-Javadoc) - * Method declared on AbstractTextEditor + 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); + } + + /** Preference key for matching brackets */ + protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS; + /** Preference key for matching brackets color */ + 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; + /** Preference key for highlight color of current line */ + 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; + /** Preference key for print margin ruler 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; + /** Preference key for error indication */ + protected final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION; + /** Preference key for error color */ + protected final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR; + /** Preference key for warning indication */ + protected final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION; + /** Preference key for warning color */ + protected final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR; + /** Preference key for task indication */ + protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION; + /** Preference key for task color */ + protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR; + /** Preference key for bookmark indication */ + protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION; + /** Preference key for bookmark color */ + protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR; + /** Preference key for search result indication */ + protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION; + /** Preference key for search result color */ + protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR; + /** Preference key for unknown annotation indication */ + protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION; + /** Preference key for unknown annotation color */ + protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR; + /** Preference key for shwoing the overview ruler */ + protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER; + /** Preference key for error indication in overview ruler */ + protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER; + /** Preference key for warning indication in overview ruler */ + protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = + PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER; + /** Preference key for task indication in overview ruler */ + protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER; + /** Preference key for bookmark indication in overview ruler */ + protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = + PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER; + /** Preference key for search result indication in overview ruler */ + protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = + PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER; + /** Preference key for unknown annotation indication in overview ruler */ + protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = + PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER; + // /** Preference key for compiler task tags */ + // private final static String COMPILER_TASK_TAGS= JavaCore.COMPILER_TASK_TAGS; + /** Preference key for browser like links */ + private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS; + /** Preference key for key modifier of browser like links */ + private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER; + /** + * Preference key for key modifier mask of browser like links. + * The value is only used if the value of EDITOR_BROWSER_LIKE_LINKS + * cannot be resolved to valid SWT modifier bits. + * + * @since 2.1.1 */ - protected void initializeEditor() { - PHPEditorEnvironment.connect(this); + private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = + PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK; - setSourceViewerConfiguration(new PHPSourceViewerConfiguration()); - setRangeIndicator(new DefaultRangeIndicator()); - setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$ - setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$ - // setDocumentProvider(PHPeclipsePlugin.getCompilationUnitDocumentProvider()); - phpPrefStore = PHPeclipsePlugin.getDefault().getPreferenceStore(); - - phpPrefStore.addPropertyChangeListener(new IPropertyChangeListener() { - public void propertyChange(PropertyChangeEvent event) { - PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner(); - if (scanner != null) { - scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider()); - } - if (getSourceViewer() != null) { - getSourceViewer().invalidateTextPresentation(); - } + private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' }; - String property = event.getProperty(); - if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) { - if (isLineNumberRulerVisible()) - showLineNumberRuler(); - else - hideLineNumberRuler(); - return; + 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; + } + } + + protected void configureSourceViewerDecorationSupport() { + + fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher); + + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.UNKNOWN, + UNKNOWN_INDICATION_COLOR, + UNKNOWN_INDICATION, + UNKNOWN_INDICATION_IN_OVERVIEW_RULER, + 0); + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.BOOKMARK, + BOOKMARK_INDICATION_COLOR, + BOOKMARK_INDICATION, + BOOKMARK_INDICATION_IN_OVERVIEW_RULER, + 1); + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.TASK, + TASK_INDICATION_COLOR, + TASK_INDICATION, + TASK_INDICATION_IN_OVERVIEW_RULER, + 2); + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.SEARCH, + SEARCH_RESULT_INDICATION_COLOR, + SEARCH_RESULT_INDICATION, + SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER, + 3); + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.WARNING, + WARNING_INDICATION_COLOR, + WARNING_INDICATION, + WARNING_INDICATION_IN_OVERVIEW_RULER, + 4); + fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys( + AnnotationType.ERROR, + ERROR_INDICATION_COLOR, + ERROR_INDICATION, + ERROR_INDICATION_IN_OVERVIEW_RULER, + 5); + + fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR); + fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN); + fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR); + + fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey()); + } + /** + * Jumps to the matching bracket. + */ + public void gotoMatchingBracket() { + + 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); + } + + /** + * 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. + * + * @param document the document + * @param lineOffset the offset of the line + * @return the line's bidi segmentation + * @throws BadLocationException in case lineOffset is not valid in document + */ + public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException { + + IRegion line = document.getLineInformationOfOffset(lineOffset); + ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength()); + + List segmentation = new ArrayList(); + for (int i = 0; i < linePartitioning.length; i++) { + if (IPHPPartitionScannerConstants.PHP_STRING.equals(linePartitioning[i].getType())) + segmentation.add(linePartitioning[i]); + } + + if (segmentation.size() == 0) + return null; + + int size = segmentation.size(); + int[] segments = new int[size * 2 + 1]; + + int j = 0; + for (int i = 0; i < size; i++) { + ITypedRegion segment = (ITypedRegion) segmentation.get(i); + + if (i == 0) + segments[j++] = 0; + + int offset = segment.getOffset() - lineOffset; + if (offset > segments[j - 1]) + segments[j++] = offset; + + if (offset + segment.getLength() >= line.getLength()) + break; + + segments[j++] = offset + segment.getLength(); + } + + if (j < segments.length) { + int[] result = new int[j]; + System.arraycopy(segments, 0, result, 0, j); + segments = result; + } + + return segments; + } + /** + * Returns a segmentation of the given line appropriate for bidi rendering. The default + * implementation returns only the string literals of a php code line as segments. + * + * @param lineOffset the offset of the line + * @param line the content of the line + * @return the line's bidi segmentation + */ + protected int[] getBidiLineSegments(int lineOffset, String line) { + IDocumentProvider provider = getDocumentProvider(); + if (provider != null && line != null && line.length() > 0) { + IDocument document = provider.getDocument(getEditorInput()); + if (document != null) + try { + return getBidiLineSegments(document, lineOffset); + } catch (BadLocationException x) { + // ignore } + } + return null; + } + + /* + * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int) + */ + // protected final ISourceViewer createSourceViewer( + // Composite parent, + // IVerticalRuler ruler, + // int styles) { + // ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles); + // StyledText text = viewer.getTextWidget(); + // text.addBidiSegmentListener(new BidiSegmentListener() { + // public void lineGetSegments(BidiSegmentEvent event) { + // event.segments = getBidiLineSegments(event.lineOffset, event.lineText); + // } + // }); + // // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR); + // return viewer; + // } + protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) { + + ISharedTextColors sharedColors = PHPeclipsePlugin.getDefault().getJavaTextTools().getColorManager(); + + fOverviewRuler = new OverviewRuler(fAnnotationAccess, VERTICAL_RULER_WIDTH, sharedColors); + fOverviewRuler.addHeaderAnnotationType(AnnotationType.WARNING); + fOverviewRuler.addHeaderAnnotationType(AnnotationType.ERROR); + + ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler, fOverviewRuler, isOverviewRulerVisible(), styles); + + StyledText text = viewer.getTextWidget(); + text.addBidiSegmentListener(new BidiSegmentListener() { + public void lineGetSegments(BidiSegmentEvent event) { + event.segments = getBidiLineSegments(event.lineOffset, event.lineText); } }); + + // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR); + + fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(viewer, fOverviewRuler, fAnnotationAccess, sharedColors); + configureSourceViewerDecorationSupport(); + + return viewer; + } + + protected void showOverviewRuler() { + if (fOverviewRuler != null) { + if (getSourceViewer() instanceof ISourceViewerExtension) { + ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(true); + fSourceViewerDecorationSupport.updateOverviewDecorations(); + } + } + } + + protected void hideOverviewRuler() { + if (getSourceViewer() instanceof ISourceViewerExtension) { + fSourceViewerDecorationSupport.hideAnnotationOverview(); + ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(false); + } + } + + protected boolean isOverviewRulerVisible() { + IPreferenceStore store = getPreferenceStore(); + return store.getBoolean(OVERVIEW_RULER); } + /* + * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int) + */ + protected ISourceViewer createJavaSourceViewer( + Composite parent, + IVerticalRuler ruler, + IOverviewRuler overviewRuler, + boolean isOverviewRulerVisible, + int styles) { + return new SourceViewer(parent, ruler, overviewRuler, isOverviewRulerVisible(), styles); + // return super.createSourceViewer(parent, ruler, styles); + } + + /* + * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent) + */ + protected boolean affectsTextPresentation(PropertyChangeEvent event) { + JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools(); + return textTools.affectsBehavior(event); + } + }