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