1 package net.sourceforge.phpeclipse.phpeditor;
3 /**********************************************************************
4 Copyright (c) 2000, 2002 IBM Corp. and others.
5 All rights reserved. This program and the accompanying materials
6 are made available under the terms of the Common Public License v1.0
7 which accompanies this distribution, and is available at
8 http://www.eclipse.org/legal/cpl-v10.html
11 IBM Corporation - Initial implementation
12 Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.ResourceBundle;
17 import java.util.StringTokenizer;
19 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
20 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
21 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
22 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
23 import net.sourceforge.phpdt.ui.IContextMenuConstants;
24 import net.sourceforge.phpdt.ui.PreferenceConstants;
25 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
26 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
27 import net.sourceforge.phpdt.ui.text.IColorManager;
28 import net.sourceforge.phpdt.ui.text.JavaTextTools;
29 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
30 import net.sourceforge.phpeclipse.phpeditor.php.IPHPPartitionScannerConstants;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.runtime.CoreException;
34 import org.eclipse.core.runtime.IProgressMonitor;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Preferences;
37 import org.eclipse.jface.action.Action;
38 import org.eclipse.jface.action.GroupMarker;
39 import org.eclipse.jface.action.IAction;
40 import org.eclipse.jface.action.MenuManager;
41 import org.eclipse.jface.action.Separator;
42 import org.eclipse.jface.preference.IPreferenceStore;
43 import org.eclipse.jface.preference.PreferenceConverter;
44 import org.eclipse.jface.text.BadLocationException;
45 import org.eclipse.jface.text.DefaultInformationControl;
46 import org.eclipse.jface.text.DocumentEvent;
47 import org.eclipse.jface.text.IDocument;
48 import org.eclipse.jface.text.IDocumentListener;
49 import org.eclipse.jface.text.IInformationControl;
50 import org.eclipse.jface.text.IInformationControlCreator;
51 import org.eclipse.jface.text.IRegion;
52 import org.eclipse.jface.text.ITextHover;
53 import org.eclipse.jface.text.ITextInputListener;
54 import org.eclipse.jface.text.ITextOperationTarget;
55 import org.eclipse.jface.text.ITextViewer;
56 import org.eclipse.jface.text.ITextViewerExtension2;
57 import org.eclipse.jface.text.ITextViewerExtension3;
58 import org.eclipse.jface.text.ITypedRegion;
59 import org.eclipse.jface.text.Position;
60 import org.eclipse.jface.text.Region;
61 import org.eclipse.jface.text.information.IInformationProvider;
62 import org.eclipse.jface.text.information.InformationPresenter;
63 import org.eclipse.jface.text.source.Annotation;
64 import org.eclipse.jface.text.source.AnnotationRulerColumn;
65 import org.eclipse.jface.text.source.CompositeRuler;
66 import org.eclipse.jface.text.source.IAnnotationAccess;
67 import org.eclipse.jface.text.source.IOverviewRuler;
68 import org.eclipse.jface.text.source.ISharedTextColors;
69 import org.eclipse.jface.text.source.ISourceViewer;
70 import org.eclipse.jface.text.source.ISourceViewerExtension;
71 import org.eclipse.jface.text.source.IVerticalRuler;
72 import org.eclipse.jface.text.source.IVerticalRulerColumn;
73 import org.eclipse.jface.text.source.LineNumberRulerColumn;
74 import org.eclipse.jface.text.source.OverviewRuler;
75 import org.eclipse.jface.text.source.SourceViewer;
76 import org.eclipse.jface.text.source.SourceViewerConfiguration;
77 import org.eclipse.jface.util.IPropertyChangeListener;
78 import org.eclipse.jface.util.PropertyChangeEvent;
79 import org.eclipse.jface.viewers.ISelectionChangedListener;
80 import org.eclipse.jface.viewers.SelectionChangedEvent;
81 import org.eclipse.swt.SWT;
82 import org.eclipse.swt.custom.BidiSegmentEvent;
83 import org.eclipse.swt.custom.BidiSegmentListener;
84 import org.eclipse.swt.custom.StyleRange;
85 import org.eclipse.swt.custom.StyledText;
86 import org.eclipse.swt.events.FocusEvent;
87 import org.eclipse.swt.events.FocusListener;
88 import org.eclipse.swt.events.KeyEvent;
89 import org.eclipse.swt.events.KeyListener;
90 import org.eclipse.swt.events.MouseEvent;
91 import org.eclipse.swt.events.MouseListener;
92 import org.eclipse.swt.events.MouseMoveListener;
93 import org.eclipse.swt.events.PaintEvent;
94 import org.eclipse.swt.events.PaintListener;
95 import org.eclipse.swt.graphics.Color;
96 import org.eclipse.swt.graphics.Cursor;
97 import org.eclipse.swt.graphics.GC;
98 import org.eclipse.swt.graphics.Point;
99 import org.eclipse.swt.graphics.RGB;
100 import org.eclipse.swt.widgets.Composite;
101 import org.eclipse.swt.widgets.Control;
102 import org.eclipse.swt.widgets.Display;
103 import org.eclipse.swt.widgets.Shell;
104 import org.eclipse.ui.IEditorInput;
105 import org.eclipse.ui.IPartService;
106 import org.eclipse.ui.IWorkbenchPart;
107 import org.eclipse.ui.IWorkbenchWindow;
108 import org.eclipse.ui.actions.ActionContext;
109 import org.eclipse.ui.actions.ActionGroup;
110 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
111 import org.eclipse.ui.editors.text.IEncodingSupport;
112 import org.eclipse.ui.texteditor.AddTaskAction;
113 import org.eclipse.ui.texteditor.ContentAssistAction;
114 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
115 import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
116 import org.eclipse.ui.texteditor.IDocumentProvider;
117 import org.eclipse.ui.texteditor.IEditorStatusLine;
118 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
119 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
120 import org.eclipse.ui.texteditor.ResourceAction;
121 import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
122 import org.eclipse.ui.texteditor.StatusTextEditor;
123 import org.eclipse.ui.texteditor.TextEditorAction;
124 import org.eclipse.ui.texteditor.TextOperationAction;
125 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
128 * PHP specific text editor.
130 public abstract class PHPEditor extends StatusTextEditor implements IViewPartInputProvider { // extends TextEditor {
131 class SelectionChangedListener implements ISelectionChangedListener {
132 public void selectionChanged(SelectionChangedEvent event) {
133 doSelectionChanged(event);
140 class MouseClickListener
147 IPropertyChangeListener,
151 /** The session is active. */
152 private boolean fActive;
154 /** The currently active style range. */
155 private IRegion fActiveRegion;
156 /** The currently active style range as position. */
157 private Position fRememberedPosition;
158 /** The hand cursor. */
159 private Cursor fCursor;
161 /** The link color. */
162 private Color fColor;
163 /** The key modifier mask. */
164 private int fKeyModifierMask;
166 public void deactivate() {
170 public void deactivate(boolean redrawAll) {
174 repairRepresentation(redrawAll);
178 public void install() {
180 ISourceViewer sourceViewer = getSourceViewer();
181 if (sourceViewer == null)
184 StyledText text = sourceViewer.getTextWidget();
185 if (text == null || text.isDisposed())
188 updateColor(sourceViewer);
190 sourceViewer.addTextInputListener(this);
192 IDocument document = sourceViewer.getDocument();
193 if (document != null)
194 document.addDocumentListener(this);
196 text.addKeyListener(this);
197 text.addMouseListener(this);
198 text.addMouseMoveListener(this);
199 text.addFocusListener(this);
200 text.addPaintListener(this);
202 updateKeyModifierMask();
204 IPreferenceStore preferenceStore = getPreferenceStore();
205 preferenceStore.addPropertyChangeListener(this);
208 private void updateKeyModifierMask() {
209 String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
210 fKeyModifierMask = computeStateMask(modifiers);
211 if (fKeyModifierMask == -1) {
212 // Fallback to stored state mask
213 fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
217 private int computeStateMask(String modifiers) {
218 if (modifiers == null)
221 if (modifiers.length() == 0)
225 StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$
226 while (modifierTokenizer.hasMoreTokens()) {
227 int modifier = EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
228 if (modifier == 0 || (stateMask & modifier) == modifier)
230 stateMask = stateMask | modifier;
235 public void uninstall() {
237 if (fColor != null) {
242 if (fCursor != null) {
247 ISourceViewer sourceViewer = getSourceViewer();
248 if (sourceViewer == null)
251 sourceViewer.removeTextInputListener(this);
253 IDocument document = sourceViewer.getDocument();
254 if (document != null)
255 document.removeDocumentListener(this);
257 IPreferenceStore preferenceStore = getPreferenceStore();
258 if (preferenceStore != null)
259 preferenceStore.removePropertyChangeListener(this);
261 StyledText text = sourceViewer.getTextWidget();
262 if (text == null || text.isDisposed())
265 text.removeKeyListener(this);
266 text.removeMouseListener(this);
267 text.removeMouseMoveListener(this);
268 text.removeFocusListener(this);
269 text.removePaintListener(this);
273 * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
275 public void propertyChange(PropertyChangeEvent event) {
276 if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
277 ISourceViewer viewer = getSourceViewer();
280 } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
281 updateKeyModifierMask();
285 private void updateColor(ISourceViewer viewer) {
289 StyledText text = viewer.getTextWidget();
290 if (text == null || text.isDisposed())
293 Display display = text.getDisplay();
294 fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display);
298 * Creates a color from the information stored in the given preference store.
299 * Returns <code>null</code> if there is no such information available.
301 private Color createColor(IPreferenceStore store, String key, Display display) {
305 if (store.contains(key)) {
307 if (store.isDefault(key))
308 rgb = PreferenceConverter.getDefaultColor(store, key);
310 rgb = PreferenceConverter.getColor(store, key);
313 return new Color(display, rgb);
319 private void repairRepresentation() {
320 repairRepresentation(false);
323 private void repairRepresentation(boolean redrawAll) {
325 if (fActiveRegion == null)
328 ISourceViewer viewer = getSourceViewer();
329 if (viewer != null) {
332 int offset = fActiveRegion.getOffset();
333 int length = fActiveRegion.getLength();
336 if (!redrawAll && viewer instanceof ITextViewerExtension2)
337 ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length);
339 viewer.invalidateTextPresentation();
342 if (viewer instanceof ITextViewerExtension3) {
343 ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
344 offset = extension.modelOffset2WidgetOffset(offset);
346 offset -= viewer.getVisibleRegion().getOffset();
349 StyledText text = viewer.getTextWidget();
351 text.redrawRange(offset, length, true);
352 } catch (IllegalArgumentException x) {
353 PHPeclipsePlugin.log(x);
357 fActiveRegion = null;
360 // will eventually be replaced by a method provided by jdt.core
361 private IRegion selectWord(IDocument document, int anchor) {
367 while (offset >= 0) {
368 c = document.getChar(offset);
369 if (!Character.isJavaIdentifierPart(c))
377 int length = document.getLength();
379 while (offset < length) {
380 c = document.getChar(offset);
381 if (!Character.isJavaIdentifierPart(c))
389 return new Region(start, 0);
391 return new Region(start + 1, end - start - 1);
393 } catch (BadLocationException x) {
398 IRegion getCurrentTextRegion(ISourceViewer viewer) {
400 int offset = getCurrentTextOffset(viewer);
405 // IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
406 // if (input == null)
411 // IJavaElement[] elements= null;
412 // synchronized (input) {
413 // elements= ((ICodeAssist) input).codeSelect(offset, 0);
416 // if (elements == null || elements.length == 0)
419 // return selectWord(viewer.getDocument(), offset);
421 // } catch (JavaModelException e) {
426 private int getCurrentTextOffset(ISourceViewer viewer) {
429 StyledText text = viewer.getTextWidget();
430 if (text == null || text.isDisposed())
433 Display display = text.getDisplay();
434 Point absolutePosition = display.getCursorLocation();
435 Point relativePosition = text.toControl(absolutePosition);
437 int widgetOffset = text.getOffsetAtLocation(relativePosition);
438 if (viewer instanceof ITextViewerExtension3) {
439 ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
440 return extension.widgetOffset2ModelOffset(widgetOffset);
442 return widgetOffset + viewer.getVisibleRegion().getOffset();
445 } catch (IllegalArgumentException e) {
450 private void highlightRegion(ISourceViewer viewer, IRegion region) {
452 if (region.equals(fActiveRegion))
455 repairRepresentation();
457 StyledText text = viewer.getTextWidget();
458 if (text == null || text.isDisposed())
465 if (viewer instanceof ITextViewerExtension3) {
466 ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
467 IRegion widgetRange = extension.modelRange2WidgetRange(region);
468 if (widgetRange == null)
471 offset = widgetRange.getOffset();
472 length = widgetRange.getLength();
475 offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
476 length = region.getLength();
479 StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
480 Color foregroundColor = fColor;
481 Color backgroundColor = oldStyleRange == null ? text.getBackground() : oldStyleRange.background;
482 StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor);
483 text.setStyleRange(styleRange);
486 text.redrawRange(offset, length, true);
488 fActiveRegion = region;
491 private void activateCursor(ISourceViewer viewer) {
492 StyledText text = viewer.getTextWidget();
493 if (text == null || text.isDisposed())
495 Display display = text.getDisplay();
497 fCursor = new Cursor(display, SWT.CURSOR_HAND);
498 text.setCursor(fCursor);
501 private void resetCursor(ISourceViewer viewer) {
502 StyledText text = viewer.getTextWidget();
503 if (text != null && !text.isDisposed())
504 text.setCursor(null);
506 if (fCursor != null) {
513 * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
515 public void keyPressed(KeyEvent event) {
522 if (event.keyCode != fKeyModifierMask) {
529 // removed for #25871
531 // ISourceViewer viewer= getSourceViewer();
532 // if (viewer == null)
535 // IRegion region= getCurrentTextRegion(viewer);
536 // if (region == null)
539 // highlightRegion(viewer, region);
540 // activateCursor(viewer);
544 * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
546 public void keyReleased(KeyEvent event) {
555 * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
557 public void mouseDoubleClick(MouseEvent e) {
560 * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
562 public void mouseDown(MouseEvent event) {
567 if (event.stateMask != fKeyModifierMask) {
572 if (event.button != 1) {
579 * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
581 public void mouseUp(MouseEvent e) {
591 boolean wasActive = fCursor != null;
596 IAction action = getAction("OpenEditor"); //$NON-NLS-1$
603 * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
605 public void mouseMove(MouseEvent event) {
607 if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) {
613 if (event.stateMask != fKeyModifierMask)
615 // modifier was already pressed
619 ISourceViewer viewer = getSourceViewer();
620 if (viewer == null) {
625 StyledText text = viewer.getTextWidget();
626 if (text == null || text.isDisposed()) {
631 if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0) {
636 IRegion region = getCurrentTextRegion(viewer);
637 if (region == null || region.getLength() == 0) {
638 repairRepresentation();
642 highlightRegion(viewer, region);
643 activateCursor(viewer);
647 * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
649 public void focusGained(FocusEvent e) {
653 * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
655 public void focusLost(FocusEvent event) {
660 * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
662 public void documentAboutToBeChanged(DocumentEvent event) {
663 if (fActive && fActiveRegion != null) {
664 fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength());
666 event.getDocument().addPosition(fRememberedPosition);
667 } catch (BadLocationException x) {
668 fRememberedPosition = null;
674 * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
676 public void documentChanged(DocumentEvent event) {
677 if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
678 event.getDocument().removePosition(fRememberedPosition);
679 fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength());
681 fRememberedPosition = null;
683 ISourceViewer viewer = getSourceViewer();
684 if (viewer != null) {
685 StyledText widget = viewer.getTextWidget();
686 if (widget != null && !widget.isDisposed()) {
687 widget.getDisplay().asyncExec(new Runnable() {
697 * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
699 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
700 if (oldInput == null)
703 oldInput.removeDocumentListener(this);
707 * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
709 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
710 if (newInput == null)
712 newInput.addDocumentListener(this);
716 * @see PaintListener#paintControl(PaintEvent)
718 public void paintControl(PaintEvent event) {
719 if (fActiveRegion == null)
722 ISourceViewer viewer = getSourceViewer();
726 StyledText text = viewer.getTextWidget();
727 if (text == null || text.isDisposed())
733 if (viewer instanceof ITextViewerExtension3) {
735 ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
736 IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length));
737 if (widgetRange == null)
740 offset = widgetRange.getOffset();
741 length = widgetRange.getLength();
745 IRegion region = viewer.getVisibleRegion();
746 if (!includes(region, fActiveRegion))
749 offset = fActiveRegion.getOffset() - region.getOffset();
750 length = fActiveRegion.getLength();
754 Point minLocation = getMinimumLocation(text, offset, length);
755 Point maxLocation = getMaximumLocation(text, offset, length);
757 int x1 = minLocation.x;
758 int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
759 int y = minLocation.y + text.getLineHeight() - 1;
762 if (fColor != null && !fColor.isDisposed())
763 gc.setForeground(fColor);
764 gc.drawLine(x1, y, x2, y);
767 private boolean includes(IRegion region, IRegion position) {
768 return position.getOffset() >= region.getOffset()
769 && position.getOffset() + position.getLength() <= region.getOffset() + region.getLength();
772 private Point getMinimumLocation(StyledText text, int offset, int length) {
773 Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
775 for (int i = 0; i <= length; i++) {
776 Point location = text.getLocationAtOffset(offset + i);
778 if (location.x < minLocation.x)
779 minLocation.x = location.x;
780 if (location.y < minLocation.y)
781 minLocation.y = location.y;
787 private Point getMaximumLocation(StyledText text, int offset, int length) {
788 Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
790 for (int i = 0; i <= length; i++) {
791 Point location = text.getLocationAtOffset(offset + i);
793 if (location.x > maxLocation.x)
794 maxLocation.x = location.x;
795 if (location.y > maxLocation.y)
796 maxLocation.y = location.y;
804 * This action dispatches into two behaviours: If there is no current text
805 * hover, the javadoc is displayed using information presenter. If there is
806 * a current text hover, it is converted into a information presenter in
807 * order to make it sticky.
809 class InformationDispatchAction extends TextEditorAction {
811 /** The wrapped text operation action. */
812 private final TextOperationAction fTextOperationAction;
815 * Creates a dispatch action.
817 public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) {
818 super(resourceBundle, prefix, PHPEditor.this);
819 if (textOperationAction == null)
820 throw new IllegalArgumentException();
821 fTextOperationAction = textOperationAction;
825 * @see org.eclipse.jface.action.IAction#run()
829 ISourceViewer sourceViewer = getSourceViewer();
830 if (sourceViewer == null) {
831 fTextOperationAction.run();
835 if (!(sourceViewer instanceof ITextViewerExtension2)) {
836 fTextOperationAction.run();
840 ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
842 // does a text hover exist?
843 ITextHover textHover = textViewerExtension2.getCurrentTextHover();
844 if (textHover == null) {
845 fTextOperationAction.run();
849 Point hoverEventLocation = textViewerExtension2.getHoverEventLocation();
850 int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y);
852 fTextOperationAction.run();
857 // get the text hover content
858 IDocument document = sourceViewer.getDocument();
859 String contentType = document.getContentType(offset);
861 final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset);
862 if (hoverRegion == null)
865 final String hoverInfo = textHover.getHoverInfo(sourceViewer, hoverRegion);
867 // with information provider
868 IInformationProvider informationProvider = new IInformationProvider() {
870 * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int)
872 public IRegion getSubject(ITextViewer textViewer, int offset) {
876 * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
878 public String getInformation(ITextViewer textViewer, IRegion subject) {
883 fInformationPresenter.setOffset(offset);
884 fInformationPresenter.setInformationProvider(informationProvider, contentType);
885 fInformationPresenter.showInformation();
887 } catch (BadLocationException e) {
891 // modified version from TextViewer
892 private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
894 StyledText styledText = textViewer.getTextWidget();
895 IDocument document = textViewer.getDocument();
897 if (document == null)
901 int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y));
902 if (textViewer instanceof ITextViewerExtension3) {
903 ITextViewerExtension3 extension = (ITextViewerExtension3) textViewer;
904 return extension.widgetOffset2ModelOffset(widgetLocation);
906 IRegion visibleRegion = textViewer.getVisibleRegion();
907 return widgetLocation + visibleRegion.getOffset();
909 } catch (IllegalArgumentException e) {
916 static protected class AnnotationAccess implements IAnnotationAccess {
918 * @see org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
920 public Object getType(Annotation annotation) {
921 if (annotation instanceof IJavaAnnotation) {
922 IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
923 if (javaAnnotation.isRelevant())
924 return javaAnnotation.getAnnotationType();
930 * @see org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
932 public boolean isMultiLine(Annotation annotation) {
937 * @see org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
939 public boolean isTemporary(Annotation annotation) {
940 if (annotation instanceof IJavaAnnotation) {
941 IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
942 if (javaAnnotation.isRelevant())
943 return javaAnnotation.isTemporary();
949 private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
951 * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
953 public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
954 handlePreferencePropertyChanged(event);
957 /** Preference key for showing the line number ruler */
958 private final static String LINE_NUMBER_RULER = PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
959 /** Preference key for the foreground color of the line numbers */
960 private final static String LINE_NUMBER_COLOR = PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
961 /** Preference key for the link color */
962 private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
964 // protected PHPActionGroup fActionGroups;
965 /** The outline page */
966 private AbstractContentOutlinePage fOutlinePage;
968 // protected PHPSyntaxParserThread fValidationThread = null;
970 // private IPreferenceStore fPHPPrefStore;
971 /** The selection changed listener */
972 protected ISelectionChangedListener fSelectionChangedListener = new SelectionChangedListener();
974 /** The editor's bracket matcher */
975 private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
976 /** The line number ruler column */
977 private LineNumberRulerColumn fLineNumberRulerColumn;
978 /** This editor's encoding support */
979 private DefaultEncodingSupport fEncodingSupport;
980 /** The mouse listener */
981 private MouseClickListener fMouseListener;
983 protected CompositeActionGroup fActionGroups;
984 /** The standard action groups added to the menu */
985 protected GenerateActionGroup fGenerateActionGroup;
986 protected CompositeActionGroup fContextMenuGroup;
988 /** The information presenter. */
989 private InformationPresenter fInformationPresenter;
990 /** The annotation access */
991 protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
992 /** The overview ruler */
993 protected OverviewRuler isOverviewRulerVisible;
994 /** The source viewer decoration support */
995 protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
996 /** The overview ruler */
997 protected OverviewRuler fOverviewRuler;
999 /** The preference property change listener for java core. */
1000 private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
1003 * Default constructor.
1005 public PHPEditor() {
1007 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1008 setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this));
1009 setRangeIndicator(new DefaultRangeIndicator());
1010 setPreferenceStore(PHPeclipsePlugin.getDefault().getPreferenceStore());
1012 // don't activate this scope without synchronizing plugin.xml !!!
1013 // setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$
1015 // if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
1016 // fUpdater= new OutlinePageSelectionUpdater();
1020 // * @see IMember#getCompilationUnit()
1022 // public ICompilationUnit getCompilationUnit() {
1026 // * @see org.phpeclipse.phpdt.internal.compiler.env.ICompilationUnit#getContents()
1028 // public char[] getContents() {
1029 // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1031 // return doc.get().toCharArray();
1034 * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
1036 protected void updatePropertyDependentActions() {
1037 super.updatePropertyDependentActions();
1038 if (fEncodingSupport != null)
1039 fEncodingSupport.reset();
1043 * Update the hovering behavior depending on the preferences.
1045 private void updateHoverBehavior() {
1046 SourceViewerConfiguration configuration = getSourceViewerConfiguration();
1047 String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
1049 for (int i = 0; i < types.length; i++) {
1051 String t = types[i];
1053 int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
1055 ISourceViewer sourceViewer = getSourceViewer();
1056 if (sourceViewer instanceof ITextViewerExtension2) {
1057 if (stateMasks != null) {
1058 for (int j = 0; j < stateMasks.length; j++) {
1059 int stateMask = stateMasks[j];
1060 ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
1061 ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
1064 ITextHover textHover = configuration.getTextHover(sourceViewer, t);
1065 ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
1068 sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
1073 * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1075 public Object getViewPartInput() {
1076 return getEditorInput().getAdapter(IResource.class);
1080 * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
1081 * widgets.Composite)
1083 public void createPartControl(Composite parent) {
1084 super.createPartControl(parent);
1086 fSourceViewerDecorationSupport.install(getPreferenceStore());
1088 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1089 preferences.addPropertyChangeListener(fPropertyChangeListener);
1091 IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
1092 public IInformationControl createInformationControl(Shell parent) {
1093 boolean cutDown = false;
1094 int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
1095 return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown));
1099 fInformationPresenter = new InformationPresenter(informationControlCreator);
1100 fInformationPresenter.setSizeConstraints(60, 10, true, true);
1101 fInformationPresenter.install(getSourceViewer());
1105 * Returns this document's complete text.
1107 * @return the document's complete text
1109 public String get() {
1110 IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1115 * Returns the standard action group of this editor.
1117 protected ActionGroup getActionGroup() {
1118 return fActionGroups;
1121 public AbstractContentOutlinePage getfOutlinePage() {
1122 return fOutlinePage;
1125 /** The <code>PHPEditor</code> implementation of this
1126 * <code>AbstractTextEditor</code> method extend the
1127 * actions to add those specific to the receiver
1129 protected void createActions() {
1130 super.createActions();
1132 ResourceAction resAction = new AddTaskAction(PHPEditorMessages.getResourceBundle(), "AddTask.", this); //$NON-NLS-1$
1133 resAction.setHelpContextId(IAbstractTextEditorHelpContextIds.ADD_TASK_ACTION);
1134 resAction.setActionDefinitionId(ITextEditorActionDefinitionIds.ADD_TASK);
1135 setAction(ITextEditorActionConstants.ADD_TASK, resAction);
1137 resAction = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
1138 resAction = new InformationDispatchAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
1139 resAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_JAVADOC);
1140 setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
1141 // WorkbenchHelp.setHelp(resAction, IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
1147 new TextOperationAction(
1148 PHPEditorMessages.getResourceBundle(),
1149 "ContentAssistTip.",
1151 ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION));
1153 action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
1154 action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
1155 setAction("ContentAssistProposal", action); //$NON-NLS-1$
1156 markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
1157 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
1159 fEncodingSupport = new DefaultEncodingSupport();
1160 fEncodingSupport.initialize(this);
1162 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
1163 action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
1164 setAction("Comment", action); //$NON-NLS-1$
1165 markAsStateDependentAction("Comment", true); //$NON-NLS-1$
1166 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION);
1168 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
1169 action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
1170 setAction("Uncomment", action); //$NON-NLS-1$
1171 markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
1172 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION);
1174 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
1175 action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
1176 setAction("Format", action); //$NON-NLS-1$
1177 markAsStateDependentAction("Format", true); //$NON-NLS-1$
1178 markAsSelectionDependentAction("Format", true); //$NON-NLS-1$
1179 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION);
1181 action = new GotoMatchingBracketAction(this);
1182 action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
1183 setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
1185 fGenerateActionGroup = new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
1187 fActionGroups = new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
1189 // We have to keep the context menu group separate to have better control over positioning
1190 fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
1192 // new LocalHistoryActionGroup(this, ITextEditorActionConstants.GROUP_EDIT)});
1194 // if (fValidationThread == null) {
1195 // fValidationThread =
1196 // new PHPSyntaxParserThread(this, getSourceViewer());
1197 // //Thread defaults
1199 // fValidationThread.start();
1202 // fValidationThread.setText(getSourceViewer().getTextWidget().getText());
1205 /** The <code>PHPEditor</code> implementation of this
1206 * <code>AbstractTextEditor</code> method performs any extra
1207 * disposal actions required by the php editor.
1209 public void dispose() {
1210 // PHPEditorEnvironment.disconnect(this);
1211 if (fOutlinePage != null)
1212 fOutlinePage.setInput(null);
1214 if (fActionGroups != null)
1215 fActionGroups.dispose();
1217 if (isBrowserLikeLinks())
1218 disableBrowserLikeLinks();
1220 if (fEncodingSupport != null) {
1221 fEncodingSupport.dispose();
1222 fEncodingSupport = null;
1225 if (fPropertyChangeListener != null) {
1226 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1227 preferences.removePropertyChangeListener(fPropertyChangeListener);
1228 fPropertyChangeListener = null;
1231 if (fSourceViewerDecorationSupport != null) {
1232 fSourceViewerDecorationSupport.dispose();
1233 fSourceViewerDecorationSupport = null;
1236 if (fBracketMatcher != null) {
1237 fBracketMatcher.dispose();
1238 fBracketMatcher = null;
1243 /** The <code>PHPEditor</code> implementation of this
1244 * <code>AbstractTextEditor</code> method performs any extra
1245 * revert behavior required by the php editor.
1247 public void doRevertToSaved() {
1248 super.doRevertToSaved();
1249 if (fOutlinePage != null)
1250 fOutlinePage.update();
1253 /** The <code>PHPEditor</code> implementation of this
1254 * <code>AbstractTextEditor</code> method performs any extra
1255 * save behavior required by the php editor.
1257 public void doSave(IProgressMonitor monitor) {
1258 super.doSave(monitor);
1259 // compile or not, according to the user preferences
1260 // IPreferenceStore store = getPreferenceStore();
1262 // the parse on save was changed to the eclipse "builders" concept
1263 // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
1264 // IAction a = PHPParserAction.getInstance();
1269 // if (SWT.getPlatform().equals("win32")) {
1270 // IAction a = ShowExternalPreviewAction.getInstance();
1274 if (fOutlinePage != null)
1275 fOutlinePage.update();
1278 /** The <code>PHPEditor</code> implementation of this
1279 * <code>AbstractTextEditor</code> method performs any extra
1280 * save as behavior required by the php editor.
1282 public void doSaveAs() {
1284 if (fOutlinePage != null)
1285 fOutlinePage.update();
1288 * @see StatusTextEditor#getStatusHeader(IStatus)
1290 protected String getStatusHeader(IStatus status) {
1291 if (fEncodingSupport != null) {
1292 String message = fEncodingSupport.getStatusHeader(status);
1293 if (message != null)
1296 return super.getStatusHeader(status);
1300 * @see StatusTextEditor#getStatusBanner(IStatus)
1302 protected String getStatusBanner(IStatus status) {
1303 if (fEncodingSupport != null) {
1304 String message = fEncodingSupport.getStatusBanner(status);
1305 if (message != null)
1308 return super.getStatusBanner(status);
1312 * @see StatusTextEditor#getStatusMessage(IStatus)
1314 protected String getStatusMessage(IStatus status) {
1315 if (fEncodingSupport != null) {
1316 String message = fEncodingSupport.getStatusMessage(status);
1317 if (message != null)
1320 return super.getStatusMessage(status);
1322 /** The <code>PHPEditor</code> implementation of this
1323 * <code>AbstractTextEditor</code> method performs sets the
1324 * input of the outline page after AbstractTextEditor has set input.
1326 protected void doSetInput(IEditorInput input) throws CoreException {
1327 super.doSetInput(input);
1329 if (fEncodingSupport != null)
1330 fEncodingSupport.reset();
1331 if (fOutlinePage != null)
1332 fOutlinePage.setInput(input);
1333 // setOutlinePageInput(fOutlinePage, input);
1337 * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1339 // public Object getViewPartInput() {
1340 // return getEditorInput().getAdapter(IFile.class);
1343 /** The <code>PHPEditor</code> implementation of this
1344 * <code>AbstractTextEditor</code> method adds any
1345 * PHPEditor specific entries.
1347 public void editorContextMenuAboutToShow(MenuManager menu) {
1348 super.editorContextMenuAboutToShow(menu);
1349 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
1350 menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
1352 ActionContext context = new ActionContext(getSelectionProvider().getSelection());
1353 fContextMenuGroup.setContext(context);
1354 fContextMenuGroup.fillContextMenu(menu);
1355 fContextMenuGroup.setContext(null);
1356 // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
1358 // ActionContext context =
1359 // new ActionContext(getSelectionProvider().getSelection());
1360 // fContextMenuGroup.setContext(context);
1361 // fContextMenuGroup.fillContextMenu(menu);
1362 // fContextMenuGroup.setContext(null);
1366 * Creates the outline page used with this editor.
1368 protected AbstractContentOutlinePage createOutlinePage() {
1370 AbstractContentOutlinePage page = new PHPContentOutlinePage(getDocumentProvider(), this);
1372 page.addSelectionChangedListener(fSelectionChangedListener);
1373 // setOutlinePageInput(page, getEditorInput());
1374 if (getEditorInput() != null)
1375 fOutlinePage.setInput(getEditorInput());
1381 * Informs the editor that its outliner has been closed.
1383 public void outlinePageClosed() {
1384 if (fOutlinePage != null) {
1385 fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
1386 fOutlinePage = null;
1387 resetHighlightRange();
1390 protected void updateStateDependentActions() {
1391 super.updateStateDependentActions();
1392 fGenerateActionGroup.editorStateChanged();
1395 /** The <code>PHPEditor</code> implementation of this
1396 * <code>AbstractTextEditor</code> method performs gets
1397 * the java content outline page if request is for a an
1400 public Object getAdapter(Class required) {
1401 if (IContentOutlinePage.class.equals(required)) {
1402 if (fOutlinePage == null) {
1403 fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
1404 if (getEditorInput() != null)
1405 fOutlinePage.setInput(getEditorInput());
1407 return fOutlinePage;
1410 if (IEncodingSupport.class.equals(required))
1411 return fEncodingSupport;
1413 return super.getAdapter(required);
1416 protected void doSelectionChanged(SelectionChangedEvent event) {
1418 // ISourceReference reference= null;
1420 // ISelection selection= event.getSelection();
1421 // Iterator iter= ((IStructuredSelection) selection).iterator();
1422 // while (iter.hasNext()) {
1423 // Object o= iter.next();
1424 // if (o instanceof ISourceReference) {
1425 // reference= (ISourceReference) o;
1429 if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
1430 PHPeclipsePlugin.getActivePage().bringToTop(this);
1433 // editingScriptStarted();
1434 // setSelection(reference, !isActivePart());
1436 // editingScriptEnded();
1440 protected boolean isActivePart() {
1441 IWorkbenchWindow window = getSite().getWorkbenchWindow();
1442 IPartService service = window.getPartService();
1443 IWorkbenchPart part = service.getActivePart();
1444 return part != null && part.equals(this);
1448 // public void openContextHelp() {
1449 // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1450 // ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
1451 // int pos = selection.getOffset();
1452 // String word = getFunctionName(doc, pos);
1453 // openContextHelp(word);
1456 // private void openContextHelp(String word) {
1460 // public static void open(String word) {
1461 // IHelp help = WorkbenchHelp.getHelpSupport();
1462 // if (help != null) {
1463 // IHelpResource helpResource = new PHPFunctionHelpResource(word);
1464 // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
1466 // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
1470 // private String getFunctionName(IDocument doc, int pos) {
1471 // Point word = PHPWordExtractor.findWord(doc, pos);
1472 // if (word != null) {
1474 // return doc.get(word.x, word.y).replace('_', '-');
1475 // } catch (BadLocationException e) {
1482 * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1484 protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1488 ISourceViewer sourceViewer = getSourceViewer();
1489 if (sourceViewer == null)
1492 String property = event.getProperty();
1494 if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
1495 Object value = event.getNewValue();
1496 if (value instanceof Integer) {
1497 sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
1498 } else if (value instanceof String) {
1499 sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
1504 if (OVERVIEW_RULER.equals(property)) {
1505 if (isOverviewRulerVisible())
1506 showOverviewRuler();
1508 hideOverviewRuler();
1512 if (LINE_NUMBER_RULER.equals(property)) {
1513 if (isLineNumberRulerVisible())
1514 showLineNumberRuler();
1516 hideLineNumberRuler();
1520 if (fLineNumberRulerColumn != null
1521 && (LINE_NUMBER_COLOR.equals(property)
1522 || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
1523 || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
1525 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
1528 if (isJavaEditorHoverProperty(property)) {
1529 updateHoverBehavior();
1533 super.handlePreferenceStoreChanged(event);
1538 // * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1540 // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1544 // ISourceViewer sourceViewer = getSourceViewer();
1545 // if (sourceViewer == null)
1548 // String property = event.getProperty();
1550 // // if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
1551 // // Object value= event.getNewValue();
1552 // // if (value instanceof Integer) {
1553 // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
1554 // // } else if (value instanceof String) {
1555 // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
1560 // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
1561 // if (isLineNumberRulerVisible())
1562 // showLineNumberRuler();
1564 // hideLineNumberRuler();
1568 // if (fLineNumberRulerColumn != null
1569 // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
1570 // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
1571 // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
1573 // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
1577 // super.handlePreferenceStoreChanged(event);
1581 private boolean isJavaEditorHoverProperty(String property) {
1582 return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
1583 || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
1584 || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
1585 || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
1586 || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
1587 || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
1588 || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
1589 || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
1593 * Shows the line number ruler column.
1595 private void showLineNumberRuler() {
1596 IVerticalRuler v = getVerticalRuler();
1597 if (v instanceof CompositeRuler) {
1598 CompositeRuler c = (CompositeRuler) v;
1599 c.addDecorator(1, createLineNumberRulerColumn());
1603 * Return whether the browser like links should be enabled
1604 * according to the preference store settings.
1605 * @return <code>true</code> if the browser like links should be enabled
1607 private boolean isBrowserLikeLinks() {
1608 IPreferenceStore store = getPreferenceStore();
1609 return store.getBoolean(BROWSER_LIKE_LINKS);
1613 * Enables browser like links.
1615 private void enableBrowserLikeLinks() {
1616 if (fMouseListener == null) {
1617 fMouseListener = new MouseClickListener();
1618 fMouseListener.install();
1623 * Disables browser like links.
1625 private void disableBrowserLikeLinks() {
1626 if (fMouseListener != null) {
1627 fMouseListener.uninstall();
1628 fMouseListener = null;
1632 * Handles a property change event describing a change
1633 * of the java core's preferences and updates the preference
1634 * related editor properties.
1636 * @param event the property change event
1638 protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1639 // if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
1640 // ISourceViewer sourceViewer= getSourceViewer();
1641 // if (sourceViewer != null && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())))
1642 // sourceViewer.invalidateTextPresentation();
1647 * Return whether the line number ruler column should be
1648 * visible according to the preference store settings.
1649 * @return <code>true</code> if the line numbers should be visible
1651 private boolean isLineNumberRulerVisible() {
1652 IPreferenceStore store = getPreferenceStore();
1653 return store.getBoolean(LINE_NUMBER_RULER);
1656 * Hides the line number ruler column.
1658 private void hideLineNumberRuler() {
1659 IVerticalRuler v = getVerticalRuler();
1660 if (v instanceof CompositeRuler) {
1661 CompositeRuler c = (CompositeRuler) v;
1663 c.removeDecorator(1);
1664 } catch (Throwable e) {
1670 * Initializes the given line number ruler column from the preference store.
1671 * @param rulerColumn the ruler column to be initialized
1673 protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
1674 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1675 IColorManager manager = textTools.getColorManager();
1677 IPreferenceStore store = getPreferenceStore();
1678 if (store != null) {
1682 if (store.contains(LINE_NUMBER_COLOR)) {
1683 if (store.isDefault(LINE_NUMBER_COLOR))
1684 rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
1686 rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
1688 rulerColumn.setForeground(manager.getColor(rgb));
1692 if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
1693 if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
1694 if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
1695 rgb = PreferenceConverter.getDefaultColor(store, PREFERENCE_COLOR_BACKGROUND);
1697 rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
1700 rulerColumn.setBackground(manager.getColor(rgb));
1705 * Creates a new line number ruler column that is appropriately initialized.
1707 protected IVerticalRulerColumn createLineNumberRulerColumn() {
1708 fLineNumberRulerColumn = new LineNumberRulerColumn();
1709 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
1710 return fLineNumberRulerColumn;
1714 * @see AbstractTextEditor#createVerticalRuler()
1716 protected IVerticalRuler createVerticalRuler() {
1717 CompositeRuler ruler = new CompositeRuler();
1718 ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
1719 if (isLineNumberRulerVisible())
1720 ruler.addDecorator(1, createLineNumberRulerColumn());
1724 private static IRegion getSignedSelection(ITextViewer viewer) {
1726 StyledText text = viewer.getTextWidget();
1727 int caretOffset = text.getCaretOffset();
1728 Point selection = text.getSelection();
1732 if (caretOffset == selection.x) {
1733 offset = selection.y;
1734 length = selection.x - selection.y;
1738 offset = selection.x;
1739 length = selection.y - selection.x;
1742 return new Region(offset, length);
1745 /** Preference key for matching brackets */
1746 protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
1747 /** Preference key for matching brackets color */
1748 protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
1749 /** Preference key for highlighting current line */
1750 protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
1751 /** Preference key for highlight color of current line */
1752 protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
1753 /** Preference key for showing print marging ruler */
1754 protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
1755 /** Preference key for print margin ruler color */
1756 protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
1757 /** Preference key for print margin ruler column */
1758 protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
1759 /** Preference key for error indication */
1760 protected final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION;
1761 /** Preference key for error color */
1762 protected final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
1763 /** Preference key for warning indication */
1764 protected final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION;
1765 /** Preference key for warning color */
1766 protected final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
1767 /** Preference key for task indication */
1768 protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
1769 /** Preference key for task color */
1770 protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
1771 /** Preference key for bookmark indication */
1772 protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
1773 /** Preference key for bookmark color */
1774 protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
1775 /** Preference key for search result indication */
1776 protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
1777 /** Preference key for search result color */
1778 protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
1779 /** Preference key for unknown annotation indication */
1780 protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
1781 /** Preference key for unknown annotation color */
1782 protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
1783 /** Preference key for shwoing the overview ruler */
1784 protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
1785 /** Preference key for error indication in overview ruler */
1786 protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
1787 /** Preference key for warning indication in overview ruler */
1788 protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER =
1789 PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
1790 /** Preference key for task indication in overview ruler */
1791 protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
1792 /** Preference key for bookmark indication in overview ruler */
1793 protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER =
1794 PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
1795 /** Preference key for search result indication in overview ruler */
1796 protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER =
1797 PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
1798 /** Preference key for unknown annotation indication in overview ruler */
1799 protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER =
1800 PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
1801 // /** Preference key for compiler task tags */
1802 // private final static String COMPILER_TASK_TAGS= JavaCore.COMPILER_TASK_TAGS;
1803 /** Preference key for browser like links */
1804 private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
1805 /** Preference key for key modifier of browser like links */
1806 private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
1808 * Preference key for key modifier mask of browser like links.
1809 * The value is only used if the value of <code>EDITOR_BROWSER_LIKE_LINKS</code>
1810 * cannot be resolved to valid SWT modifier bits.
1814 private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK =
1815 PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
1817 private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
1819 private static boolean isBracket(char character) {
1820 for (int i = 0; i != BRACKETS.length; ++i)
1821 if (character == BRACKETS[i])
1826 private static boolean isSurroundedByBrackets(IDocument document, int offset) {
1827 if (offset == 0 || offset == document.getLength())
1831 return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
1833 } catch (BadLocationException e) {
1838 protected void configureSourceViewerDecorationSupport() {
1840 fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
1842 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1843 AnnotationType.UNKNOWN,
1844 UNKNOWN_INDICATION_COLOR,
1846 UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
1848 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1849 AnnotationType.BOOKMARK,
1850 BOOKMARK_INDICATION_COLOR,
1851 BOOKMARK_INDICATION,
1852 BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
1854 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1855 AnnotationType.TASK,
1856 TASK_INDICATION_COLOR,
1858 TASK_INDICATION_IN_OVERVIEW_RULER,
1860 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1861 AnnotationType.SEARCH,
1862 SEARCH_RESULT_INDICATION_COLOR,
1863 SEARCH_RESULT_INDICATION,
1864 SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
1866 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1867 AnnotationType.WARNING,
1868 WARNING_INDICATION_COLOR,
1870 WARNING_INDICATION_IN_OVERVIEW_RULER,
1872 fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
1873 AnnotationType.ERROR,
1874 ERROR_INDICATION_COLOR,
1876 ERROR_INDICATION_IN_OVERVIEW_RULER,
1879 fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
1880 fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
1881 fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
1883 fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
1886 * Jumps to the matching bracket.
1888 public void gotoMatchingBracket() {
1890 ISourceViewer sourceViewer = getSourceViewer();
1891 IDocument document = sourceViewer.getDocument();
1892 if (document == null)
1895 IRegion selection = getSignedSelection(sourceViewer);
1897 int selectionLength = Math.abs(selection.getLength());
1898 if (selectionLength > 1) {
1899 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
1900 sourceViewer.getTextWidget().getDisplay().beep();
1905 int sourceCaretOffset = selection.getOffset() + selection.getLength();
1906 if (isSurroundedByBrackets(document, sourceCaretOffset))
1907 sourceCaretOffset -= selection.getLength();
1909 IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
1910 if (region == null) {
1911 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
1912 sourceViewer.getTextWidget().getDisplay().beep();
1916 int offset = region.getOffset();
1917 int length = region.getLength();
1922 int anchor = fBracketMatcher.getAnchor();
1923 int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
1925 boolean visible = false;
1926 if (sourceViewer instanceof ITextViewerExtension3) {
1927 ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
1928 visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
1930 IRegion visibleRegion = sourceViewer.getVisibleRegion();
1931 visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
1935 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
1936 sourceViewer.getTextWidget().getDisplay().beep();
1940 if (selection.getLength() < 0)
1941 targetOffset -= selection.getLength();
1943 sourceViewer.setSelectedRange(targetOffset, selection.getLength());
1944 sourceViewer.revealRange(targetOffset, selection.getLength());
1947 * Ses the given message as error message to this editor's status line.
1948 * @param msg message to be set
1950 protected void setStatusLineErrorMessage(String msg) {
1951 IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
1952 if (statusLine != null)
1953 statusLine.setMessage(true, msg, null);
1957 * Returns a segmentation of the line of the given document appropriate for bidi rendering.
1958 * The default implementation returns only the string literals of a php code line as segments.
1960 * @param document the document
1961 * @param lineOffset the offset of the line
1962 * @return the line's bidi segmentation
1963 * @throws BadLocationException in case lineOffset is not valid in document
1965 public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException {
1967 IRegion line = document.getLineInformationOfOffset(lineOffset);
1968 ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength());
1970 List segmentation = new ArrayList();
1971 for (int i = 0; i < linePartitioning.length; i++) {
1972 if (IPHPPartitionScannerConstants.PHP_STRING.equals(linePartitioning[i].getType()))
1973 segmentation.add(linePartitioning[i]);
1976 if (segmentation.size() == 0)
1979 int size = segmentation.size();
1980 int[] segments = new int[size * 2 + 1];
1983 for (int i = 0; i < size; i++) {
1984 ITypedRegion segment = (ITypedRegion) segmentation.get(i);
1989 int offset = segment.getOffset() - lineOffset;
1990 if (offset > segments[j - 1])
1991 segments[j++] = offset;
1993 if (offset + segment.getLength() >= line.getLength())
1996 segments[j++] = offset + segment.getLength();
1999 if (j < segments.length) {
2000 int[] result = new int[j];
2001 System.arraycopy(segments, 0, result, 0, j);
2008 * Returns a segmentation of the given line appropriate for bidi rendering. The default
2009 * implementation returns only the string literals of a php code line as segments.
2011 * @param lineOffset the offset of the line
2012 * @param line the content of the line
2013 * @return the line's bidi segmentation
2015 protected int[] getBidiLineSegments(int lineOffset, String line) {
2016 IDocumentProvider provider = getDocumentProvider();
2017 if (provider != null && line != null && line.length() > 0) {
2018 IDocument document = provider.getDocument(getEditorInput());
2019 if (document != null)
2021 return getBidiLineSegments(document, lineOffset);
2022 } catch (BadLocationException x) {
2030 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
2032 // protected final ISourceViewer createSourceViewer(
2033 // Composite parent,
2034 // IVerticalRuler ruler,
2036 // ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
2037 // StyledText text = viewer.getTextWidget();
2038 // text.addBidiSegmentListener(new BidiSegmentListener() {
2039 // public void lineGetSegments(BidiSegmentEvent event) {
2040 // event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
2043 // // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
2046 protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
2048 ISharedTextColors sharedColors = PHPeclipsePlugin.getDefault().getJavaTextTools().getColorManager();
2050 fOverviewRuler = new OverviewRuler(fAnnotationAccess, VERTICAL_RULER_WIDTH, sharedColors);
2051 fOverviewRuler.addHeaderAnnotationType(AnnotationType.WARNING);
2052 fOverviewRuler.addHeaderAnnotationType(AnnotationType.ERROR);
2054 ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler, fOverviewRuler, isOverviewRulerVisible(), styles);
2056 StyledText text = viewer.getTextWidget();
2057 text.addBidiSegmentListener(new BidiSegmentListener() {
2058 public void lineGetSegments(BidiSegmentEvent event) {
2059 event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
2063 // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
2065 fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(viewer, fOverviewRuler, fAnnotationAccess, sharedColors);
2066 configureSourceViewerDecorationSupport();
2071 protected void showOverviewRuler() {
2072 if (fOverviewRuler != null) {
2073 if (getSourceViewer() instanceof ISourceViewerExtension) {
2074 ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(true);
2075 fSourceViewerDecorationSupport.updateOverviewDecorations();
2080 protected void hideOverviewRuler() {
2081 if (getSourceViewer() instanceof ISourceViewerExtension) {
2082 fSourceViewerDecorationSupport.hideAnnotationOverview();
2083 ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(false);
2087 protected boolean isOverviewRulerVisible() {
2088 IPreferenceStore store = getPreferenceStore();
2089 return store.getBoolean(OVERVIEW_RULER);
2092 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
2094 protected ISourceViewer createJavaSourceViewer(
2096 IVerticalRuler ruler,
2097 IOverviewRuler overviewRuler,
2098 boolean isOverviewRulerVisible,
2100 return new SourceViewer(parent, ruler, overviewRuler, isOverviewRulerVisible(), styles);
2101 // return super.createSourceViewer(parent, ruler, styles);
2105 * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
2107 protected boolean affectsTextPresentation(PropertyChangeEvent event) {
2108 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
2109 return textTools.affectsBehavior(event);