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