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;
350 // the parse on save was changed to the eclipse "builders" concept
351 // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
352 // IAction a = PHPParserAction.getInstance();
357 // if (SWT.getPlatform().equals("win32")) {
358 // IAction a = ShowExternalPreviewAction.getInstance();
362 if (fOutlinePage != null)
363 fOutlinePage.update();
366 /** The <code>PHPEditor</code> implementation of this
367 * <code>AbstractTextEditor</code> method performs any extra
368 * save as behavior required by the php editor.
370 public void doSaveAs() {
372 if (fOutlinePage != null)
373 fOutlinePage.update();
376 /** The <code>PHPEditor</code> implementation of this
377 * <code>AbstractTextEditor</code> method performs sets the
378 * input of the outline page after AbstractTextEditor has set input.
380 protected void doSetInput(IEditorInput input) throws CoreException {
381 super.doSetInput(input);
382 if (fOutlinePage != null)
383 fOutlinePage.setInput(input);
387 * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
389 // public Object getViewPartInput() {
390 // return getEditorInput().getAdapter(IFile.class);
393 /** The <code>PHPEditor</code> implementation of this
394 * <code>AbstractTextEditor</code> method adds any
395 * PHPEditor specific entries.
397 public void editorContextMenuAboutToShow(MenuManager menu) {
398 super.editorContextMenuAboutToShow(menu);
400 ITextEditorActionConstants.GROUP_UNDO,
401 new Separator(IContextMenuConstants.GROUP_OPEN));
403 IContextMenuConstants.GROUP_OPEN,
404 new GroupMarker(IContextMenuConstants.GROUP_SHOW));
406 ActionContext context =
407 new ActionContext(getSelectionProvider().getSelection());
408 fContextMenuGroup.setContext(context);
409 fContextMenuGroup.fillContextMenu(menu);
410 fContextMenuGroup.setContext(null);
411 // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
413 // ActionContext context =
414 // new ActionContext(getSelectionProvider().getSelection());
415 // fContextMenuGroup.setContext(context);
416 // fContextMenuGroup.fillContextMenu(menu);
417 // fContextMenuGroup.setContext(null);
420 protected void updateStateDependentActions() {
421 super.updateStateDependentActions();
422 fGenerateActionGroup.editorStateChanged();
425 /** The <code>PHPEditor</code> implementation of this
426 * <code>AbstractTextEditor</code> method performs gets
427 * the java content outline page if request is for a an
430 public Object getAdapter(Class required) {
431 if (IContentOutlinePage.class.equals(required)) {
432 if (fOutlinePage == null) {
433 fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
434 if (getEditorInput() != null)
435 fOutlinePage.setInput(getEditorInput());
439 return super.getAdapter(required);
442 // public void openContextHelp() {
443 // IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
444 // ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
445 // int pos = selection.getOffset();
446 // String word = getFunctionName(doc, pos);
447 // openContextHelp(word);
450 // private void openContextHelp(String word) {
454 // public static void open(String word) {
455 // IHelp help = WorkbenchHelp.getHelpSupport();
456 // if (help != null) {
457 // IHelpResource helpResource = new PHPFunctionHelpResource(word);
458 // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
460 // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
464 // private String getFunctionName(IDocument doc, int pos) {
465 // Point word = PHPWordExtractor.findWord(doc, pos);
466 // if (word != null) {
468 // return doc.get(word.x, word.y).replace('_', '-');
469 // } catch (BadLocationException e) {
476 * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
478 protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
482 ISourceViewer sourceViewer = getSourceViewer();
483 if (sourceViewer == null)
486 String property = event.getProperty();
488 if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
489 Object value = event.getNewValue();
490 if (value instanceof Integer) {
491 sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
492 } else if (value instanceof String) {
493 sourceViewer.getTextWidget().setTabs(
494 Integer.parseInt((String) value));
499 if (LINE_NUMBER_RULER.equals(property)) {
500 if (isLineNumberRulerVisible())
501 showLineNumberRuler();
503 hideLineNumberRuler();
507 if (fLineNumberRulerColumn != null
508 && (LINE_NUMBER_COLOR.equals(property)
509 || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
510 || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
512 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
515 if (isJavaEditorHoverProperty(property)) {
516 updateHoverBehavior();
520 super.handlePreferenceStoreChanged(event);
525 // * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
527 // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
531 // ISourceViewer sourceViewer = getSourceViewer();
532 // if (sourceViewer == null)
535 // String property = event.getProperty();
537 // // if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
538 // // Object value= event.getNewValue();
539 // // if (value instanceof Integer) {
540 // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
541 // // } else if (value instanceof String) {
542 // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
547 // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
548 // if (isLineNumberRulerVisible())
549 // showLineNumberRuler();
551 // hideLineNumberRuler();
555 // if (fLineNumberRulerColumn != null
556 // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
557 // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
558 // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
560 // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
564 // super.handlePreferenceStoreChanged(event);
568 private boolean isJavaEditorHoverProperty(String property) {
569 return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
570 || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
571 || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
572 || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
573 || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
574 || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
575 || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
576 || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
580 * Shows the line number ruler column.
582 private void showLineNumberRuler() {
583 IVerticalRuler v = getVerticalRuler();
584 if (v instanceof CompositeRuler) {
585 CompositeRuler c = (CompositeRuler) v;
586 c.addDecorator(1, createLineNumberRulerColumn());
591 * Return whether the line number ruler column should be
592 * visible according to the preference store settings.
593 * @return <code>true</code> if the line numbers should be visible
595 private boolean isLineNumberRulerVisible() {
596 IPreferenceStore store = getPreferenceStore();
597 return store.getBoolean(LINE_NUMBER_RULER);
600 * Hides the line number ruler column.
602 private void hideLineNumberRuler() {
603 IVerticalRuler v = getVerticalRuler();
604 if (v instanceof CompositeRuler) {
605 CompositeRuler c = (CompositeRuler) v;
607 c.removeDecorator(1);
608 } catch (Throwable e) {
614 * Initializes the given line number ruler column from the preference store.
615 * @param rulerColumn the ruler column to be initialized
617 protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
618 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
619 IColorManager manager = textTools.getColorManager();
621 IPreferenceStore store = getPreferenceStore();
626 if (store.contains(LINE_NUMBER_COLOR)) {
627 if (store.isDefault(LINE_NUMBER_COLOR))
628 rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
630 rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
632 rulerColumn.setForeground(manager.getColor(rgb));
636 if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
637 if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
638 if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
640 PreferenceConverter.getDefaultColor(
642 PREFERENCE_COLOR_BACKGROUND);
645 PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
648 rulerColumn.setBackground(manager.getColor(rgb));
653 * Creates a new line number ruler column that is appropriately initialized.
655 protected IVerticalRulerColumn createLineNumberRulerColumn() {
656 fLineNumberRulerColumn = new LineNumberRulerColumn();
657 initializeLineNumberRulerColumn(fLineNumberRulerColumn);
658 return fLineNumberRulerColumn;
662 * @see AbstractTextEditor#createVerticalRuler()
664 protected IVerticalRuler createVerticalRuler() {
665 CompositeRuler ruler = new CompositeRuler();
666 ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
667 if (isLineNumberRulerVisible())
668 ruler.addDecorator(1, createLineNumberRulerColumn());
673 * Method declared on TextEditor
675 protected void initializeEditor() {
676 IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
677 // PHPEditorEnvironment.connect(this);
679 // store.addPropertyChangeListener(new IPropertyChangeListener() {
680 // public void propertyChange(PropertyChangeEvent event) {
681 // PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner();
682 // if (scanner != null) {
683 // scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider());
685 // if (getSourceViewer() != null) {
686 // getSourceViewer().invalidateTextPresentation();
689 // String property = event.getProperty();
690 // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
691 // if (isLineNumberRulerVisible())
692 // showLineNumberRuler();
694 // hideLineNumberRuler();
701 private static IRegion getSignedSelection(ITextViewer viewer) {
703 StyledText text = viewer.getTextWidget();
704 int caretOffset = text.getCaretOffset();
705 Point selection = text.getSelection();
709 if (caretOffset == selection.x) {
710 offset = selection.y;
711 length = selection.x - selection.y;
715 offset = selection.x;
716 length = selection.y - selection.x;
719 return new Region(offset, length);
722 private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
724 private static boolean isBracket(char character) {
725 for (int i = 0; i != BRACKETS.length; ++i)
726 if (character == BRACKETS[i])
731 private static boolean isSurroundedByBrackets(
734 if (offset == 0 || offset == document.getLength())
738 return isBracket(document.getChar(offset - 1))
739 && isBracket(document.getChar(offset));
741 } catch (BadLocationException e) {
746 * Jumps to the matching bracket.
748 public void gotoMatchingBracket() {
750 if (fBracketMatcher == null)
751 fBracketMatcher = new PHPPairMatcher(BRACKETS);
753 ISourceViewer sourceViewer = getSourceViewer();
754 IDocument document = sourceViewer.getDocument();
755 if (document == null)
758 IRegion selection = getSignedSelection(sourceViewer);
760 int selectionLength = Math.abs(selection.getLength());
761 if (selectionLength > 1) {
762 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
763 sourceViewer.getTextWidget().getDisplay().beep();
768 int sourceCaretOffset = selection.getOffset() + selection.getLength();
769 if (isSurroundedByBrackets(document, sourceCaretOffset))
770 sourceCaretOffset -= selection.getLength();
772 IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
773 if (region == null) {
774 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
775 sourceViewer.getTextWidget().getDisplay().beep();
779 int offset = region.getOffset();
780 int length = region.getLength();
785 int anchor = fBracketMatcher.getAnchor();
787 (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
789 boolean visible = false;
790 if (sourceViewer instanceof ITextViewerExtension3) {
791 ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
792 visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
794 IRegion visibleRegion = sourceViewer.getVisibleRegion();
796 (targetOffset >= visibleRegion.getOffset()
797 && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
801 setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
802 sourceViewer.getTextWidget().getDisplay().beep();
806 if (selection.getLength() < 0)
807 targetOffset -= selection.getLength();
809 sourceViewer.setSelectedRange(targetOffset, selection.getLength());
810 sourceViewer.revealRange(targetOffset, selection.getLength());
813 * Ses the given message as error message to this editor's status line.
814 * @param msg message to be set
816 protected void setStatusLineErrorMessage(String msg) {
817 IEditorStatusLine statusLine =
818 (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
819 if (statusLine != null)
820 statusLine.setMessage(true, msg, null);
824 * Returns a segmentation of the line of the given document appropriate for bidi rendering.
825 * The default implementation returns only the string literals of a php code line as segments.
827 * @param document the document
828 * @param lineOffset the offset of the line
829 * @return the line's bidi segmentation
830 * @throws BadLocationException in case lineOffset is not valid in document
832 public static int[] getBidiLineSegments(IDocument document, int lineOffset)
833 throws BadLocationException {
835 IRegion line = document.getLineInformationOfOffset(lineOffset);
836 ITypedRegion[] linePartitioning =
837 document.computePartitioning(lineOffset, line.getLength());
839 List segmentation = new ArrayList();
840 for (int i = 0; i < linePartitioning.length; i++) {
841 if (IPHPPartitionScannerConstants
843 .equals(linePartitioning[i].getType()))
844 segmentation.add(linePartitioning[i]);
847 if (segmentation.size() == 0)
850 int size = segmentation.size();
851 int[] segments = new int[size * 2 + 1];
854 for (int i = 0; i < size; i++) {
855 ITypedRegion segment = (ITypedRegion) segmentation.get(i);
860 int offset = segment.getOffset() - lineOffset;
861 if (offset > segments[j - 1])
862 segments[j++] = offset;
864 if (offset + segment.getLength() >= line.getLength())
867 segments[j++] = offset + segment.getLength();
870 if (j < segments.length) {
871 int[] result = new int[j];
872 System.arraycopy(segments, 0, result, 0, j);
879 * Returns a segmentation of the given line appropriate for bidi rendering. The default
880 * implementation returns only the string literals of a php code line as segments.
882 * @param lineOffset the offset of the line
883 * @param line the content of the line
884 * @return the line's bidi segmentation
886 protected int[] getBidiLineSegments(int lineOffset, String line) {
887 IDocumentProvider provider = getDocumentProvider();
888 if (provider != null && line != null && line.length() > 0) {
889 IDocument document = provider.getDocument(getEditorInput());
890 if (document != null)
892 return getBidiLineSegments(document, lineOffset);
893 } catch (BadLocationException x) {
901 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
903 protected final ISourceViewer createSourceViewer(
905 IVerticalRuler ruler,
907 ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
908 StyledText text = viewer.getTextWidget();
909 text.addBidiSegmentListener(new BidiSegmentListener() {
910 public void lineGetSegments(BidiSegmentEvent event) {
911 event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
914 // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
919 * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
921 protected ISourceViewer createJavaSourceViewer(
923 IVerticalRuler ruler,
925 return super.createSourceViewer(parent, ruler, styles);
929 * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
931 protected boolean affectsTextPresentation(PropertyChangeEvent event) {
932 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
933 return textTools.affectsBehavior(event);