*** empty log message ***
[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     setDocumentProvider(PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider());
838     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
839     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
840     
841   }
842   
843   public void createPartControl(Composite parent) {
844     super.createPartControl(parent);
845
846     fPaintManager = new PaintManager(getSourceViewer());
847
848     LinePainter linePainter;
849     linePainter = new LinePainter(getSourceViewer());
850
851     linePainter.setHighlightColor(
852       new Color(Display.getCurrent(), 225, 235, 224));
853
854     fPaintManager.addPainter(linePainter);
855
856                 
857     if (isBracketHighlightingEnabled())
858       startBracketHighlighting();
859     if (isLineHighlightingEnabled())
860       startLineHighlighting();
861     if (isPrintMarginVisible())
862       showPrintMargin();
863                 
864                 
865     Iterator e= ANNOTATION_MAP.keySet().iterator();
866     while (e.hasNext()) {
867       AnnotationType type= (AnnotationType) e.next();
868       if (isAnnotationIndicationEnabled(type))
869         startAnnotationIndication(type);
870     }
871                         
872     if (isTabConversionEnabled())
873       startTabConversion();
874
875     if (isOverviewRulerVisible())
876       showOverviewRuler();
877                         
878                         
879     Preferences preferences= PHPeclipsePlugin.getDefault().getPluginPreferences();
880     preferences.addPropertyChangeListener(fPropertyChangeListener);                     
881                 
882     IPreferenceStore preferenceStore= getPreferenceStore();
883     boolean closeBrackets= preferenceStore.getBoolean(CLOSE_BRACKETS);
884     boolean closeStrings= preferenceStore.getBoolean(CLOSE_STRINGS);
885                 
886     fBracketInserter.setCloseBracketsEnabled(closeBrackets);
887     fBracketInserter.setCloseStringsEnabled(closeStrings);
888                 
889     ISourceViewer sourceViewer= getSourceViewer();
890     if (sourceViewer instanceof ITextViewerExtension)
891       ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
892
893   }
894
895   private static char getPeerCharacter(char character) {
896     switch (character) {
897       case '(':
898         return ')';
899                                 
900       case ')':
901         return '(';
902                                 
903       case '[':
904         return ']';
905
906       case ']':
907         return '[';
908                                 
909       case '"':
910         return character;
911                         
912       default:
913         throw new IllegalArgumentException();
914     }                                   
915   }
916         
917   /*
918    * @see AbstractTextEditor#doSetInput(IEditorInput)
919    */
920   protected void doSetInput(IEditorInput input) throws CoreException {
921     super.doSetInput(input);
922     configureTabConverter();
923   }
924
925   private void startBracketHighlighting() {
926     if (fBracketPainter == null) {
927       ISourceViewer sourceViewer = getSourceViewer();
928       fBracketPainter = new BracketPainter(sourceViewer);
929       fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
930       fPaintManager.addPainter(fBracketPainter);
931     }
932   }
933
934   private void stopBracketHighlighting() {
935     if (fBracketPainter != null) {
936       fPaintManager.removePainter(fBracketPainter);
937       fBracketPainter.deactivate(true);
938       fBracketPainter.dispose();
939       fBracketPainter = null;
940     }
941   }
942
943   private boolean isBracketHighlightingEnabled() {
944     IPreferenceStore store = getPreferenceStore();
945     return store.getBoolean(MATCHING_BRACKETS);
946   }
947
948   private void startLineHighlighting() {
949     if (fLinePainter == null) {
950       ISourceViewer sourceViewer = getSourceViewer();
951       fLinePainter = new LinePainter(sourceViewer);
952       fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
953       fPaintManager.addPainter(fLinePainter);
954     }
955   }
956
957   private void stopLineHighlighting() {
958     if (fLinePainter != null) {
959       fPaintManager.removePainter(fLinePainter);
960       fLinePainter.deactivate(true);
961       fLinePainter.dispose();
962       fLinePainter = null;
963     }
964   }
965
966   private boolean isLineHighlightingEnabled() {
967     IPreferenceStore store = getPreferenceStore();
968     return store.getBoolean(CURRENT_LINE);
969   }
970
971   private void showPrintMargin() {
972     if (fPrintMarginPainter == null) {
973       fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
974       fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
975       fPrintMarginPainter.setMarginRulerColumn(
976         getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
977       fPaintManager.addPainter(fPrintMarginPainter);
978     }
979   }
980
981   private void hidePrintMargin() {
982     if (fPrintMarginPainter != null) {
983       fPaintManager.removePainter(fPrintMarginPainter);
984       fPrintMarginPainter.deactivate(true);
985       fPrintMarginPainter.dispose();
986       fPrintMarginPainter = null;
987     }
988   }
989
990   private boolean isPrintMarginVisible() {
991     IPreferenceStore store = getPreferenceStore();
992     return store.getBoolean(PRINT_MARGIN);
993   }
994
995   private void startAnnotationIndication(AnnotationType annotationType) {
996     if (fProblemPainter == null) {
997       fProblemPainter = new ProblemPainter(this, getSourceViewer());
998       fPaintManager.addPainter(fProblemPainter);
999     }
1000     fProblemPainter.setColor(annotationType, getColor(annotationType));
1001     fProblemPainter.paintAnnotations(annotationType, true);
1002     fProblemPainter.paint(IPainter.CONFIGURATION);
1003   }
1004
1005   private void shutdownAnnotationIndication() {
1006     if (fProblemPainter != null) {
1007
1008       if (!fProblemPainter.isPaintingAnnotations()) {
1009         fPaintManager.removePainter(fProblemPainter);
1010         fProblemPainter.deactivate(true);
1011         fProblemPainter.dispose();
1012         fProblemPainter = null;
1013       } else {
1014         fProblemPainter.paint(IPainter.CONFIGURATION);
1015       }
1016     }
1017   }
1018
1019   private void stopAnnotationIndication(AnnotationType annotationType) {
1020     if (fProblemPainter != null) {
1021       fProblemPainter.paintAnnotations(annotationType, false);
1022       shutdownAnnotationIndication();
1023     }
1024   }
1025
1026   private boolean isAnnotationIndicationEnabled(AnnotationType annotationType) {
1027     IPreferenceStore store = getPreferenceStore();
1028     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1029     if (info != null)
1030       return store.getBoolean(info.fEditorPreference);
1031     return false;
1032   }
1033
1034   private boolean isAnnotationIndicationInOverviewRulerEnabled(AnnotationType annotationType) {
1035     IPreferenceStore store = getPreferenceStore();
1036     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1037     if (info != null)
1038       return store.getBoolean(info.fOverviewRulerPreference);
1039     return false;
1040   }
1041
1042   private void showAnnotationIndicationInOverviewRuler(
1043     AnnotationType annotationType,
1044     boolean show) {
1045     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1046     OverviewRuler ruler = asv.getOverviewRuler();
1047     if (ruler != null) {
1048       ruler.setColor(annotationType, getColor(annotationType));
1049       ruler.showAnnotation(annotationType, show);
1050       ruler.update();
1051     }
1052   }
1053
1054   private void setColorInOverviewRuler(
1055     AnnotationType annotationType,
1056     Color color) {
1057     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1058     OverviewRuler ruler = asv.getOverviewRuler();
1059     if (ruler != null) {
1060       ruler.setColor(annotationType, color);
1061       ruler.update();
1062     }
1063   }
1064
1065   private void configureTabConverter() {
1066     if (fTabConverter != null) {
1067       IDocumentProvider provider = getDocumentProvider();
1068       if (provider instanceof PHPDocumentProvider) {
1069         PHPDocumentProvider cup = (PHPDocumentProvider) provider;
1070         fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
1071       }
1072     }
1073   }
1074
1075   private int getTabSize() {
1076     Preferences preferences =
1077       PHPeclipsePlugin.getDefault().getPluginPreferences();
1078     return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1079   }
1080
1081   private void startTabConversion() {
1082     if (fTabConverter == null) {
1083       fTabConverter = new TabConverter();
1084       configureTabConverter();
1085       fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1086       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1087       asv.addTextConverter(fTabConverter);
1088       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1089       asv.updateIndentationPrefixes();
1090     }
1091   }
1092
1093   private void stopTabConversion() {
1094     if (fTabConverter != null) {
1095       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1096       asv.removeTextConverter(fTabConverter);
1097       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1098       asv.updateIndentationPrefixes();
1099       fTabConverter = null;
1100     }
1101   }
1102
1103   private boolean isTabConversionEnabled() {
1104     IPreferenceStore store = getPreferenceStore();
1105     return store.getBoolean(SPACES_FOR_TABS);
1106   }
1107
1108   private void showOverviewRuler() {
1109     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1110     asv.showOverviewRuler();
1111
1112     OverviewRuler overviewRuler = asv.getOverviewRuler();
1113     if (overviewRuler != null) {
1114       for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1115         AnnotationType type = ANNOTATION_LAYERS[i];
1116         overviewRuler.setLayer(type, i);
1117         if (isAnnotationIndicationInOverviewRulerEnabled(type))
1118           showAnnotationIndicationInOverviewRuler(type, true);
1119       }
1120     }
1121   }
1122
1123   private void hideOverviewRuler() {
1124     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1125     asv.hideOverviewRuler();
1126   }
1127
1128   private boolean isOverviewRulerVisible() {
1129     IPreferenceStore store = getPreferenceStore();
1130     return store.getBoolean(OVERVIEW_RULER);
1131   }
1132
1133   private Color getColor(String key) {
1134     RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1135     return getColor(rgb);
1136   }
1137
1138   private Color getColor(RGB rgb) {
1139     //    JavaTextTools textTools = JavaPlugin.getDefault().getJavaTextTools();
1140     //    return textTools.getColorManager().getColor(rgb);
1141     return PHPEditorEnvironment.getPHPColorProvider().getColor(rgb);
1142   }
1143
1144   private Color getColor(AnnotationType annotationType) {
1145     AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1146     if (info != null)
1147       return getColor(info.fColorPreference);
1148     return null;
1149   }
1150
1151   public void dispose() {
1152     ISourceViewer sourceViewer= getSourceViewer();
1153     if (sourceViewer instanceof ITextViewerExtension)
1154       ((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fBracketInserter);
1155       
1156     if (fPropertyChangeListener != null) {
1157       Preferences preferences= PHPeclipsePlugin.getDefault().getPluginPreferences();
1158       preferences.removePropertyChangeListener(fPropertyChangeListener);
1159       fPropertyChangeListener= null;
1160     }
1161     
1162                 
1163 //    if (fJavaEditorErrorTickUpdater != null) {
1164 //      fJavaEditorErrorTickUpdater.dispose();
1165 //      fJavaEditorErrorTickUpdater= null;
1166 //    }
1167 //              
1168 //    if (fSelectionHistory != null)
1169 //      fSelectionHistory.dispose();
1170       
1171     if (fPaintManager != null) {
1172       fPaintManager.dispose();
1173       fPaintManager = null;
1174     }
1175
1176     if (fActionGroups != null)
1177       fActionGroups.dispose();
1178       
1179     super.dispose();
1180   }
1181   
1182   protected AnnotationType getAnnotationType(String preferenceKey) {
1183     Iterator e= ANNOTATION_MAP.keySet().iterator();
1184     while (e.hasNext()) {
1185       AnnotationType type= (AnnotationType) e.next();
1186       AnnotationInfo info= (AnnotationInfo) ANNOTATION_MAP.get(type);
1187       if (info != null) {
1188         if (preferenceKey.equals(info.fColorPreference) || preferenceKey.equals(info.fEditorPreference) || preferenceKey.equals(info.fOverviewRulerPreference)) 
1189           return type;
1190       }
1191     }
1192     return null;
1193   }
1194   
1195   /*
1196    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1197    */
1198   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1199                 
1200     try {
1201                         
1202       AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
1203       if (asv != null) {
1204                                         
1205         String p= event.getProperty();          
1206                                 
1207         if (CLOSE_BRACKETS.equals(p)) {
1208           fBracketInserter.setCloseBracketsEnabled(getPreferenceStore().getBoolean(p));
1209           return;       
1210         }
1211
1212         if (CLOSE_STRINGS.equals(p)) {
1213           fBracketInserter.setCloseStringsEnabled(getPreferenceStore().getBoolean(p));
1214           return;
1215         }
1216                                                                 
1217         if (SPACES_FOR_TABS.equals(p)) {
1218           if (isTabConversionEnabled())
1219             startTabConversion();
1220           else
1221             stopTabConversion();
1222           return;
1223         }
1224                                 
1225         if (MATCHING_BRACKETS.equals(p)) {
1226           if (isBracketHighlightingEnabled())
1227             startBracketHighlighting();
1228           else
1229             stopBracketHighlighting();
1230           return;
1231         }
1232                                 
1233         if (MATCHING_BRACKETS_COLOR.equals(p)) {
1234           if (fBracketPainter != null)
1235             fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1236           return;
1237         }
1238                                 
1239         if (CURRENT_LINE.equals(p)) {
1240           if (isLineHighlightingEnabled())
1241             startLineHighlighting();
1242           else
1243             stopLineHighlighting();
1244           return;
1245         }
1246                                 
1247         if (CURRENT_LINE_COLOR.equals(p)) {
1248           if (fLinePainter != null) {
1249             stopLineHighlighting();
1250             startLineHighlighting();
1251           }                                     
1252           return;
1253         }
1254                                 
1255         if (PRINT_MARGIN.equals(p)) {
1256           if (isPrintMarginVisible())
1257             showPrintMargin();
1258           else
1259             hidePrintMargin();
1260           return;
1261         }
1262                                 
1263         if (PRINT_MARGIN_COLOR.equals(p)) {
1264           if (fPrintMarginPainter != null)
1265             fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1266           return;
1267         }
1268                                 
1269         if (PRINT_MARGIN_COLUMN.equals(p)) {
1270           if (fPrintMarginPainter != null)
1271             fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
1272           return;
1273         }
1274                                 
1275         if (OVERVIEW_RULER.equals(p))  {
1276           if (isOverviewRulerVisible())
1277             showOverviewRuler();
1278           else
1279             hideOverviewRuler();
1280           return;
1281         }
1282                                 
1283         AnnotationType type= getAnnotationType(p);
1284         if (type != null) {
1285                                         
1286           AnnotationInfo info= (AnnotationInfo) ANNOTATION_MAP.get(type);
1287           if (info.fColorPreference.equals(p)) {
1288             Color color= getColor(type);
1289             if (fProblemPainter != null) {
1290               fProblemPainter.setColor(type, color);
1291               fProblemPainter.paint(IPainter.CONFIGURATION);
1292             }
1293             setColorInOverviewRuler(type, color);
1294             return;
1295           }
1296                                         
1297           if (info.fEditorPreference.equals(p)) {
1298             if (isAnnotationIndicationEnabled(type))
1299               startAnnotationIndication(type);
1300             else
1301               stopAnnotationIndication(type);
1302             return;
1303           }
1304                                         
1305           if (info.fOverviewRulerPreference.equals(p)) {
1306             if (isAnnotationIndicationInOverviewRulerEnabled(type))
1307               showAnnotationIndicationInOverviewRuler(type, true);
1308             else
1309               showAnnotationIndicationInOverviewRuler(type, false);
1310             return;
1311           }
1312         }
1313
1314 //        IContentAssistant c= asv.getContentAssistant();
1315 //        if (c instanceof ContentAssistant)
1316 //          ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
1317       }
1318                                 
1319     } finally {
1320       super.handlePreferenceStoreChanged(event);
1321     }
1322   }
1323
1324   /**
1325    * Handles a property change event describing a change
1326    * of the php core's preferences and updates the preference
1327    * related editor properties.
1328    * 
1329    * @param event the property change event
1330    */
1331   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1332     AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer();
1333     if (asv != null) {
1334       String p= event.getProperty();                                    
1335       if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1336         asv.updateIndentationPrefixes();
1337         if (fTabConverter != null)
1338           fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1339       }
1340     }
1341   }
1342   
1343   /*
1344    * @see PHPEditor#createJavaSourceViewer(Composite, IVerticalRuler, int)
1345    */
1346   protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
1347     return new AdaptedSourceViewer(parent, ruler, styles);
1348   }
1349  
1350   private boolean isValidSelection(int offset, int length) {
1351     IDocumentProvider provider= getDocumentProvider();
1352     if (provider != null) {
1353       IDocument document= provider.getDocument(getEditorInput());
1354       if (document != null) {
1355         int end= offset + length;
1356         int documentLength= document.getLength();
1357         return 0 <= offset  && offset <= documentLength && 0 <= end && end <= documentLength;
1358       }
1359     }
1360     return false;
1361   }
1362         
1363   /*
1364    * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1365    */
1366   protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
1367                 
1368     String oldExtension= ""; //$NON-NLS-1$
1369     if (originalElement instanceof IFileEditorInput) {
1370       IFile file= ((IFileEditorInput) originalElement).getFile();
1371       if (file != null) {
1372         String ext= file.getFileExtension();
1373         if (ext != null)
1374           oldExtension= ext;
1375       }
1376     }
1377                 
1378     String newExtension= ""; //$NON-NLS-1$
1379     if (movedElement instanceof IFileEditorInput) {
1380       IFile file= ((IFileEditorInput) movedElement).getFile();
1381       if (file != null)
1382         newExtension= file.getFileExtension();
1383     }
1384                 
1385     return oldExtension.equals(newExtension);
1386   } 
1387 }