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;
17 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
18 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
19 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
20 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
21 import net.sourceforge.phpdt.ui.IContextMenuConstants;
22 import net.sourceforge.phpdt.ui.PreferenceConstants;
23 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
24 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
25 import net.sourceforge.phpdt.ui.text.IColorManager;
26 import net.sourceforge.phpdt.ui.text.JavaTextTools;
27 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
28 import net.sourceforge.phpeclipse.phpeditor.php.IPHPPartitionScannerConstants;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.jface.action.Action;
34 import org.eclipse.jface.action.GroupMarker;
35 import org.eclipse.jface.action.IAction;
36 import org.eclipse.jface.action.MenuManager;
37 import org.eclipse.jface.action.Separator;
38 import org.eclipse.jface.preference.IPreferenceStore;
39 import org.eclipse.jface.preference.PreferenceConverter;
40 import org.eclipse.jface.text.BadLocationException;
41 import org.eclipse.jface.text.DefaultInformationControl;
42 import org.eclipse.jface.text.IDocument;
43 import org.eclipse.jface.text.IInformationControl;
44 import org.eclipse.jface.text.IInformationControlCreator;
45 import org.eclipse.jface.text.IRegion;
46 import org.eclipse.jface.text.ITextHover;
47 import org.eclipse.jface.text.ITextOperationTarget;
48 import org.eclipse.jface.text.ITextViewer;
49 import org.eclipse.jface.text.ITextViewerExtension2;
50 import org.eclipse.jface.text.ITextViewerExtension3;
51 import org.eclipse.jface.text.ITypedRegion;
52 import org.eclipse.jface.text.Region;
53 import org.eclipse.jface.text.information.InformationPresenter;
54 import org.eclipse.jface.text.source.AnnotationRulerColumn;
55 import org.eclipse.jface.text.source.CompositeRuler;
56 import org.eclipse.jface.text.source.ISourceViewer;
57 import org.eclipse.jface.text.source.IVerticalRuler;
58 import org.eclipse.jface.text.source.IVerticalRulerColumn;
59 import org.eclipse.jface.text.source.LineNumberRulerColumn;
60 import org.eclipse.jface.text.source.SourceViewerConfiguration;
61 import org.eclipse.jface.util.PropertyChangeEvent;
62 import org.eclipse.swt.SWT;
63 import org.eclipse.swt.custom.BidiSegmentEvent;
64 import org.eclipse.swt.custom.BidiSegmentListener;
65 import org.eclipse.swt.custom.StyledText;
66 import org.eclipse.swt.graphics.Point;
67 import org.eclipse.swt.graphics.RGB;
68 import org.eclipse.swt.widgets.Composite;
69 import org.eclipse.swt.widgets.Shell;
70 import org.eclipse.ui.IEditorInput;
71 import org.eclipse.ui.actions.ActionContext;
72 import org.eclipse.ui.actions.ActionGroup;
73 import org.eclipse.ui.texteditor.ContentAssistAction;
74 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
75 import org.eclipse.ui.texteditor.IDocumentProvider;
76 import org.eclipse.ui.texteditor.IEditorStatusLine;
77 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
78 import org.eclipse.ui.texteditor.StatusTextEditor;
79 import org.eclipse.ui.texteditor.TextOperationAction;
80 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
82 * PHP specific text editor.
84 public class PHPEditor
85 extends StatusTextEditor
86 implements IViewPartInputProvider { // extends TextEditor {
88 /** Preference key for showing the line number ruler */
89 private final static String LINE_NUMBER_RULER =
90 PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
91 /** Preference key for the foreground color of the line numbers */
92 private final static String LINE_NUMBER_COLOR =
93 PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
94 /** Preference key for the link color */
95 private final static String LINK_COLOR =
96 PreferenceConstants.EDITOR_LINK_COLOR;
98 // protected PHPActionGroup fActionGroups;
99 /** The outline page */
100 private AbstractContentOutlinePage fOutlinePage;
102 // protected PHPSyntaxParserThread fValidationThread = null;
104 // private IPreferenceStore fPHPPrefStore;
106 /** The editor's bracket matcher */
107 private PHPPairMatcher fBracketMatcher;
108 /** The line number ruler column */
109 private LineNumberRulerColumn fLineNumberRulerColumn;
111 protected CompositeActionGroup fActionGroups;
112 /** The standard action groups added to the menu */
113 protected GenerateActionGroup fGenerateActionGroup;
114 protected CompositeActionGroup fContextMenuGroup;
116 /** The information presenter. */
117 private InformationPresenter fInformationPresenter;
120 * Default constructor.
124 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
125 setSourceViewerConfiguration(
126 new PHPSourceViewerConfiguration(textTools, this));
127 setRangeIndicator(new DefaultRangeIndicator());
128 setPreferenceStore(PHPeclipsePlugin.getDefault().getPreferenceStore());
130 // if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
131 // fUpdater= new OutlinePageSelectionUpdater();
137 // * @see IMember#getCompilationUnit()
139 // public ICompilationUnit getCompilationUnit() {
143 // * @see org.phpeclipse.phpdt.internal.compiler.env.ICompilationUnit#getContents()
145 // public char[] getContents() {
146 // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
148 // return doc.get().toCharArray();
152 * Update the hovering behavior depending on the preferences.
154 private void updateHoverBehavior() {
155 SourceViewerConfiguration configuration = getSourceViewerConfiguration();
156 String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
158 for (int i = 0; i < types.length; i++) {
163 configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
165 ISourceViewer sourceViewer = getSourceViewer();
166 if (sourceViewer instanceof ITextViewerExtension2) {
167 if (stateMasks != null) {
168 for (int j = 0; j < stateMasks.length; j++) {
169 int stateMask = stateMasks[j];
170 ITextHover textHover =
171 configuration.getTextHover(sourceViewer, t, stateMask);
172 ((ITextViewerExtension2) sourceViewer).setTextHover(
178 ITextHover textHover = configuration.getTextHover(sourceViewer, t);
179 ((ITextViewerExtension2) sourceViewer).setTextHover(
182 ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
185 sourceViewer.setTextHover(
186 configuration.getTextHover(sourceViewer, t),
192 * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
194 public Object getViewPartInput() {
195 return getEditorInput().getAdapter(IResource.class);
199 * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
202 public void createPartControl(Composite parent) {
203 super.createPartControl(parent);
205 IInformationControlCreator informationControlCreator =
206 new IInformationControlCreator() {
207 public IInformationControl createInformationControl(Shell parent) {
208 boolean cutDown = false;
209 int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
210 return new DefaultInformationControl(
214 new HTMLTextPresenter(cutDown));
218 fInformationPresenter = new InformationPresenter(informationControlCreator);
219 fInformationPresenter.setSizeConstraints(60, 10, true, true);
220 fInformationPresenter.install(getSourceViewer());
224 * Returns this document's complete text.
226 * @return the document's complete text
228 public String get() {
230 this.getDocumentProvider().getDocument(this.getEditorInput());
235 * Returns the standard action group of this editor.
237 protected ActionGroup getActionGroup() {
238 return fActionGroups;
241 public AbstractContentOutlinePage getfOutlinePage() {
245 /** The <code>PHPEditor</code> implementation of this
246 * <code>AbstractTextEditor</code> method extend the
247 * actions to add those specific to the receiver
249 protected void createActions() {
250 super.createActions();
256 new TextOperationAction(
257 PHPEditorMessages.getResourceBundle(),
260 ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION));
262 action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
263 action.setActionDefinitionId(
264 PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
265 setAction("ContentAssistProposal", action); //$NON-NLS-1$
266 markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
267 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
269 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
270 action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
271 setAction("Comment", action); //$NON-NLS-1$
272 markAsStateDependentAction("Comment", true); //$NON-NLS-1$
273 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION);
275 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
276 action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
277 setAction("Uncomment", action); //$NON-NLS-1$
278 markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
279 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION);
281 action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
282 action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
283 setAction("Format", action); //$NON-NLS-1$
284 markAsStateDependentAction("Format", true); //$NON-NLS-1$
285 markAsSelectionDependentAction("Format", true); //$NON-NLS-1$
286 // WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION);
288 action = new GotoMatchingBracketAction(this);
289 action.setActionDefinitionId(
290 PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
291 setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
293 fGenerateActionGroup =
294 new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
297 new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
299 // We have to keep the context menu group separate to have better control over positioning
301 new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
303 // new LocalHistoryActionGroup(this, ITextEditorActionConstants.GROUP_EDIT)});
305 // if (fValidationThread == null) {
306 // fValidationThread =
307 // new PHPSyntaxParserThread(this, getSourceViewer());
310 // fValidationThread.start();
313 // fValidationThread.setText(getSourceViewer().getTextWidget().getText());
316 /** The <code>PHPEditor</code> implementation of this
317 * <code>AbstractTextEditor</code> method performs any extra
318 * disposal actions required by the php editor.
320 public void dispose() {
321 // PHPEditorEnvironment.disconnect(this);
322 if (fOutlinePage != null)
323 fOutlinePage.setInput(null);
325 if (fActionGroups != null)
326 fActionGroups.dispose();
331 /** The <code>PHPEditor</code> implementation of this
332 * <code>AbstractTextEditor</code> method performs any extra
333 * revert behavior required by the php editor.
335 public void doRevertToSaved() {
336 super.doRevertToSaved();
337 if (fOutlinePage != null)
338 fOutlinePage.update();
341 /** The <code>PHPEditor</code> implementation of this
342 * <code>AbstractTextEditor</code> method performs any extra
343 * save behavior required by the php editor.
345 public void doSave(IProgressMonitor monitor) {
346 super.doSave(monitor);
347 // compile or not, according to the user preferences
348 IPreferenceStore store = getPreferenceStore(); // fPHPPrefStore;
349 if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
350 IAction a = PHPParserAction.getInstance();
354 // if (SWT.getPlatform().equals("win32")) {
355 // IAction a = ShowExternalPreviewAction.getInstance();
359 if (fOutlinePage != null)
360 fOutlinePage.update();
363 /** The <code>PHPEditor</code> implementation of this
364 * <code>AbstractTextEditor</code> method performs any extra
365 * save as behavior required by the php editor.
367 public void doSaveAs() {
369 if (fOutlinePage != null)
370 fOutlinePage.update();
373 /** The <code>PHPEditor</code> implementation of this
374 * <code>AbstractTextEditor</code> method performs sets the
375 * input of the outline page after AbstractTextEditor has set input.
377 protected void doSetInput(IEditorInput input) throws CoreException {
378 super.doSetInput(input);
379 if (fOutlinePage != null)
380 fOutlinePage.setInput(input);
384 * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
386 // public Object getViewPartInput() {
387 // return getEditorInput().getAdapter(IFile.class);
390 /** The <code>PHPEditor</code> implementation of this
391 * <code>AbstractTextEditor</code> method adds any
392 * PHPEditor specific entries.
394 public void editorContextMenuAboutToShow(MenuManager menu) {
395 super.editorContextMenuAboutToShow(menu);
396 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
397 menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
399 ActionContext context= new ActionContext(getSelectionProvider().getSelection());
400 fContextMenuGroup.setContext(context);
401 fContextMenuGroup.fillContextMenu(menu);
402 fContextMenuGroup.setContext(null);
403 // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
405 // ActionContext context =
406 // new ActionContext(getSelectionProvider().getSelection());
407 // fContextMenuGroup.setContext(context);
408 // fContextMenuGroup.fillContextMenu(menu);
409 // fContextMenuGroup.setContext(null);
412 protected void updateStateDependentActions() {
413 super.updateStateDependentActions();
414 fGenerateActionGroup.editorStateChanged();
417 /** The <code>PHPEditor</code> implementation of this
418 * <code>AbstractTextEditor</code> method performs gets
419 * the java content outline page if request is for a an
422 public Object getAdapter(Class required) {
423 if (IContentOutlinePage.class.equals(required)) {
424 if (fOutlinePage == null) {
425 fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
426 if (getEditorInput() != null)
427 fOutlinePage.setInput(getEditorInput());
431 return super.getAdapter(required);
434 // public void openContextHelp() {
435 // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
436 // ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
437 // int pos = selection.getOffset();
438 // String word = getFunctionName(doc, pos);
439 // openContextHelp(word);
442 // private void openContextHelp(String word) {
446 // public static void open(String word) {
447 // IHelp help = WorkbenchHelp.getHelpSupport();
448 // if (help != null) {
449 // IHelpResource helpResource = new PHPFunctionHelpResource(word);
450 // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
452 // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
456 // private String getFunctionName(IDocument doc, int pos) {
457 // Point word = PHPWordExtractor.findWord(doc, pos);
458 // if (word != null) {
460 // return doc.get(word.x, word.y).replace('_', '-');
461 // } catch (BadLocationException e) {
468 * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
470 protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
474 ISourceViewer sourceViewer = getSourceViewer();
475 if (sourceViewer == null)
478 String property = event.getProperty();
480 if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
481 Object value = event.getNewValue();
482 if (value instanceof Integer) {
483 sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
484 } else if (value instanceof String) {
485 sourceViewer.getTextWidget().setTabs(
486 Integer.parseInt((String) value));
491 if (LINE_NUMBER_RULER.equals(property)) {
492 if (isLineNumberRulerVisible())
493 showLineNumberRuler();
495 hideLineNumberRuler();
499 if (fLineNumberRulerColumn != null
500 && (LINE_NUMBER_COLOR.equals(property)
501 || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
502 || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
504 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
507 if (isJavaEditorHoverProperty(property)) {
508 updateHoverBehavior();
512 super.handlePreferenceStoreChanged(event);
517 // * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
519 // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
523 // ISourceViewer sourceViewer = getSourceViewer();
524 // if (sourceViewer == null)
527 // String property = event.getProperty();
529 // // if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
530 // // Object value= event.getNewValue();
531 // // if (value instanceof Integer) {
532 // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
533 // // } else if (value instanceof String) {
534 // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
539 // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
540 // if (isLineNumberRulerVisible())
541 // showLineNumberRuler();
543 // hideLineNumberRuler();
547 // if (fLineNumberRulerColumn != null
548 // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
549 // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
550 // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
552 // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
556 // super.handlePreferenceStoreChanged(event);
560 private boolean isJavaEditorHoverProperty(String property) {
561 return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
562 || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
563 || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
564 || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
565 || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
566 || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
567 || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
568 || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
572 * Shows the line number ruler column.
574 private void showLineNumberRuler() {
575 IVerticalRuler v = getVerticalRuler();
576 if (v instanceof CompositeRuler) {
577 CompositeRuler c = (CompositeRuler) v;
578 c.addDecorator(1, createLineNumberRulerColumn());
583 * Return whether the line number ruler column should be
584 * visible according to the preference store settings.
585 * @return <code>true</code> if the line numbers should be visible
587 private boolean isLineNumberRulerVisible() {
588 IPreferenceStore store = getPreferenceStore();
589 return store.getBoolean(LINE_NUMBER_RULER);
592 * Hides the line number ruler column.
594 private void hideLineNumberRuler() {
595 IVerticalRuler v = getVerticalRuler();
596 if (v instanceof CompositeRuler) {
597 CompositeRuler c = (CompositeRuler) v;
599 c.removeDecorator(1);
600 } catch (Throwable e) {
606 * Initializes the given line number ruler column from the preference store.
607 * @param rulerColumn the ruler column to be initialized
609 protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
610 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
611 IColorManager manager = textTools.getColorManager();
613 IPreferenceStore store = getPreferenceStore();
618 if (store.contains(LINE_NUMBER_COLOR)) {
619 if (store.isDefault(LINE_NUMBER_COLOR))
620 rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
622 rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
624 rulerColumn.setForeground(manager.getColor(rgb));
628 if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
629 if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
630 if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
632 PreferenceConverter.getDefaultColor(
634 PREFERENCE_COLOR_BACKGROUND);
637 PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
640 rulerColumn.setBackground(manager.getColor(rgb));
645 * Creates a new line number ruler column that is appropriately initialized.
647 protected IVerticalRulerColumn createLineNumberRulerColumn() {
648 fLineNumberRulerColumn = new LineNumberRulerColumn();
649 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
650 return fLineNumberRulerColumn;
654 * @see AbstractTextEditor#createVerticalRuler()
656 protected IVerticalRuler createVerticalRuler() {
657 CompositeRuler ruler = new CompositeRuler();
658 ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
659 if (isLineNumberRulerVisible())
660 ruler.addDecorator(1, createLineNumberRulerColumn());
665 * Method declared on TextEditor
667 protected void initializeEditor() {
668 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
669 // PHPEditorEnvironment.connect(this);
671 // store.addPropertyChangeListener(new IPropertyChangeListener() {
672 // public void propertyChange(PropertyChangeEvent event) {
673 // PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner();
674 // if (scanner != null) {
675 // scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider());
677 // if (getSourceViewer() != null) {
678 // getSourceViewer().invalidateTextPresentation();
681 // String property = event.getProperty();
682 // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
683 // if (isLineNumberRulerVisible())
684 // showLineNumberRuler();
686 // hideLineNumberRuler();
693 private static IRegion getSignedSelection(ITextViewer viewer) {
695 StyledText text = viewer.getTextWidget();
696 int caretOffset = text.getCaretOffset();
697 Point selection = text.getSelection();
701 if (caretOffset == selection.x) {
702 offset = selection.y;
703 length = selection.x - selection.y;
707 offset = selection.x;
708 length = selection.y - selection.x;
711 return new Region(offset, length);
714 private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
716 private static boolean isBracket(char character) {
717 for (int i = 0; i != BRACKETS.length; ++i)
718 if (character == BRACKETS[i])
723 private static boolean isSurroundedByBrackets(
726 if (offset == 0 || offset == document.getLength())
730 return isBracket(document.getChar(offset - 1))
731 && isBracket(document.getChar(offset));
733 } catch (BadLocationException e) {
738 * Jumps to the matching bracket.
740 public void gotoMatchingBracket() {
742 if (fBracketMatcher == null)
743 fBracketMatcher = new PHPPairMatcher(BRACKETS);
745 ISourceViewer sourceViewer = getSourceViewer();
746 IDocument document = sourceViewer.getDocument();
747 if (document == null)
750 IRegion selection = getSignedSelection(sourceViewer);
752 int selectionLength = Math.abs(selection.getLength());
753 if (selectionLength > 1) {
754 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
755 sourceViewer.getTextWidget().getDisplay().beep();
760 int sourceCaretOffset = selection.getOffset() + selection.getLength();
761 if (isSurroundedByBrackets(document, sourceCaretOffset))
762 sourceCaretOffset -= selection.getLength();
764 IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
765 if (region == null) {
766 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
767 sourceViewer.getTextWidget().getDisplay().beep();
771 int offset = region.getOffset();
772 int length = region.getLength();
777 int anchor = fBracketMatcher.getAnchor();
779 (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
781 boolean visible = false;
782 if (sourceViewer instanceof ITextViewerExtension3) {
783 ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
784 visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
786 IRegion visibleRegion = sourceViewer.getVisibleRegion();
788 (targetOffset >= visibleRegion.getOffset()
789 && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
793 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
794 sourceViewer.getTextWidget().getDisplay().beep();
798 if (selection.getLength() < 0)
799 targetOffset -= selection.getLength();
801 sourceViewer.setSelectedRange(targetOffset, selection.getLength());
802 sourceViewer.revealRange(targetOffset, selection.getLength());
805 * Ses the given message as error message to this editor's status line.
806 * @param msg message to be set
808 protected void setStatusLineErrorMessage(String msg) {
809 IEditorStatusLine statusLine =
810 (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
811 if (statusLine != null)
812 statusLine.setMessage(true, msg, null);
816 * Returns a segmentation of the line of the given document appropriate for bidi rendering.
817 * The default implementation returns only the string literals of a php code line as segments.
819 * @param document the document
820 * @param lineOffset the offset of the line
821 * @return the line's bidi segmentation
822 * @throws BadLocationException in case lineOffset is not valid in document
824 public static int[] getBidiLineSegments(IDocument document, int lineOffset)
825 throws BadLocationException {
827 IRegion line = document.getLineInformationOfOffset(lineOffset);
828 ITypedRegion[] linePartitioning =
829 document.computePartitioning(lineOffset, line.getLength());
831 List segmentation = new ArrayList();
832 for (int i = 0; i < linePartitioning.length; i++) {
833 if (IPHPPartitionScannerConstants
835 .equals(linePartitioning[i].getType()))
836 segmentation.add(linePartitioning[i]);
839 if (segmentation.size() == 0)
842 int size = segmentation.size();
843 int[] segments = new int[size * 2 + 1];
846 for (int i = 0; i < size; i++) {
847 ITypedRegion segment = (ITypedRegion) segmentation.get(i);
852 int offset = segment.getOffset() - lineOffset;
853 if (offset > segments[j - 1])
854 segments[j++] = offset;
856 if (offset + segment.getLength() >= line.getLength())
859 segments[j++] = offset + segment.getLength();
862 if (j < segments.length) {
863 int[] result = new int[j];
864 System.arraycopy(segments, 0, result, 0, j);
871 * Returns a segmentation of the given line appropriate for bidi rendering. The default
872 * implementation returns only the string literals of a php code line as segments.
874 * @param lineOffset the offset of the line
875 * @param line the content of the line
876 * @return the line's bidi segmentation
878 protected int[] getBidiLineSegments(int lineOffset, String line) {
879 IDocumentProvider provider = getDocumentProvider();
880 if (provider != null && line != null && line.length() > 0) {
881 IDocument document = provider.getDocument(getEditorInput());
882 if (document != null)
884 return getBidiLineSegments(document, lineOffset);
885 } catch (BadLocationException x) {
893 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
895 protected final ISourceViewer createSourceViewer(
897 IVerticalRuler ruler,
899 ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
900 StyledText text = viewer.getTextWidget();
901 text.addBidiSegmentListener(new BidiSegmentListener() {
902 public void lineGetSegments(BidiSegmentEvent event) {
903 event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
906 // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
911 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
913 protected ISourceViewer createJavaSourceViewer(
915 IVerticalRuler ruler,
917 return super.createSourceViewer(parent, ruler, styles);
921 * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
923 protected boolean affectsTextPresentation(PropertyChangeEvent event) {
924 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
925 return textTools.affectsBehavior(event);