874085179e8d063a4c3f40ba7dbeb3b979f3557b
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPUnitEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Map;
8
9 import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
10 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
11 import net.sourceforge.phpdt.internal.ui.text.java.IReconcilingParticipant;
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
20 import org.eclipse.core.resources.IFile;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.core.runtime.Preferences;
23 import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
24 import org.eclipse.jface.preference.IPreferenceStore;
25 import org.eclipse.jface.preference.PreferenceConverter;
26 import org.eclipse.jface.text.AbstractHoverInformationControlManager;
27 import org.eclipse.jface.text.BadLocationException;
28 import org.eclipse.jface.text.DocumentCommand;
29 import org.eclipse.jface.text.IDocument;
30 import org.eclipse.jface.text.ILineTracker;
31 import org.eclipse.jface.text.IRegion;
32 import org.eclipse.jface.text.ITextSelection;
33 import org.eclipse.jface.text.ITextViewerExtension;
34 import org.eclipse.jface.text.ITypedRegion;
35 import org.eclipse.jface.text.IWidgetTokenKeeper;
36 import org.eclipse.jface.text.contentassist.ContentAssistant;
37 import org.eclipse.jface.text.contentassist.IContentAssistant;
38 import org.eclipse.jface.text.source.IAnnotationModel;
39 import org.eclipse.jface.text.source.ISourceViewer;
40 import org.eclipse.jface.text.source.IVerticalRuler;
41 import org.eclipse.jface.text.source.SourceViewer;
42 import org.eclipse.jface.text.source.SourceViewerConfiguration;
43 import org.eclipse.jface.util.PropertyChangeEvent;
44 import org.eclipse.swt.SWT;
45 import org.eclipse.swt.custom.StyledText;
46 import org.eclipse.swt.custom.VerifyKeyListener;
47 import org.eclipse.swt.events.VerifyEvent;
48 import org.eclipse.swt.graphics.Color;
49 import org.eclipse.swt.graphics.Point;
50 import org.eclipse.swt.graphics.RGB;
51 import org.eclipse.swt.graphics.Rectangle;
52 import org.eclipse.swt.widgets.Composite;
53 import org.eclipse.swt.widgets.Control;
54 import org.eclipse.swt.widgets.Display;
55 import org.eclipse.swt.widgets.Layout;
56 import org.eclipse.ui.IEditorInput;
57 import org.eclipse.ui.IFileEditorInput;
58 import org.eclipse.ui.help.WorkbenchHelp;
59 import org.eclipse.ui.texteditor.IDocumentProvider;
60
61 /**********************************************************************
62 Copyright (c) 2000, 2002 IBM Corp. and others.
63 All rights reserved. This program and the accompanying materials
64 are made available under the terms of the Common Public License v1.0
65 which accompanies this distribution, and is available at
66 http://www.eclipse.org/legal/cpl-v10.html
67
68 Contributors:
69     IBM Corporation - Initial implementation
70     Klaus Hartlage - www.eclipseproject.de
71 **********************************************************************/
72 /**
73  * PHP specific text editor.
74  */
75 public class PHPUnitEditor extends PHPEditor {
76   interface ITextConverter {
77     void customizeDocumentCommand(IDocument document, DocumentCommand command);
78   };
79
80   class AdaptedRulerLayout extends Layout {
81
82     protected int fGap;
83     protected AdaptedSourceViewer fAdaptedSourceViewer;
84
85     protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
86       fGap = gap;
87       fAdaptedSourceViewer = asv;
88     }
89
90     protected Point computeSize(
91       Composite composite,
92       int wHint,
93       int hHint,
94       boolean flushCache) {
95       Control[] children = composite.getChildren();
96       Point s =
97         children[children.length
98           - 1].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
99       if (fAdaptedSourceViewer.isVerticalRulerVisible())
100         s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
101       return s;
102     }
103
104     protected void layout(Composite composite, boolean flushCache) {
105       Rectangle clArea = composite.getClientArea();
106       if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
107
108         StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
109         Rectangle trim = textWidget.computeTrim(0, 0, 0, 0);
110         int scrollbarHeight = trim.height;
111
112         IVerticalRuler vr = fAdaptedSourceViewer.getVerticalRuler();
113         int vrWidth = vr.getWidth();
114
115         int orWidth = 0;
116         if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
117           OverviewRuler or = fAdaptedSourceViewer.getOverviewRuler();
118           orWidth = or.getWidth();
119           or.getControl().setBounds(
120             clArea.width - orWidth,
121             scrollbarHeight,
122             orWidth,
123             clArea.height - 3 * scrollbarHeight);
124         }
125
126         textWidget.setBounds(
127           vrWidth + fGap,
128           0,
129           clArea.width - vrWidth - orWidth - 2 * fGap,
130           clArea.height);
131         vr.getControl().setBounds(
132           0,
133           0,
134           vrWidth,
135           clArea.height - scrollbarHeight);
136
137       } else {
138         StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
139         textWidget.setBounds(0, 0, clArea.width, clArea.height);
140       }
141     }
142   };
143
144   class AdaptedSourceViewer
145     extends SourceViewer { // extends JavaCorrectionSourceViewer  {
146
147     private List fTextConverters;
148
149     private OverviewRuler fOverviewRuler;
150     private boolean fIsOverviewRulerVisible;
151     /** The viewer's overview ruler hovering controller */
152     private AbstractHoverInformationControlManager fOverviewRulerHoveringController;
153
154     private boolean fIgnoreTextConverters = false;
155
156     private IVerticalRuler fCachedVerticalRuler;
157     private boolean fCachedIsVerticalRulerVisible;
158
159     public AdaptedSourceViewer(
160       Composite parent,
161       IVerticalRuler ruler,
162       int styles) {
163       super(parent, ruler, styles); //, CompilationUnitEditor.this);
164
165       fCachedVerticalRuler = ruler;
166       fCachedIsVerticalRulerVisible = (ruler != null);
167       fOverviewRuler = new OverviewRuler(VERTICAL_RULER_WIDTH);
168
169       delayedCreateControl(parent, styles);
170     }
171
172     /*
173      * @see ISourceViewer#showAnnotations(boolean)
174      */
175     public void showAnnotations(boolean show) {
176       fCachedIsVerticalRulerVisible = (show && fCachedVerticalRuler != null);
177       //   super.showAnnotations(show);
178     }
179
180     public IContentAssistant getContentAssistant() {
181       return fContentAssistant;
182     }
183
184     /*
185      * @see ITextOperationTarget#doOperation(int)
186      */
187     public void doOperation(int operation) {
188
189       if (getTextWidget() == null)
190         return;
191
192       switch (operation) {
193         case CONTENTASSIST_PROPOSALS :
194           String msg = fContentAssistant.showPossibleCompletions();
195           setStatusLineErrorMessage(msg);
196           return;
197         case UNDO :
198           fIgnoreTextConverters = true;
199           break;
200         case REDO :
201           fIgnoreTextConverters = true;
202           break;
203       }
204
205       super.doOperation(operation);
206     }
207
208     public void insertTextConverter(ITextConverter textConverter, int index) {
209       throw new UnsupportedOperationException();
210     }
211
212     public void addTextConverter(ITextConverter textConverter) {
213       if (fTextConverters == null) {
214         fTextConverters = new ArrayList(1);
215         fTextConverters.add(textConverter);
216       } else if (!fTextConverters.contains(textConverter))
217         fTextConverters.add(textConverter);
218     }
219
220     public void removeTextConverter(ITextConverter textConverter) {
221       if (fTextConverters != null) {
222         fTextConverters.remove(textConverter);
223         if (fTextConverters.size() == 0)
224           fTextConverters = null;
225       }
226     }
227
228     /*
229      * @see TextViewer#customizeDocumentCommand(DocumentCommand)
230      */
231     protected void customizeDocumentCommand(DocumentCommand command) {
232       super.customizeDocumentCommand(command);
233       if (!fIgnoreTextConverters && fTextConverters != null) {
234         for (Iterator e = fTextConverters.iterator(); e.hasNext();)
235           ((ITextConverter) e.next()).customizeDocumentCommand(
236             getDocument(),
237             command);
238       }
239       fIgnoreTextConverters = false;
240     }
241
242     public IVerticalRuler getVerticalRuler() {
243       return fCachedVerticalRuler;
244     }
245
246     public boolean isVerticalRulerVisible() {
247       return fCachedIsVerticalRulerVisible;
248     }
249
250     public OverviewRuler getOverviewRuler() {
251       return fOverviewRuler;
252     }
253
254     /*
255      * @see TextViewer#createControl(Composite, int)
256      */
257     protected void createControl(Composite parent, int styles) {
258       // do nothing here
259     }
260
261     protected void delayedCreateControl(Composite parent, int styles) {
262       //create the viewer
263       super.createControl(parent, styles);
264
265       Control control = getControl();
266       if (control instanceof Composite) {
267         Composite composite = (Composite) control;
268         composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this));
269         fOverviewRuler.createControl(composite, this);
270       }
271     }
272
273     protected void ensureOverviewHoverManagerInstalled() {
274       if (fOverviewRulerHoveringController == null
275         && fAnnotationHover != null
276         && fHoverControlCreator != null) {
277         fOverviewRulerHoveringController =
278           new OverviewRulerHoverManager(
279             fOverviewRuler,
280             this,
281             fAnnotationHover,
282             fHoverControlCreator);
283         fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
284       }
285     }
286
287     public void hideOverviewRuler() {
288       fIsOverviewRulerVisible = false;
289       Control control = getControl();
290       if (control instanceof Composite) {
291         Composite composite = (Composite) control;
292         composite.layout();
293       }
294       if (fOverviewRulerHoveringController != null) {
295         fOverviewRulerHoveringController.dispose();
296         fOverviewRulerHoveringController = null;
297       }
298     }
299
300     public void showOverviewRuler() {
301       fIsOverviewRulerVisible = true;
302       Control control = getControl();
303       if (control instanceof Composite) {
304         Composite composite = (Composite) control;
305         composite.layout();
306       }
307       ensureOverviewHoverManagerInstalled();
308     }
309
310     public boolean isOverviewRulerVisible() {
311       return fIsOverviewRulerVisible;
312     }
313
314     /*
315      * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
316      */
317     public void setDocument(
318       IDocument document,
319       IAnnotationModel annotationModel,
320       int visibleRegionOffset,
321       int visibleRegionLength) {
322       super.setDocument(
323         document,
324         annotationModel,
325         visibleRegionOffset,
326         visibleRegionLength);
327       fOverviewRuler.setModel(annotationModel);
328     }
329
330     // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
331     public void updateIndentationPrefixes() {
332       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
333       String[] types = configuration.getConfiguredContentTypes(this);
334       for (int i = 0; i < types.length; i++) {
335         String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
336         if (prefixes != null && prefixes.length > 0)
337           setIndentPrefixes(prefixes, types[i]);
338       }
339     }
340
341     /*
342      * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
343      */
344     public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
345       if (WorkbenchHelp.isContextHelpDisplayed())
346         return false;
347       return super.requestWidgetToken(requester);
348     }
349
350     /*
351      * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
352      */
353     public void configure(SourceViewerConfiguration configuration) {
354       super.configure(configuration);
355       //      prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this), IDocument.DEFAULT_CONTENT_TYPE);
356     }
357
358     protected void handleDispose() {
359       fOverviewRuler = null;
360
361       if (fOverviewRulerHoveringController != null) {
362         fOverviewRulerHoveringController.dispose();
363         fOverviewRulerHoveringController = null;
364       }
365
366       super.handleDispose();
367     }
368
369   };
370
371   static class TabConverter implements ITextConverter {
372
373     private int fTabRatio;
374     private ILineTracker fLineTracker;
375
376     public TabConverter() {
377     }
378
379     public void setNumberOfSpacesPerTab(int ratio) {
380       fTabRatio = ratio;
381     }
382
383     public void setLineTracker(ILineTracker lineTracker) {
384       fLineTracker = lineTracker;
385     }
386
387     private int insertTabString(StringBuffer buffer, int offsetInLine) {
388
389       if (fTabRatio == 0)
390         return 0;
391
392       int remainder = offsetInLine % fTabRatio;
393       remainder = fTabRatio - remainder;
394       for (int i = 0; i < remainder; i++)
395         buffer.append(' ');
396       return remainder;
397     }
398
399     public void customizeDocumentCommand(
400       IDocument document,
401       DocumentCommand command) {
402       String text = command.text;
403       if (text == null)
404         return;
405
406       int index = text.indexOf('\t');
407       if (index > -1) {
408
409         StringBuffer buffer = new StringBuffer();
410
411         fLineTracker.set(command.text);
412         int lines = fLineTracker.getNumberOfLines();
413
414         try {
415
416           for (int i = 0; i < lines; i++) {
417
418             int offset = fLineTracker.getLineOffset(i);
419             int endOffset = offset + fLineTracker.getLineLength(i);
420             String line = text.substring(offset, endOffset);
421
422             int position = 0;
423             if (i == 0) {
424               IRegion firstLine =
425                 document.getLineInformationOfOffset(command.offset);
426               position = command.offset - firstLine.getOffset();
427             }
428
429             int length = line.length();
430             for (int j = 0; j < length; j++) {
431               char c = line.charAt(j);
432               if (c == '\t') {
433                 position += insertTabString(buffer, position);
434               } else {
435                 buffer.append(c);
436                 ++position;
437               }
438             }
439
440           }
441
442           command.text = buffer.toString();
443
444         } catch (BadLocationException x) {
445         }
446       }
447     }
448   };
449
450   private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
451                 
452     final char fExitCharacter;
453                 
454     public ExitPolicy(char exitCharacter) {
455       fExitCharacter= exitCharacter;
456     }
457
458     /*
459      * @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)
460      */
461     public ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event, int offset, int length) {
462                         
463       if (event.character == fExitCharacter) {
464         if (manager.anyPositionIncludes(offset, length))
465           return new ExitFlags(LinkedPositionUI.COMMIT| LinkedPositionUI.UPDATE_CARET, false);
466         else
467           return new ExitFlags(LinkedPositionUI.COMMIT, true);
468       } 
469                         
470       switch (event.character) {                        
471       case '\b':
472         if (manager.getFirstPosition().length == 0)
473           return new ExitFlags(0, false);
474         else
475           return null;
476                                 
477       case '\n':
478       case '\r':
479         return new ExitFlags(LinkedPositionUI.COMMIT, true);
480                                 
481       default:
482         return null;
483       }                                         
484     }
485
486   }
487   private class BracketInserter implements VerifyKeyListener, LinkedPositionUI.ExitListener {
488                 
489     private boolean fCloseBrackets= true;
490     private boolean fCloseStrings= true;
491                 
492     private int fOffset;
493     private int fLength;
494
495     public void setCloseBracketsEnabled(boolean enabled) {
496       fCloseBrackets= enabled;
497     }
498
499     public void setCloseStringsEnabled(boolean enabled) {
500       fCloseStrings= enabled;
501     }
502
503     private boolean hasIdentifierToTheRight(IDocument document, int offset) {
504       try {
505         int end= offset;
506         IRegion endLine= document.getLineInformationOfOffset(end);
507         int maxEnd= endLine.getOffset() + endLine.getLength();
508         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
509           ++end;
510
511         return end != maxEnd && Character.isJavaIdentifierPart(document.getChar(end));
512
513       } catch (BadLocationException e) {
514         // be conservative
515         return true;
516       }
517     }
518
519     private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
520       try {
521         int start= offset;
522         IRegion startLine= document.getLineInformationOfOffset(start);
523         int minStart= startLine.getOffset();
524         while (start != minStart && Character.isWhitespace(document.getChar(start - 1)))
525           --start;
526                                 
527         return start != minStart && Character.isJavaIdentifierPart(document.getChar(start - 1));
528
529       } catch (BadLocationException e) {
530         return true;
531       }                 
532     }
533
534     private boolean hasCharacterToTheRight(IDocument document, int offset, char character) {
535       try {
536         int end= offset;
537         IRegion endLine= document.getLineInformationOfOffset(end);
538         int maxEnd= endLine.getOffset() + endLine.getLength();
539         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
540           ++end;
541                                 
542         return end != maxEnd && document.getChar(end) == character;
543
544
545       } catch (BadLocationException e) {
546         // be conservative
547         return true;
548       }                 
549     }
550                 
551     /*
552      * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
553      */
554     public void verifyKey(VerifyEvent event) {                  
555
556       if (!event.doit)
557         return;
558
559       final ISourceViewer sourceViewer= getSourceViewer();
560       IDocument document= sourceViewer.getDocument();
561
562       final Point selection= sourceViewer.getSelectedRange();
563       final int offset= selection.x;
564       final int length= selection.y;
565
566       switch (event.character) {
567       case '(':
568         if (hasCharacterToTheRight(document, offset + length, '('))
569           return;
570
571         // fall through
572
573       case '[':
574           if (!fCloseBrackets)
575             return;
576           if (hasIdentifierToTheRight(document, offset + length))
577             return;
578                         
579         // fall through
580                         
581       case '"':
582         if (event.character == '"') {
583           if (!fCloseStrings)
584             return;
585           if (hasIdentifierToTheLeft(document, offset) || hasIdentifierToTheRight(document, offset + length))
586             return;
587         }
588                                 
589         try {           
590           ITypedRegion partition= document.getPartition(offset);
591           if (! IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) && partition.getOffset() != offset)
592             return;
593
594           final char character= event.character;
595           final char closingCharacter= getPeerCharacter(character);             
596           final StringBuffer buffer= new StringBuffer();
597           buffer.append(character);
598           buffer.append(closingCharacter);
599
600           document.replace(offset, length, buffer.toString());
601
602           LinkedPositionManager manager= new LinkedPositionManager(document);
603           manager.addPosition(offset + 1, 0);
604
605           fOffset= offset;
606           fLength= 2;
607                         
608           LinkedPositionUI editor= new LinkedPositionUI(sourceViewer, manager);
609           editor.setCancelListener(this);
610           editor.setExitPolicy(new ExitPolicy(closingCharacter));
611           editor.setFinalCaretOffset(offset + 2);
612           editor.enter();
613
614           IRegion newSelection= editor.getSelectedRegion();
615           sourceViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());
616         
617           event.doit= false;
618
619         } catch (BadLocationException e) {
620         }
621         break;  
622       }
623     }
624                 
625     /*
626      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
627      */
628     public void exit(boolean accept) {
629       if (accept)
630         return;
631
632       // remove brackets
633       try {
634         final ISourceViewer sourceViewer= getSourceViewer();
635         IDocument document= sourceViewer.getDocument();
636         document.replace(fOffset, fLength, null);
637       } catch (BadLocationException e) {
638       }
639     }
640
641   }
642   /** The editor's paint manager */
643   private PaintManager fPaintManager;
644   /** The editor's bracket painter */
645   private BracketPainter fBracketPainter;
646   /** The editor's bracket matcher */
647   private PHPPairMatcher fBracketMatcher;
648   /** The editor's line painter */
649   private LinePainter fLinePainter;
650   /** The editor's print margin ruler painter */
651   private PrintMarginPainter fPrintMarginPainter;
652   /** The editor's problem painter */
653   private ProblemPainter fProblemPainter;
654   /** The editor's tab converter */
655   private TabConverter fTabConverter;
656   /** History for structure select action */
657   //private SelectionHistory fSelectionHistory;
658   
659   /** The preference property change listener for php core. */
660   private IPropertyChangeListener fPropertyChangeListener= new PropertyChangeListener();
661   /** The remembered selection */
662   private ITextSelection fRememberedSelection;
663   /** The remembered php element offset */
664   private int fRememberedElementOffset;
665   /** The bracket inserter. */
666   private BracketInserter fBracketInserter= new BracketInserter();
667   
668   private class PropertyChangeListener implements IPropertyChangeListener {             
669     /*
670      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
671      */
672     public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
673       handlePreferencePropertyChanged(event);
674     }
675   }
676   /* Preference key for code formatter tab size */
677   private final static String CODE_FORMATTER_TAB_SIZE =
678     PHPCore.FORMATTER_TAB_SIZE;
679   /** Preference key for matching brackets */
680   private final static String MATCHING_BRACKETS =
681     PreferenceConstants.EDITOR_MATCHING_BRACKETS;
682   /** Preference key for matching brackets color */
683   private final static String MATCHING_BRACKETS_COLOR =
684     PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
685   /** Preference key for highlighting current line */
686   private final static String CURRENT_LINE =
687     PreferenceConstants.EDITOR_CURRENT_LINE;
688   /** Preference key for highlight color of current line */
689   private final static String CURRENT_LINE_COLOR =
690     PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
691   /** Preference key for showing print marging ruler */
692   private final static String PRINT_MARGIN =
693     PreferenceConstants.EDITOR_PRINT_MARGIN;
694   /** Preference key for print margin ruler color */
695   private final static String PRINT_MARGIN_COLOR =
696     PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
697   /** Preference key for print margin ruler column */
698   private final static String PRINT_MARGIN_COLUMN =
699     PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
700   /** Preference key for inserting spaces rather than tabs */
701   private final static String SPACES_FOR_TABS =
702     PreferenceConstants.EDITOR_SPACES_FOR_TABS;
703   /** Preference key for error indication */
704   private final static String ERROR_INDICATION =
705     PreferenceConstants.EDITOR_PROBLEM_INDICATION;
706   /** Preference key for error color */
707   private final static String ERROR_INDICATION_COLOR =
708     PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
709   /** Preference key for warning indication */
710   private final static String WARNING_INDICATION =
711     PreferenceConstants.EDITOR_WARNING_INDICATION;
712   /** Preference key for warning color */
713   private final static String WARNING_INDICATION_COLOR =
714     PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
715   /** Preference key for task indication */
716   private final static String TASK_INDICATION =
717     PreferenceConstants.EDITOR_TASK_INDICATION;
718   /** Preference key for task color */
719   private final static String TASK_INDICATION_COLOR =
720     PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
721   /** Preference key for bookmark indication */
722   private final static String BOOKMARK_INDICATION =
723     PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
724   /** Preference key for bookmark color */
725   private final static String BOOKMARK_INDICATION_COLOR =
726     PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
727   /** Preference key for search result indication */
728   private final static String SEARCH_RESULT_INDICATION =
729     PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
730   /** Preference key for search result color */
731   private final static String SEARCH_RESULT_INDICATION_COLOR =
732     PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
733   /** Preference key for unknown annotation indication */
734   private final static String UNKNOWN_INDICATION =
735     PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
736   /** Preference key for unknown annotation color */
737   private final static String UNKNOWN_INDICATION_COLOR =
738     PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
739   /** Preference key for linked position color */
740   private final static String LINKED_POSITION_COLOR =
741     PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
742   /** Preference key for shwoing the overview ruler */
743   private final static String OVERVIEW_RULER =
744     PreferenceConstants.EDITOR_OVERVIEW_RULER;
745     
746   /** Preference key for error indication in overview ruler */
747   private final static String ERROR_INDICATION_IN_OVERVIEW_RULER =
748     PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
749   /** Preference key for warning indication in overview ruler */
750   private final static String WARNING_INDICATION_IN_OVERVIEW_RULER =
751     PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
752   /** Preference key for task indication in overview ruler */
753   private final static String TASK_INDICATION_IN_OVERVIEW_RULER =
754     PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
755   /** Preference key for bookmark indication in overview ruler */
756   private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER =
757     PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
758   /** Preference key for search result indication in overview ruler */
759   private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER =
760     PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
761   /** Preference key for unknown annotation indication in overview ruler */
762   private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER =
763     PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
764   /** Preference key for automatically closing strings */
765   private final static String CLOSE_STRINGS= PreferenceConstants.EDITOR_CLOSE_STRINGS;
766   /** Preference key for automatically wrapping Java strings */
767   private final static String WRAP_STRINGS= PreferenceConstants.EDITOR_WRAP_STRINGS;
768   /** Preference key for automatically closing brackets and parenthesis */
769   private final static String CLOSE_BRACKETS= PreferenceConstants.EDITOR_CLOSE_BRACKETS;
770   /** Preference key for automatically closing phpdocs and comments */
771   private final static String CLOSE_JAVADOCS= PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
772   /** Preference key for automatically adding phpdoc tags */
773   private final static String ADD_JAVADOC_TAGS= PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
774   /** Preference key for automatically formatting phpdocs */
775   private final static String FORMAT_JAVADOCS= PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
776   /** Preference key for smart paste */
777   private final static String SMART_PASTE= PreferenceConstants.EDITOR_SMART_PASTE;
778   private final static class AnnotationInfo {
779     public String fColorPreference;
780     public String fOverviewRulerPreference;
781     public String fEditorPreference;
782   };
783
784   private final static Map ANNOTATION_MAP;
785   static {
786
787     AnnotationInfo info;
788     ANNOTATION_MAP = new HashMap();
789
790     info = new AnnotationInfo();
791     info.fColorPreference = TASK_INDICATION_COLOR;
792     info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
793     info.fEditorPreference = TASK_INDICATION;
794     ANNOTATION_MAP.put(AnnotationType.TASK, info);
795
796     info = new AnnotationInfo();
797     info.fColorPreference = ERROR_INDICATION_COLOR;
798     info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
799     info.fEditorPreference = ERROR_INDICATION;
800     ANNOTATION_MAP.put(AnnotationType.ERROR, info);
801
802     info = new AnnotationInfo();
803     info.fColorPreference = WARNING_INDICATION_COLOR;
804     info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
805     info.fEditorPreference = WARNING_INDICATION;
806     ANNOTATION_MAP.put(AnnotationType.WARNING, info);
807
808     info = new AnnotationInfo();
809     info.fColorPreference = BOOKMARK_INDICATION_COLOR;
810     info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
811     info.fEditorPreference = BOOKMARK_INDICATION;
812     ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
813
814     info = new AnnotationInfo();
815     info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
816     info.fOverviewRulerPreference = SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
817     info.fEditorPreference = SEARCH_RESULT_INDICATION;
818     ANNOTATION_MAP.put(AnnotationType.SEARCH_RESULT, info);
819
820     info = new AnnotationInfo();
821     info.fColorPreference = UNKNOWN_INDICATION_COLOR;
822     info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
823     info.fEditorPreference = UNKNOWN_INDICATION;
824     ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
825   };
826
827   private final static AnnotationType[] ANNOTATION_LAYERS =
828     new AnnotationType[] {
829       AnnotationType.UNKNOWN,
830       AnnotationType.BOOKMARK,
831       AnnotationType.TASK,
832       AnnotationType.SEARCH_RESULT,
833       AnnotationType.WARNING,
834       AnnotationType.ERROR };
835
836   /**
837    * Creates a new php unit editor.
838    */
839   public PHPUnitEditor() {
840     super();
841     setDocumentProvider(PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider());
842     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
843     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
844     
845   }
846   
847   public void createPartControl(Composite parent) {
848     super.createPartControl(parent);
849
850     fPaintManager = new PaintManager(getSourceViewer());
851
852     LinePainter linePainter;
853     linePainter = new LinePainter(getSourceViewer());
854
855     linePainter.setHighlightColor(
856       new Color(Display.getCurrent(), 225, 235, 224));
857
858     fPaintManager.addPainter(linePainter);
859
860                 
861     if (isBracketHighlightingEnabled())
862       startBracketHighlighting();
863     if (isLineHighlightingEnabled())
864       startLineHighlighting();
865     if (isPrintMarginVisible())
866       showPrintMargin();
867                 
868                 
869     Iterator e= ANNOTATION_MAP.keySet().iterator();
870     while (e.hasNext()) {
871       AnnotationType type= (AnnotationType) e.next();
872       if (isAnnotationIndicationEnabled(type))
873         startAnnotationIndication(type);
874     }
875                         
876     if (isTabConversionEnabled())
877       startTabConversion();
878
879     if (isOverviewRulerVisible())
880       showOverviewRuler();
881                         
882                         
883     Preferences preferences= PHPeclipsePlugin.getDefault().getPluginPreferences();
884     preferences.addPropertyChangeListener(fPropertyChangeListener);                     
885                 
886     IPreferenceStore preferenceStore= getPreferenceStore();
887     boolean closeBrackets= preferenceStore.getBoolean(CLOSE_BRACKETS);
888     boolean closeStrings= preferenceStore.getBoolean(CLOSE_STRINGS);
889                 
890     fBracketInserter.setCloseBracketsEnabled(closeBrackets);
891     fBracketInserter.setCloseStringsEnabled(closeStrings);
892                 
893     ISourceViewer sourceViewer= getSourceViewer();
894     if (sourceViewer instanceof ITextViewerExtension)
895       ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
896
897   }
898
899   private static char getPeerCharacter(char character) {
900     switch (character) {
901       case '(':
902         return ')';
903                                 
904       case ')':
905         return '(';
906                                 
907       case '[':
908         return ']';
909
910       case ']':
911         return '[';
912                                 
913       case '"':
914         return character;
915                         
916       default:
917         throw new IllegalArgumentException();
918     }                                   
919   }
920         
921   /*
922    * @see AbstractTextEditor#doSetInput(IEditorInput)
923    */
924   protected void doSetInput(IEditorInput input) throws CoreException {
925     super.doSetInput(input);
926     configureTabConverter();
927   }
928
929   private void startBracketHighlighting() {
930     if (fBracketPainter == null) {
931       ISourceViewer sourceViewer = getSourceViewer();
932       fBracketPainter = new BracketPainter(sourceViewer);
933       fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
934       fPaintManager.addPainter(fBracketPainter);
935     }
936   }
937
938   private void stopBracketHighlighting() {
939     if (fBracketPainter != null) {
940       fPaintManager.removePainter(fBracketPainter);
941       fBracketPainter.deactivate(true);
942       fBracketPainter.dispose();
943       fBracketPainter = null;
944     }
945   }
946
947   private boolean isBracketHighlightingEnabled() {
948     IPreferenceStore store = getPreferenceStore();
949     return store.getBoolean(MATCHING_BRACKETS);
950   }
951
952   private void startLineHighlighting() {
953     if (fLinePainter == null) {
954       ISourceViewer sourceViewer = getSourceViewer();
955       fLinePainter = new LinePainter(sourceViewer);
956       fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
957       fPaintManager.addPainter(fLinePainter);
958     }
959   }
960
961   private void stopLineHighlighting() {
962     if (fLinePainter != null) {
963       fPaintManager.removePainter(fLinePainter);
964       fLinePainter.deactivate(true);
965       fLinePainter.dispose();
966       fLinePainter = null;
967     }
968   }
969
970   private boolean isLineHighlightingEnabled() {
971     IPreferenceStore store = getPreferenceStore();
972     return store.getBoolean(CURRENT_LINE);
973   }
974
975   private void showPrintMargin() {
976     if (fPrintMarginPainter == null) {
977       fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
978       fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
979       fPrintMarginPainter.setMarginRulerColumn(
980         getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
981       fPaintManager.addPainter(fPrintMarginPainter);
982     }
983   }
984
985   private void hidePrintMargin() {
986     if (fPrintMarginPainter != null) {
987       fPaintManager.removePainter(fPrintMarginPainter);
988       fPrintMarginPainter.deactivate(true);
989       fPrintMarginPainter.dispose();
990       fPrintMarginPainter = null;
991     }
992   }
993
994   private boolean isPrintMarginVisible() {
995     IPreferenceStore store = getPreferenceStore();
996     return store.getBoolean(PRINT_MARGIN);
997   }
998
999   private void startAnnotationIndication(AnnotationType annotationType) {
1000     if (fProblemPainter == null) {
1001       fProblemPainter = new ProblemPainter(this, getSourceViewer());
1002       fPaintManager.addPainter(fProblemPainter);
1003     }
1004     fProblemPainter.setColor(annotationType, getColor(annotationType));
1005     fProblemPainter.paintAnnotations(annotationType, true);
1006     fProblemPainter.paint(IPainter.CONFIGURATION);
1007   }
1008
1009   private void shutdownAnnotationIndication() {
1010     if (fProblemPainter != null) {
1011
1012       if (!fProblemPainter.isPaintingAnnotations()) {
1013         fPaintManager.removePainter(fProblemPainter);
1014         fProblemPainter.deactivate(true);
1015         fProblemPainter.dispose();
1016         fProblemPainter = null;
1017       } else {
1018         fProblemPainter.paint(IPainter.CONFIGURATION);
1019       }
1020     }
1021   }
1022
1023   private void stopAnnotationIndication(AnnotationType annotationType) {
1024     if (fProblemPainter != null) {
1025       fProblemPainter.paintAnnotations(annotationType, false);
1026       shutdownAnnotationIndication();
1027     }
1028   }
1029
1030   private boolean isAnnotationIndicationEnabled(AnnotationType annotationType) {
1031     IPreferenceStore store = getPreferenceStore();
1032     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1033     if (info != null)
1034       return store.getBoolean(info.fEditorPreference);
1035     return false;
1036   }
1037
1038   private boolean isAnnotationIndicationInOverviewRulerEnabled(AnnotationType annotationType) {
1039     IPreferenceStore store = getPreferenceStore();
1040     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1041     if (info != null)
1042       return store.getBoolean(info.fOverviewRulerPreference);
1043     return false;
1044   }
1045
1046   private void showAnnotationIndicationInOverviewRuler(
1047     AnnotationType annotationType,
1048     boolean show) {
1049     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1050     OverviewRuler ruler = asv.getOverviewRuler();
1051     if (ruler != null) {
1052       ruler.setColor(annotationType, getColor(annotationType));
1053       ruler.showAnnotation(annotationType, show);
1054       ruler.update();
1055     }
1056   }
1057
1058   private void setColorInOverviewRuler(
1059     AnnotationType annotationType,
1060     Color color) {
1061     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1062     OverviewRuler ruler = asv.getOverviewRuler();
1063     if (ruler != null) {
1064       ruler.setColor(annotationType, color);
1065       ruler.update();
1066     }
1067   }
1068
1069   private void configureTabConverter() {
1070     if (fTabConverter != null) {
1071       IDocumentProvider provider = getDocumentProvider();
1072       if (provider instanceof PHPDocumentProvider) {
1073         PHPDocumentProvider cup = (PHPDocumentProvider) provider;
1074         fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
1075       }
1076     }
1077   }
1078
1079   private int getTabSize() {
1080     Preferences preferences =
1081       PHPeclipsePlugin.getDefault().getPluginPreferences();
1082     return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1083   }
1084
1085   private void startTabConversion() {
1086     if (fTabConverter == null) {
1087       fTabConverter = new TabConverter();
1088       configureTabConverter();
1089       fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1090       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1091       asv.addTextConverter(fTabConverter);
1092       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1093       asv.updateIndentationPrefixes();
1094     }
1095   }
1096
1097   private void stopTabConversion() {
1098     if (fTabConverter != null) {
1099       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1100       asv.removeTextConverter(fTabConverter);
1101       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1102       asv.updateIndentationPrefixes();
1103       fTabConverter = null;
1104     }
1105   }
1106
1107   private boolean isTabConversionEnabled() {
1108     IPreferenceStore store = getPreferenceStore();
1109     return store.getBoolean(SPACES_FOR_TABS);
1110   }
1111
1112   private void showOverviewRuler() {
1113     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1114     asv.showOverviewRuler();
1115
1116     OverviewRuler overviewRuler = asv.getOverviewRuler();
1117     if (overviewRuler != null) {
1118       for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1119         AnnotationType type = ANNOTATION_LAYERS[i];
1120         overviewRuler.setLayer(type, i);
1121         if (isAnnotationIndicationInOverviewRulerEnabled(type))
1122           showAnnotationIndicationInOverviewRuler(type, true);
1123       }
1124     }
1125   }
1126
1127   private void hideOverviewRuler() {
1128     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1129     asv.hideOverviewRuler();
1130   }
1131
1132   private boolean isOverviewRulerVisible() {
1133     IPreferenceStore store = getPreferenceStore();
1134     return store.getBoolean(OVERVIEW_RULER);
1135   }
1136
1137   private Color getColor(String key) {
1138     RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1139     return getColor(rgb);
1140   }
1141
1142   private Color getColor(RGB rgb) {
1143     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1144     return textTools.getColorManager().getColor(rgb);
1145   }
1146
1147   private Color getColor(AnnotationType annotationType) {
1148     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1149     if (info != null)
1150       return getColor(info.fColorPreference);
1151     return null;
1152   }
1153
1154   public void dispose() {
1155     ISourceViewer sourceViewer= getSourceViewer();
1156     if (sourceViewer instanceof ITextViewerExtension)
1157       ((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fBracketInserter);
1158       
1159     if (fPropertyChangeListener != null) {
1160       Preferences preferences= PHPeclipsePlugin.getDefault().getPluginPreferences();
1161       preferences.removePropertyChangeListener(fPropertyChangeListener);
1162       fPropertyChangeListener= null;
1163     }
1164     
1165                 
1166 //    if (fJavaEditorErrorTickUpdater != null) {
1167 //      fJavaEditorErrorTickUpdater.dispose();
1168 //      fJavaEditorErrorTickUpdater= null;
1169 //    }
1170 //              
1171 //    if (fSelectionHistory != null)
1172 //      fSelectionHistory.dispose();
1173       
1174     if (fPaintManager != null) {
1175       fPaintManager.dispose();
1176       fPaintManager = null;
1177     }
1178
1179     if (fActionGroups != null)
1180       fActionGroups.dispose();
1181       
1182     super.dispose();
1183   }
1184   
1185   protected AnnotationType getAnnotationType(String preferenceKey) {
1186     Iterator e= ANNOTATION_MAP.keySet().iterator();
1187     while (e.hasNext()) {
1188       AnnotationType type= (AnnotationType) e.next();
1189       AnnotationInfo info= (AnnotationInfo) ANNOTATION_MAP.get(type);
1190       if (info != null) {
1191         if (preferenceKey.equals(info.fColorPreference) || preferenceKey.equals(info.fEditorPreference) || preferenceKey.equals(info.fOverviewRulerPreference)) 
1192           return type;
1193       }
1194     }
1195     return null;
1196   }
1197   
1198   /*
1199    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1200    */
1201   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1202                 
1203     try {
1204                         
1205       AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
1206       if (asv != null) {
1207                                         
1208         String p= event.getProperty();          
1209                                 
1210         if (CLOSE_BRACKETS.equals(p)) {
1211           fBracketInserter.setCloseBracketsEnabled(getPreferenceStore().getBoolean(p));
1212           return;       
1213         }
1214
1215         if (CLOSE_STRINGS.equals(p)) {
1216           fBracketInserter.setCloseStringsEnabled(getPreferenceStore().getBoolean(p));
1217           return;
1218         }
1219                                                                 
1220         if (SPACES_FOR_TABS.equals(p)) {
1221           if (isTabConversionEnabled())
1222             startTabConversion();
1223           else
1224             stopTabConversion();
1225           return;
1226         }
1227                                 
1228         if (MATCHING_BRACKETS.equals(p)) {
1229           if (isBracketHighlightingEnabled())
1230             startBracketHighlighting();
1231           else
1232             stopBracketHighlighting();
1233           return;
1234         }
1235                                 
1236         if (MATCHING_BRACKETS_COLOR.equals(p)) {
1237           if (fBracketPainter != null)
1238             fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1239           return;
1240         }
1241                                 
1242         if (CURRENT_LINE.equals(p)) {
1243           if (isLineHighlightingEnabled())
1244             startLineHighlighting();
1245           else
1246             stopLineHighlighting();
1247           return;
1248         }
1249                                 
1250         if (CURRENT_LINE_COLOR.equals(p)) {
1251           if (fLinePainter != null) {
1252             stopLineHighlighting();
1253             startLineHighlighting();
1254           }                                     
1255           return;
1256         }
1257                                 
1258         if (PRINT_MARGIN.equals(p)) {
1259           if (isPrintMarginVisible())
1260             showPrintMargin();
1261           else
1262             hidePrintMargin();
1263           return;
1264         }
1265                                 
1266         if (PRINT_MARGIN_COLOR.equals(p)) {
1267           if (fPrintMarginPainter != null)
1268             fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1269           return;
1270         }
1271                                 
1272         if (PRINT_MARGIN_COLUMN.equals(p)) {
1273           if (fPrintMarginPainter != null)
1274             fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
1275           return;
1276         }
1277                                 
1278         if (OVERVIEW_RULER.equals(p))  {
1279           if (isOverviewRulerVisible())
1280             showOverviewRuler();
1281           else
1282             hideOverviewRuler();
1283           return;
1284         }
1285                                 
1286         AnnotationType type= getAnnotationType(p);
1287         if (type != null) {
1288                                         
1289           AnnotationInfo info= (AnnotationInfo) ANNOTATION_MAP.get(type);
1290           if (info.fColorPreference.equals(p)) {
1291             Color color= getColor(type);
1292             if (fProblemPainter != null) {
1293               fProblemPainter.setColor(type, color);
1294               fProblemPainter.paint(IPainter.CONFIGURATION);
1295             }
1296             setColorInOverviewRuler(type, color);
1297             return;
1298           }
1299                                         
1300           if (info.fEditorPreference.equals(p)) {
1301             if (isAnnotationIndicationEnabled(type))
1302               startAnnotationIndication(type);
1303             else
1304               stopAnnotationIndication(type);
1305             return;
1306           }
1307                                         
1308           if (info.fOverviewRulerPreference.equals(p)) {
1309             if (isAnnotationIndicationInOverviewRulerEnabled(type))
1310               showAnnotationIndicationInOverviewRuler(type, true);
1311             else
1312               showAnnotationIndicationInOverviewRuler(type, false);
1313             return;
1314           }
1315         }
1316
1317         IContentAssistant c= asv.getContentAssistant();
1318         if (c instanceof ContentAssistant)
1319           ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
1320       }
1321                                 
1322     } finally {
1323       super.handlePreferenceStoreChanged(event);
1324     }
1325   }
1326
1327   /**
1328    * Handles a property change event describing a change
1329    * of the php core's preferences and updates the preference
1330    * related editor properties.
1331    * 
1332    * @param event the property change event
1333    */
1334   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1335     AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
1336     if (asv != null) {
1337       String p= event.getProperty();                                    
1338       if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1339         asv.updateIndentationPrefixes();
1340         if (fTabConverter != null)
1341           fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1342       }
1343     }
1344   }
1345   
1346   /*
1347    * @see PHPEditor#createJavaSourceViewer(Composite, IVerticalRuler, int)
1348    */
1349   protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
1350     return new AdaptedSourceViewer(parent, ruler, styles);
1351   }
1352  
1353   private boolean isValidSelection(int offset, int length) {
1354     IDocumentProvider provider= getDocumentProvider();
1355     if (provider != null) {
1356       IDocument document= provider.getDocument(getEditorInput());
1357       if (document != null) {
1358         int end= offset + length;
1359         int documentLength= document.getLength();
1360         return 0 <= offset  && offset <= documentLength && 0 <= end && end <= documentLength;
1361       }
1362     }
1363     return false;
1364   }
1365         
1366   /*
1367    * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1368    */
1369   protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
1370                 
1371     String oldExtension= ""; //$NON-NLS-1$
1372     if (originalElement instanceof IFileEditorInput) {
1373       IFile file= ((IFileEditorInput) originalElement).getFile();
1374       if (file != null) {
1375         String ext= file.getFileExtension();
1376         if (ext != null)
1377           oldExtension= ext;
1378       }
1379     }
1380                 
1381     String newExtension= ""; //$NON-NLS-1$
1382     if (movedElement instanceof IFileEditorInput) {
1383       IFile file= ((IFileEditorInput) movedElement).getFile();
1384       if (file != null)
1385         newExtension= file.getFileExtension();
1386     }
1387                 
1388     return oldExtension.equals(newExtension);
1389   } 
1390 }