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