1 package net.sourceforge.phpeclipse.phpeditor;
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.Iterator;
9 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
10 import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
11 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
12 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
13 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
14 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI.ExitFlags;
15 import net.sourceforge.phpdt.ui.PreferenceConstants;
16 import net.sourceforge.phpdt.ui.text.JavaTextTools;
17 import net.sourceforge.phpeclipse.PHPCore;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import net.sourceforge.phpeclipse.phpeditor.php.IPHPPartitionScannerConstants;
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.Preferences;
24 import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
25 import org.eclipse.jface.preference.IPreferenceStore;
26 import org.eclipse.jface.preference.PreferenceConverter;
27 import org.eclipse.jface.text.AbstractHoverInformationControlManager;
28 import org.eclipse.jface.text.BadLocationException;
29 import org.eclipse.jface.text.DocumentCommand;
30 import org.eclipse.jface.text.IDocument;
31 import org.eclipse.jface.text.ILineTracker;
32 import org.eclipse.jface.text.IRegion;
33 import org.eclipse.jface.text.ITextSelection;
34 import org.eclipse.jface.text.ITextViewerExtension;
35 import org.eclipse.jface.text.ITypedRegion;
36 import org.eclipse.jface.text.IWidgetTokenKeeper;
37 import org.eclipse.jface.text.contentassist.ContentAssistant;
38 import org.eclipse.jface.text.contentassist.IContentAssistant;
39 import org.eclipse.jface.text.source.IAnnotationModel;
40 import org.eclipse.jface.text.source.ISourceViewer;
41 import org.eclipse.jface.text.source.IVerticalRuler;
42 import org.eclipse.jface.text.source.SourceViewer;
43 import org.eclipse.jface.text.source.SourceViewerConfiguration;
44 import org.eclipse.jface.util.PropertyChangeEvent;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.custom.StyledText;
47 import org.eclipse.swt.custom.VerifyKeyListener;
48 import org.eclipse.swt.events.VerifyEvent;
49 import org.eclipse.swt.graphics.Color;
50 import org.eclipse.swt.graphics.Point;
51 import org.eclipse.swt.graphics.RGB;
52 import org.eclipse.swt.graphics.Rectangle;
53 import org.eclipse.swt.widgets.Composite;
54 import org.eclipse.swt.widgets.Control;
55 import org.eclipse.swt.widgets.Display;
56 import org.eclipse.swt.widgets.Layout;
57 import org.eclipse.ui.IEditorInput;
58 import org.eclipse.ui.IFileEditorInput;
59 import org.eclipse.ui.help.WorkbenchHelp;
60 import org.eclipse.ui.texteditor.IDocumentProvider;
62 /**********************************************************************
63 Copyright (c) 2000, 2002 IBM Corp. and others.
64 All rights reserved. This program and the accompanying materials
65 are made available under the terms of the Common Public License v1.0
66 which accompanies this distribution, and is available at
67 http://www.eclipse.org/legal/cpl-v10.html
70 IBM Corporation - Initial implementation
71 Klaus Hartlage - www.eclipseproject.de
72 **********************************************************************/
74 * PHP specific text editor.
76 public class PHPUnitEditor extends PHPEditor {
77 interface ITextConverter {
78 void customizeDocumentCommand(IDocument document, DocumentCommand command);
81 class AdaptedRulerLayout extends Layout {
84 protected AdaptedSourceViewer fAdaptedSourceViewer;
86 protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
88 fAdaptedSourceViewer = asv;
91 protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
92 Control[] children = composite.getChildren();
93 Point s = children[children.length - 1].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
94 if (fAdaptedSourceViewer.isVerticalRulerVisible())
95 s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
99 protected void layout(Composite composite, boolean flushCache) {
100 Rectangle clArea = composite.getClientArea();
101 if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
103 StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
104 Rectangle trim = textWidget.computeTrim(0, 0, 0, 0);
105 int scrollbarHeight = trim.height;
107 IVerticalRuler vr = fAdaptedSourceViewer.getVerticalRuler();
108 int vrWidth = vr.getWidth();
111 if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
112 OverviewRuler or = fAdaptedSourceViewer.getOverviewRuler();
113 orWidth = or.getWidth();
114 or.getControl().setBounds(clArea.width - orWidth, scrollbarHeight, orWidth, clArea.height - 3 * scrollbarHeight);
117 textWidget.setBounds(vrWidth + fGap, 0, clArea.width - vrWidth - orWidth - 2 * fGap, clArea.height);
118 vr.getControl().setBounds(0, 0, vrWidth, clArea.height - scrollbarHeight);
121 StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
122 textWidget.setBounds(0, 0, clArea.width, clArea.height);
127 class AdaptedSourceViewer extends SourceViewer { // extends JavaCorrectionSourceViewer {
129 private List fTextConverters;
131 private OverviewRuler fOverviewRuler;
132 private boolean fIsOverviewRulerVisible;
133 /** The viewer's overview ruler hovering controller */
134 private AbstractHoverInformationControlManager fOverviewRulerHoveringController;
136 private boolean fIgnoreTextConverters = false;
138 private IVerticalRuler fCachedVerticalRuler;
139 private boolean fCachedIsVerticalRulerVisible;
141 public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
142 super(parent, ruler, styles); //, CompilationUnitEditor.this);
144 fCachedVerticalRuler = ruler;
145 fCachedIsVerticalRulerVisible = (ruler != null);
146 fOverviewRuler = new OverviewRuler(VERTICAL_RULER_WIDTH);
148 delayedCreateControl(parent, styles);
152 * @see ISourceViewer#showAnnotations(boolean)
154 public void showAnnotations(boolean show) {
155 fCachedIsVerticalRulerVisible = (show && fCachedVerticalRuler != null);
156 // super.showAnnotations(show);
159 public IContentAssistant getContentAssistant() {
160 return fContentAssistant;
164 * @see ITextOperationTarget#doOperation(int)
166 public void doOperation(int operation) {
168 if (getTextWidget() == null)
172 case CONTENTASSIST_PROPOSALS :
173 String msg = fContentAssistant.showPossibleCompletions();
174 setStatusLineErrorMessage(msg);
177 fIgnoreTextConverters = true;
180 fIgnoreTextConverters = true;
184 super.doOperation(operation);
187 public void insertTextConverter(ITextConverter textConverter, int index) {
188 throw new UnsupportedOperationException();
191 public void addTextConverter(ITextConverter textConverter) {
192 if (fTextConverters == null) {
193 fTextConverters = new ArrayList(1);
194 fTextConverters.add(textConverter);
195 } else if (!fTextConverters.contains(textConverter))
196 fTextConverters.add(textConverter);
199 public void removeTextConverter(ITextConverter textConverter) {
200 if (fTextConverters != null) {
201 fTextConverters.remove(textConverter);
202 if (fTextConverters.size() == 0)
203 fTextConverters = null;
208 * @see TextViewer#customizeDocumentCommand(DocumentCommand)
210 protected void customizeDocumentCommand(DocumentCommand command) {
211 super.customizeDocumentCommand(command);
212 if (!fIgnoreTextConverters && fTextConverters != null) {
213 for (Iterator e = fTextConverters.iterator(); e.hasNext();)
214 ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(), command);
216 fIgnoreTextConverters = false;
219 public IVerticalRuler getVerticalRuler() {
220 return fCachedVerticalRuler;
223 public boolean isVerticalRulerVisible() {
224 return fCachedIsVerticalRulerVisible;
227 public OverviewRuler getOverviewRuler() {
228 return fOverviewRuler;
232 * @see TextViewer#createControl(Composite, int)
234 protected void createControl(Composite parent, int styles) {
238 protected void delayedCreateControl(Composite parent, int styles) {
240 super.createControl(parent, styles);
242 Control control = getControl();
243 if (control instanceof Composite) {
244 Composite composite = (Composite) control;
245 composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this));
246 fOverviewRuler.createControl(composite, this);
250 protected void ensureOverviewHoverManagerInstalled() {
251 if (fOverviewRulerHoveringController == null && fAnnotationHover != null && fHoverControlCreator != null) {
252 fOverviewRulerHoveringController =
253 new OverviewRulerHoverManager(fOverviewRuler, this, fAnnotationHover, fHoverControlCreator);
254 fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
258 public void hideOverviewRuler() {
259 fIsOverviewRulerVisible = false;
260 Control control = getControl();
261 if (control instanceof Composite) {
262 Composite composite = (Composite) control;
265 if (fOverviewRulerHoveringController != null) {
266 fOverviewRulerHoveringController.dispose();
267 fOverviewRulerHoveringController = null;
271 public void showOverviewRuler() {
272 fIsOverviewRulerVisible = true;
273 Control control = getControl();
274 if (control instanceof Composite) {
275 Composite composite = (Composite) control;
278 ensureOverviewHoverManagerInstalled();
281 public boolean isOverviewRulerVisible() {
282 return fIsOverviewRulerVisible;
286 * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
288 public void setDocument(
290 IAnnotationModel annotationModel,
291 int visibleRegionOffset,
292 int visibleRegionLength) {
293 super.setDocument(document, annotationModel, visibleRegionOffset, visibleRegionLength);
294 fOverviewRuler.setModel(annotationModel);
297 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
298 public void updateIndentationPrefixes() {
299 SourceViewerConfiguration configuration = getSourceViewerConfiguration();
300 String[] types = configuration.getConfiguredContentTypes(this);
301 for (int i = 0; i < types.length; i++) {
302 String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
303 if (prefixes != null && prefixes.length > 0)
304 setIndentPrefixes(prefixes, types[i]);
309 * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
311 public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
312 if (WorkbenchHelp.isContextHelpDisplayed())
314 return super.requestWidgetToken(requester);
318 * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
320 public void configure(SourceViewerConfiguration configuration) {
321 super.configure(configuration);
322 // prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this), IDocument.DEFAULT_CONTENT_TYPE);
325 protected void handleDispose() {
326 fOverviewRuler = null;
328 if (fOverviewRulerHoveringController != null) {
329 fOverviewRulerHoveringController.dispose();
330 fOverviewRulerHoveringController = null;
333 super.handleDispose();
338 static class TabConverter implements ITextConverter {
340 private int fTabRatio;
341 private ILineTracker fLineTracker;
343 public TabConverter() {
346 public void setNumberOfSpacesPerTab(int ratio) {
350 public void setLineTracker(ILineTracker lineTracker) {
351 fLineTracker = lineTracker;
354 private int insertTabString(StringBuffer buffer, int offsetInLine) {
359 int remainder = offsetInLine % fTabRatio;
360 remainder = fTabRatio - remainder;
361 for (int i = 0; i < remainder; i++)
366 public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
367 String text = command.text;
371 int index = text.indexOf('\t');
374 StringBuffer buffer = new StringBuffer();
376 fLineTracker.set(command.text);
377 int lines = fLineTracker.getNumberOfLines();
381 for (int i = 0; i < lines; i++) {
383 int offset = fLineTracker.getLineOffset(i);
384 int endOffset = offset + fLineTracker.getLineLength(i);
385 String line = text.substring(offset, endOffset);
389 IRegion firstLine = document.getLineInformationOfOffset(command.offset);
390 position = command.offset - firstLine.getOffset();
393 int length = line.length();
394 for (int j = 0; j < length; j++) {
395 char c = line.charAt(j);
397 position += insertTabString(buffer, position);
406 command.text = buffer.toString();
408 } catch (BadLocationException x) {
414 private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
416 final char fExitCharacter;
418 public ExitPolicy(char exitCharacter) {
419 fExitCharacter = exitCharacter;
423 * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionManager, org.eclipse.swt.events.VerifyEvent, int, int)
425 public ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event, int offset, int length) {
427 if (event.character == fExitCharacter) {
428 if (manager.anyPositionIncludes(offset, length))
429 return new ExitFlags(LinkedPositionUI.COMMIT | LinkedPositionUI.UPDATE_CARET, false);
431 return new ExitFlags(LinkedPositionUI.COMMIT, true);
434 switch (event.character) {
436 if (manager.getFirstPosition().length == 0)
437 return new ExitFlags(0, false);
443 return new ExitFlags(LinkedPositionUI.COMMIT, true);
451 private class BracketInserter implements VerifyKeyListener, LinkedPositionUI.ExitListener {
453 private boolean fCloseBracketsPHP = true;
454 private boolean fCloseStringsPHP = true;
455 private boolean fCloseBracketsHTML = true;
456 private boolean fCloseStringsHTML = true;
461 public void setCloseBracketsPHPEnabled(boolean enabled) {
462 fCloseBracketsPHP = enabled;
465 public void setCloseStringsPHPEnabled(boolean enabled) {
466 fCloseStringsPHP = enabled;
469 public void setCloseBracketsHTMLEnabled(boolean enabled) {
470 fCloseBracketsHTML = enabled;
473 public void setCloseStringsHTMLEnabled(boolean enabled) {
474 fCloseStringsHTML = enabled;
477 private boolean hasIdentifierToTheRight(IDocument document, int offset) {
480 IRegion endLine = document.getLineInformationOfOffset(end);
481 int maxEnd = endLine.getOffset() + endLine.getLength();
482 while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
485 return end != maxEnd && Scanner.isPHPIdentifierPart(document.getChar(end));
487 } catch (BadLocationException e) {
493 private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
496 IRegion startLine = document.getLineInformationOfOffset(start);
497 int minStart = startLine.getOffset();
498 while (start != minStart && Character.isWhitespace(document.getChar(start - 1)))
501 return start != minStart && Scanner.isPHPIdentifierPart(document.getChar(start - 1));
503 } catch (BadLocationException e) {
508 private boolean hasCharacterToTheRight(IDocument document, int offset, char character) {
511 IRegion endLine = document.getLineInformationOfOffset(end);
512 int maxEnd = endLine.getOffset() + endLine.getLength();
513 while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
516 return end != maxEnd && document.getChar(end) == character;
518 } catch (BadLocationException e) {
525 * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
527 public void verifyKey(VerifyEvent event) {
532 final ISourceViewer sourceViewer = getSourceViewer();
533 IDocument document = sourceViewer.getDocument();
535 final Point selection = sourceViewer.getSelectedRange();
536 final int offset = selection.x;
537 final int length = selection.y;
540 ITypedRegion partition = document.getPartition(offset);
541 String type = partition.getType();
542 if (type.equals(IPHPPartitionScannerConstants.PHP)) {
543 switch (event.character) {
545 if (hasCharacterToTheRight(document, offset + length, '('))
551 if (!fCloseBracketsPHP)
553 if (hasIdentifierToTheRight(document, offset + length))
559 if (event.character == '"') {
560 if (!fCloseStringsPHP)
562 // changed for statements like echo "" print ""
563 // if (hasIdentifierToTheLeft(document, offset) || hasIdentifierToTheRight(document, offset + length))
564 if (hasIdentifierToTheRight(document, offset + length))
568 // ITypedRegion partition= document.getPartition(offset);
569 // if (! IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) && (partition.getOffset() != offset))
572 final char character = event.character;
573 final char closingCharacter = getPeerCharacter(character);
574 final StringBuffer buffer = new StringBuffer();
575 buffer.append(character);
576 buffer.append(closingCharacter);
578 document.replace(offset, length, buffer.toString());
580 LinkedPositionManager manager = new LinkedPositionManager(document);
581 manager.addPosition(offset + 1, 0);
586 LinkedPositionUI editor = new LinkedPositionUI(sourceViewer, manager);
587 editor.setCancelListener(this);
588 editor.setExitPolicy(new ExitPolicy(closingCharacter));
589 editor.setFinalCaretOffset(offset + 2);
592 IRegion newSelection = editor.getSelectedRegion();
593 sourceViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());
597 } else if (type.equals(IPHPPartitionScannerConstants.HTML) || type.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
598 switch (event.character) {
600 if (hasCharacterToTheRight(document, offset + length, '('))
606 if (!fCloseBracketsHTML)
608 if (hasIdentifierToTheRight(document, offset + length))
614 if (event.character == '"') {
615 if (!fCloseStringsHTML)
618 if (hasIdentifierToTheLeft(document, offset) || hasIdentifierToTheRight(document, offset + length))
622 // ITypedRegion partition= document.getPartition(offset);
623 // if (! IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) && (partition.getOffset() != offset))
626 final char character = event.character;
627 final char closingCharacter = getPeerCharacter(character);
628 final StringBuffer buffer = new StringBuffer();
629 buffer.append(character);
630 buffer.append(closingCharacter);
632 document.replace(offset, length, buffer.toString());
634 LinkedPositionManager manager = new LinkedPositionManager(document);
635 manager.addPosition(offset + 1, 0);
640 LinkedPositionUI editor = new LinkedPositionUI(sourceViewer, manager);
641 editor.setCancelListener(this);
642 editor.setExitPolicy(new ExitPolicy(closingCharacter));
643 editor.setFinalCaretOffset(offset + 2);
646 IRegion newSelection = editor.getSelectedRegion();
647 sourceViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());
652 } catch (BadLocationException e) {
658 * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
660 public void exit(boolean accept) {
666 final ISourceViewer sourceViewer = getSourceViewer();
667 IDocument document = sourceViewer.getDocument();
668 document.replace(fOffset, fLength, null);
669 } catch (BadLocationException e) {
674 /** The editor's paint manager */
675 private PaintManager fPaintManager;
676 /** The editor's bracket painter */
677 private BracketPainter fBracketPainter;
678 /** The editor's bracket matcher */
679 private PHPPairMatcher fBracketMatcher;
680 /** The editor's line painter */
681 private LinePainter fLinePainter;
682 /** The editor's print margin ruler painter */
683 private PrintMarginPainter fPrintMarginPainter;
684 /** The editor's problem painter */
685 private ProblemPainter fProblemPainter;
686 /** The editor's tab converter */
687 private TabConverter fTabConverter;
688 /** History for structure select action */
689 //private SelectionHistory fSelectionHistory;
691 /** The preference property change listener for php core. */
692 private IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
693 /** The remembered selection */
694 private ITextSelection fRememberedSelection;
695 /** The remembered php element offset */
696 private int fRememberedElementOffset;
697 /** The bracket inserter. */
698 private BracketInserter fBracketInserter = new BracketInserter();
700 private class PropertyChangeListener implements IPropertyChangeListener {
702 * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
704 public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
705 handlePreferencePropertyChanged(event);
708 /* Preference key for code formatter tab size */
709 private final static String CODE_FORMATTER_TAB_SIZE = PHPCore.FORMATTER_TAB_SIZE;
710 /** Preference key for matching brackets */
711 private final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
712 /** Preference key for matching brackets color */
713 private final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
714 /** Preference key for highlighting current line */
715 private final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
716 /** Preference key for highlight color of current line */
717 private final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
718 /** Preference key for showing print marging ruler */
719 private final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
720 /** Preference key for print margin ruler color */
721 private final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
722 /** Preference key for print margin ruler column */
723 private final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
724 /** Preference key for inserting spaces rather than tabs */
725 private final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
726 /** Preference key for error indication */
727 private final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION;
728 /** Preference key for error color */
729 private final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
730 /** Preference key for warning indication */
731 private final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION;
732 /** Preference key for warning color */
733 private final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
734 /** Preference key for task indication */
735 private final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
736 /** Preference key for task color */
737 private final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
738 /** Preference key for bookmark indication */
739 private final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
740 /** Preference key for bookmark color */
741 private final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
742 /** Preference key for search result indication */
743 private final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
744 /** Preference key for search result color */
745 private final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
746 /** Preference key for unknown annotation indication */
747 private final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
748 /** Preference key for unknown annotation color */
749 private final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
750 /** Preference key for linked position color */
751 private final static String LINKED_POSITION_COLOR = PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
752 /** Preference key for shwoing the overview ruler */
753 private final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
755 /** Preference key for error indication in overview ruler */
756 private final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
757 /** Preference key for warning indication in overview ruler */
758 private final static String WARNING_INDICATION_IN_OVERVIEW_RULER =
759 PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
760 /** Preference key for task indication in overview ruler */
761 private final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
762 /** Preference key for bookmark indication in overview ruler */
763 private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER =
764 PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
765 /** Preference key for search result indication in overview ruler */
766 private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER =
767 PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
768 /** Preference key for unknown annotation indication in overview ruler */
769 private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER =
770 PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
771 /** Preference key for automatically closing strings */
772 private final static String CLOSE_STRINGS_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_PHP;
773 /** Preference key for automatically wrapping Java strings */
774 private final static String WRAP_STRINGS = PreferenceConstants.EDITOR_WRAP_STRINGS;
775 /** Preference key for automatically closing brackets and parenthesis */
776 private final static String CLOSE_BRACKETS_PHP = PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP;
777 /** Preference key for automatically closing phpdocs and comments */
778 private final static String CLOSE_JAVADOCS = PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
779 /** Preference key for automatically adding phpdoc tags */
780 private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
781 /** Preference key for automatically formatting phpdocs */
782 private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
783 /** Preference key for automatically closing strings */
784 private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
785 /** Preference key for automatically closing brackets and parenthesis */
786 private final static String CLOSE_BRACKETS_HTML = PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML;
788 /** Preference key for smart paste */
789 private final static String SMART_PASTE = PreferenceConstants.EDITOR_SMART_PASTE;
790 private final static class AnnotationInfo {
791 public String fColorPreference;
792 public String fOverviewRulerPreference;
793 public String fEditorPreference;
796 private final static Map ANNOTATION_MAP;
800 ANNOTATION_MAP = new HashMap();
802 info = new AnnotationInfo();
803 info.fColorPreference = TASK_INDICATION_COLOR;
804 info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
805 info.fEditorPreference = TASK_INDICATION;
806 ANNOTATION_MAP.put(AnnotationType.TASK, info);
808 info = new AnnotationInfo();
809 info.fColorPreference = ERROR_INDICATION_COLOR;
810 info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
811 info.fEditorPreference = ERROR_INDICATION;
812 ANNOTATION_MAP.put(AnnotationType.ERROR, info);
814 info = new AnnotationInfo();
815 info.fColorPreference = WARNING_INDICATION_COLOR;
816 info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
817 info.fEditorPreference = WARNING_INDICATION;
818 ANNOTATION_MAP.put(AnnotationType.WARNING, info);
820 info = new AnnotationInfo();
821 info.fColorPreference = BOOKMARK_INDICATION_COLOR;
822 info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
823 info.fEditorPreference = BOOKMARK_INDICATION;
824 ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
826 info = new AnnotationInfo();
827 info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
828 info.fOverviewRulerPreference = SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
829 info.fEditorPreference = SEARCH_RESULT_INDICATION;
830 ANNOTATION_MAP.put(AnnotationType.SEARCH_RESULT, info);
832 info = new AnnotationInfo();
833 info.fColorPreference = UNKNOWN_INDICATION_COLOR;
834 info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
835 info.fEditorPreference = UNKNOWN_INDICATION;
836 ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
839 private final static AnnotationType[] ANNOTATION_LAYERS =
840 new AnnotationType[] {
841 AnnotationType.UNKNOWN,
842 AnnotationType.BOOKMARK,
844 AnnotationType.SEARCH_RESULT,
845 AnnotationType.WARNING,
846 AnnotationType.ERROR };
849 * Creates a new php unit editor.
851 public PHPUnitEditor() {
853 setDocumentProvider(PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider());
854 setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
855 setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
859 public void createPartControl(Composite parent) {
860 super.createPartControl(parent);
862 fPaintManager = new PaintManager(getSourceViewer());
864 LinePainter linePainter;
865 linePainter = new LinePainter(getSourceViewer());
867 linePainter.setHighlightColor(new Color(Display.getCurrent(), 225, 235, 224));
869 fPaintManager.addPainter(linePainter);
871 if (isBracketHighlightingEnabled())
872 startBracketHighlighting();
873 if (isLineHighlightingEnabled())
874 startLineHighlighting();
875 if (isPrintMarginVisible())
878 Iterator e = ANNOTATION_MAP.keySet().iterator();
879 while (e.hasNext()) {
880 AnnotationType type = (AnnotationType) e.next();
881 if (isAnnotationIndicationEnabled(type))
882 startAnnotationIndication(type);
885 if (isTabConversionEnabled())
886 startTabConversion();
888 if (isOverviewRulerVisible())
891 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
892 preferences.addPropertyChangeListener(fPropertyChangeListener);
894 IPreferenceStore preferenceStore = getPreferenceStore();
895 boolean closeBracketsPHP = preferenceStore.getBoolean(CLOSE_BRACKETS_PHP);
896 boolean closeStringsPHP = preferenceStore.getBoolean(CLOSE_STRINGS_PHP);
897 boolean closeBracketsHTML = preferenceStore.getBoolean(CLOSE_BRACKETS_HTML);
898 boolean closeStringsHTML = preferenceStore.getBoolean(CLOSE_STRINGS_HTML);
900 fBracketInserter.setCloseBracketsPHPEnabled(closeBracketsPHP);
901 fBracketInserter.setCloseStringsPHPEnabled(closeStringsPHP);
902 fBracketInserter.setCloseBracketsHTMLEnabled(closeBracketsHTML);
903 fBracketInserter.setCloseStringsHTMLEnabled(closeStringsHTML);
905 ISourceViewer sourceViewer = getSourceViewer();
906 if (sourceViewer instanceof ITextViewerExtension)
907 ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
911 private static char getPeerCharacter(char character) {
929 throw new IllegalArgumentException();
934 * @see AbstractTextEditor#doSetInput(IEditorInput)
936 protected void doSetInput(IEditorInput input) throws CoreException {
937 super.doSetInput(input);
938 configureTabConverter();
941 private void startBracketHighlighting() {
942 if (fBracketPainter == null) {
943 ISourceViewer sourceViewer = getSourceViewer();
944 fBracketPainter = new BracketPainter(sourceViewer);
945 fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
946 fPaintManager.addPainter(fBracketPainter);
950 private void stopBracketHighlighting() {
951 if (fBracketPainter != null) {
952 fPaintManager.removePainter(fBracketPainter);
953 fBracketPainter.deactivate(true);
954 fBracketPainter.dispose();
955 fBracketPainter = null;
959 private boolean isBracketHighlightingEnabled() {
960 IPreferenceStore store = getPreferenceStore();
961 return store.getBoolean(MATCHING_BRACKETS);
964 private void startLineHighlighting() {
965 if (fLinePainter == null) {
966 ISourceViewer sourceViewer = getSourceViewer();
967 fLinePainter = new LinePainter(sourceViewer);
968 fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
969 fPaintManager.addPainter(fLinePainter);
973 private void stopLineHighlighting() {
974 if (fLinePainter != null) {
975 fPaintManager.removePainter(fLinePainter);
976 fLinePainter.deactivate(true);
977 fLinePainter.dispose();
982 private boolean isLineHighlightingEnabled() {
983 IPreferenceStore store = getPreferenceStore();
984 return store.getBoolean(CURRENT_LINE);
987 private void showPrintMargin() {
988 if (fPrintMarginPainter == null) {
989 fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
990 fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
991 fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
992 fPaintManager.addPainter(fPrintMarginPainter);
996 private void hidePrintMargin() {
997 if (fPrintMarginPainter != null) {
998 fPaintManager.removePainter(fPrintMarginPainter);
999 fPrintMarginPainter.deactivate(true);
1000 fPrintMarginPainter.dispose();
1001 fPrintMarginPainter = null;
1005 private boolean isPrintMarginVisible() {
1006 IPreferenceStore store = getPreferenceStore();
1007 return store.getBoolean(PRINT_MARGIN);
1010 private void startAnnotationIndication(AnnotationType annotationType) {
1011 if (fProblemPainter == null) {
1012 fProblemPainter = new ProblemPainter(this, getSourceViewer());
1013 fPaintManager.addPainter(fProblemPainter);
1015 fProblemPainter.setColor(annotationType, getColor(annotationType));
1016 fProblemPainter.paintAnnotations(annotationType, true);
1017 fProblemPainter.paint(IPainter.CONFIGURATION);
1020 private void shutdownAnnotationIndication() {
1021 if (fProblemPainter != null) {
1023 if (!fProblemPainter.isPaintingAnnotations()) {
1024 fPaintManager.removePainter(fProblemPainter);
1025 fProblemPainter.deactivate(true);
1026 fProblemPainter.dispose();
1027 fProblemPainter = null;
1029 fProblemPainter.paint(IPainter.CONFIGURATION);
1034 private void stopAnnotationIndication(AnnotationType annotationType) {
1035 if (fProblemPainter != null) {
1036 fProblemPainter.paintAnnotations(annotationType, false);
1037 shutdownAnnotationIndication();
1041 private boolean isAnnotationIndicationEnabled(AnnotationType annotationType) {
1042 IPreferenceStore store = getPreferenceStore();
1043 AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1045 return store.getBoolean(info.fEditorPreference);
1049 private boolean isAnnotationIndicationInOverviewRulerEnabled(AnnotationType annotationType) {
1050 IPreferenceStore store = getPreferenceStore();
1051 AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1053 return store.getBoolean(info.fOverviewRulerPreference);
1057 private void showAnnotationIndicationInOverviewRuler(AnnotationType annotationType, boolean show) {
1058 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1059 OverviewRuler ruler = asv.getOverviewRuler();
1060 if (ruler != null) {
1061 ruler.setColor(annotationType, getColor(annotationType));
1062 ruler.showAnnotation(annotationType, show);
1067 private void setColorInOverviewRuler(AnnotationType annotationType, Color color) {
1068 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1069 OverviewRuler ruler = asv.getOverviewRuler();
1070 if (ruler != null) {
1071 ruler.setColor(annotationType, color);
1076 private void configureTabConverter() {
1077 if (fTabConverter != null) {
1078 IDocumentProvider provider = getDocumentProvider();
1079 if (provider instanceof PHPDocumentProvider) {
1080 PHPDocumentProvider cup = (PHPDocumentProvider) provider;
1081 fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
1086 private int getTabSize() {
1087 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1088 return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1091 private void startTabConversion() {
1092 if (fTabConverter == null) {
1093 fTabConverter = new TabConverter();
1094 configureTabConverter();
1095 fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1096 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1097 asv.addTextConverter(fTabConverter);
1098 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1099 asv.updateIndentationPrefixes();
1103 private void stopTabConversion() {
1104 if (fTabConverter != null) {
1105 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1106 asv.removeTextConverter(fTabConverter);
1107 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1108 asv.updateIndentationPrefixes();
1109 fTabConverter = null;
1113 private boolean isTabConversionEnabled() {
1114 IPreferenceStore store = getPreferenceStore();
1115 return store.getBoolean(SPACES_FOR_TABS);
1118 private void showOverviewRuler() {
1119 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1120 asv.showOverviewRuler();
1122 OverviewRuler overviewRuler = asv.getOverviewRuler();
1123 if (overviewRuler != null) {
1124 for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1125 AnnotationType type = ANNOTATION_LAYERS[i];
1126 overviewRuler.setLayer(type, i);
1127 if (isAnnotationIndicationInOverviewRulerEnabled(type))
1128 showAnnotationIndicationInOverviewRuler(type, true);
1133 private void hideOverviewRuler() {
1134 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1135 asv.hideOverviewRuler();
1138 private boolean isOverviewRulerVisible() {
1139 IPreferenceStore store = getPreferenceStore();
1140 return store.getBoolean(OVERVIEW_RULER);
1143 private Color getColor(String key) {
1144 RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1145 return getColor(rgb);
1148 private Color getColor(RGB rgb) {
1149 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1150 return textTools.getColorManager().getColor(rgb);
1153 private Color getColor(AnnotationType annotationType) {
1154 AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1156 return getColor(info.fColorPreference);
1160 public void dispose() {
1161 ISourceViewer sourceViewer = getSourceViewer();
1162 if (sourceViewer instanceof ITextViewerExtension)
1163 ((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fBracketInserter);
1165 if (fPropertyChangeListener != null) {
1166 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1167 preferences.removePropertyChangeListener(fPropertyChangeListener);
1168 fPropertyChangeListener = null;
1171 // if (fJavaEditorErrorTickUpdater != null) {
1172 // fJavaEditorErrorTickUpdater.dispose();
1173 // fJavaEditorErrorTickUpdater= null;
1176 // if (fSelectionHistory != null)
1177 // fSelectionHistory.dispose();
1179 if (fPaintManager != null) {
1180 fPaintManager.dispose();
1181 fPaintManager = null;
1184 if (fActionGroups != null)
1185 fActionGroups.dispose();
1190 protected AnnotationType getAnnotationType(String preferenceKey) {
1191 Iterator e = ANNOTATION_MAP.keySet().iterator();
1192 while (e.hasNext()) {
1193 AnnotationType type = (AnnotationType) e.next();
1194 AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1196 if (preferenceKey.equals(info.fColorPreference)
1197 || preferenceKey.equals(info.fEditorPreference)
1198 || preferenceKey.equals(info.fOverviewRulerPreference))
1206 * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1208 protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1212 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1215 String p = event.getProperty();
1217 if (CLOSE_BRACKETS_PHP.equals(p)) {
1218 fBracketInserter.setCloseBracketsPHPEnabled(getPreferenceStore().getBoolean(p));
1222 if (CLOSE_STRINGS_PHP.equals(p)) {
1223 fBracketInserter.setCloseStringsPHPEnabled(getPreferenceStore().getBoolean(p));
1227 if (CLOSE_BRACKETS_HTML.equals(p)) {
1228 fBracketInserter.setCloseBracketsHTMLEnabled(getPreferenceStore().getBoolean(p));
1232 if (CLOSE_STRINGS_HTML.equals(p)) {
1233 fBracketInserter.setCloseStringsHTMLEnabled(getPreferenceStore().getBoolean(p));
1237 if (SPACES_FOR_TABS.equals(p)) {
1238 if (isTabConversionEnabled())
1239 startTabConversion();
1241 stopTabConversion();
1245 if (MATCHING_BRACKETS.equals(p)) {
1246 if (isBracketHighlightingEnabled())
1247 startBracketHighlighting();
1249 stopBracketHighlighting();
1253 if (MATCHING_BRACKETS_COLOR.equals(p)) {
1254 if (fBracketPainter != null)
1255 fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1259 if (CURRENT_LINE.equals(p)) {
1260 if (isLineHighlightingEnabled())
1261 startLineHighlighting();
1263 stopLineHighlighting();
1267 if (CURRENT_LINE_COLOR.equals(p)) {
1268 if (fLinePainter != null) {
1269 stopLineHighlighting();
1270 startLineHighlighting();
1275 if (PRINT_MARGIN.equals(p)) {
1276 if (isPrintMarginVisible())
1283 if (PRINT_MARGIN_COLOR.equals(p)) {
1284 if (fPrintMarginPainter != null)
1285 fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1289 if (PRINT_MARGIN_COLUMN.equals(p)) {
1290 if (fPrintMarginPainter != null)
1291 fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
1295 if (OVERVIEW_RULER.equals(p)) {
1296 if (isOverviewRulerVisible())
1297 showOverviewRuler();
1299 hideOverviewRuler();
1303 AnnotationType type = getAnnotationType(p);
1306 AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1307 if (info.fColorPreference.equals(p)) {
1308 Color color = getColor(type);
1309 if (fProblemPainter != null) {
1310 fProblemPainter.setColor(type, color);
1311 fProblemPainter.paint(IPainter.CONFIGURATION);
1313 setColorInOverviewRuler(type, color);
1317 if (info.fEditorPreference.equals(p)) {
1318 if (isAnnotationIndicationEnabled(type))
1319 startAnnotationIndication(type);
1321 stopAnnotationIndication(type);
1325 if (info.fOverviewRulerPreference.equals(p)) {
1326 if (isAnnotationIndicationInOverviewRulerEnabled(type))
1327 showAnnotationIndicationInOverviewRuler(type, true);
1329 showAnnotationIndicationInOverviewRuler(type, false);
1334 IContentAssistant c = asv.getContentAssistant();
1335 if (c instanceof ContentAssistant)
1336 ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
1340 super.handlePreferenceStoreChanged(event);
1345 * Handles a property change event describing a change
1346 * of the php core's preferences and updates the preference
1347 * related editor properties.
1349 * @param event the property change event
1351 protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1352 AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1354 String p = event.getProperty();
1355 if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1356 asv.updateIndentationPrefixes();
1357 if (fTabConverter != null)
1358 fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1364 * @see PHPEditor#createJavaSourceViewer(Composite, IVerticalRuler, int)
1366 protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
1367 return new AdaptedSourceViewer(parent, ruler, styles);
1370 private boolean isValidSelection(int offset, int length) {
1371 IDocumentProvider provider = getDocumentProvider();
1372 if (provider != null) {
1373 IDocument document = provider.getDocument(getEditorInput());
1374 if (document != null) {
1375 int end = offset + length;
1376 int documentLength = document.getLength();
1377 return 0 <= offset && offset <= documentLength && 0 <= end && end <= documentLength;
1384 * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1386 protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
1388 String oldExtension = ""; //$NON-NLS-1$
1389 if (originalElement instanceof IFileEditorInput) {
1390 IFile file = ((IFileEditorInput) originalElement).getFile();
1392 String ext = file.getFileExtension();
1398 String newExtension = ""; //$NON-NLS-1$
1399 if (movedElement instanceof IFileEditorInput) {
1400 IFile file = ((IFileEditorInput) movedElement).getFile();
1402 newExtension = file.getFileExtension();
1405 return oldExtension.equals(newExtension);