Goto line/Goto Matching Bracket Shortcuts should work
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPUnitEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.text.MessageFormat;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7
8 import net.sourceforge.phpdt.core.ICompilationUnit;
9 import net.sourceforge.phpdt.core.IJavaElement;
10 import net.sourceforge.phpdt.core.ISourceRange;
11 import net.sourceforge.phpdt.core.ISourceReference;
12 import net.sourceforge.phpdt.core.JavaCore;
13 import net.sourceforge.phpdt.core.JavaModelException;
14 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
15 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
16 import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
17 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
18 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
19 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
20 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
21 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI.ExitFlags;
22 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
23 import net.sourceforge.phpdt.ui.PreferenceConstants;
24 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
25 import net.sourceforge.phpdt.ui.text.JavaTextTools;
26 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
27
28 import org.eclipse.core.resources.IFile;
29 import org.eclipse.core.resources.IWorkspaceRoot;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.core.runtime.IStatus;
35 import org.eclipse.core.runtime.Preferences;
36 import org.eclipse.jface.action.Action;
37 import org.eclipse.jface.action.IAction;
38 import org.eclipse.jface.action.IMenuManager;
39 import org.eclipse.jface.dialogs.ErrorDialog;
40 import org.eclipse.jface.dialogs.IMessageProvider;
41 import org.eclipse.jface.dialogs.MessageDialog;
42 import org.eclipse.jface.preference.IPreferenceStore;
43 import org.eclipse.jface.preference.PreferenceConverter;
44 import org.eclipse.jface.text.BadLocationException;
45 import org.eclipse.jface.text.DocumentCommand;
46 import org.eclipse.jface.text.IDocument;
47 import org.eclipse.jface.text.ILineTracker;
48 import org.eclipse.jface.text.IRegion;
49 import org.eclipse.jface.text.ITextOperationTarget;
50 import org.eclipse.jface.text.ITextSelection;
51 import org.eclipse.jface.text.ITextViewerExtension;
52 import org.eclipse.jface.text.ITypedRegion;
53 import org.eclipse.jface.text.IWidgetTokenKeeper;
54 import org.eclipse.jface.text.contentassist.ContentAssistant;
55 import org.eclipse.jface.text.contentassist.IContentAssistant;
56 import org.eclipse.jface.text.source.IOverviewRuler;
57 import org.eclipse.jface.text.source.ISourceViewer;
58 import org.eclipse.jface.text.source.IVerticalRuler;
59 import org.eclipse.jface.text.source.SourceViewerConfiguration;
60 import org.eclipse.jface.util.PropertyChangeEvent;
61 import org.eclipse.jface.viewers.ISelectionProvider;
62 import org.eclipse.jface.window.Window;
63 import org.eclipse.swt.SWT;
64 import org.eclipse.swt.custom.VerifyKeyListener;
65 import org.eclipse.swt.events.VerifyEvent;
66 import org.eclipse.swt.graphics.Color;
67 import org.eclipse.swt.graphics.Point;
68 import org.eclipse.swt.graphics.RGB;
69 import org.eclipse.swt.widgets.Composite;
70 import org.eclipse.swt.widgets.Display;
71 import org.eclipse.swt.widgets.Shell;
72 import org.eclipse.ui.IEditorInput;
73 import org.eclipse.ui.IFileEditorInput;
74 import org.eclipse.ui.actions.ActionContext;
75 import org.eclipse.ui.actions.ActionGroup;
76 import org.eclipse.ui.dialogs.SaveAsDialog;
77 import org.eclipse.ui.editors.text.IStorageDocumentProvider;
78 import org.eclipse.ui.help.WorkbenchHelp;
79 import org.eclipse.ui.part.FileEditorInput;
80 import org.eclipse.ui.texteditor.ContentAssistAction;
81 import org.eclipse.ui.texteditor.IDocumentProvider;
82 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
83 import org.eclipse.ui.texteditor.TextOperationAction;
84
85 /*******************************************************************************
86  * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This
87  * program and the accompanying materials are made available under the terms of
88  * the Common Public License v1.0 which accompanies this distribution, and is
89  * available at http://www.eclipse.org/legal/cpl-v10.html
90  * 
91  * Contributors: IBM Corporation - Initial implementation Klaus Hartlage -
92  * www.eclipseproject.de
93  ******************************************************************************/
94 /**
95  * PHP specific text editor.
96  */
97 public class PHPUnitEditor extends PHPEditor { //implements
98   // IJavaReconcilingListener {
99   interface ITextConverter {
100     void customizeDocumentCommand(IDocument document, DocumentCommand command);
101   };
102
103   //  class AdaptedRulerLayout extends Layout {
104   //
105   //    protected int fGap;
106   //    protected AdaptedSourceViewer fAdaptedSourceViewer;
107   //
108   //    protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
109   //      fGap = gap;
110   //      fAdaptedSourceViewer = asv;
111   //    }
112   //
113   //    protected Point computeSize(Composite composite, int wHint, int hHint,
114   // boolean flushCache) {
115   //      Control[] children = composite.getChildren();
116   //      Point s = children[children.length - 1].computeSize(SWT.DEFAULT,
117   // SWT.DEFAULT, flushCache);
118   //      if (fAdaptedSourceViewer.isVerticalRulerVisible())
119   //        s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
120   //      return s;
121   //    }
122   //
123   //    protected void layout(Composite composite, boolean flushCache) {
124   //      Rectangle clArea = composite.getClientArea();
125   //      if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
126   //
127   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
128   //        Rectangle trim = textWidget.computeTrim(0, 0, 0, 0);
129   //        int scrollbarHeight = trim.height;
130   //
131   //        IVerticalRuler vr = fAdaptedSourceViewer.getVerticalRuler();
132   //        int vrWidth = vr.getWidth();
133   //
134   //        int orWidth = 0;
135   //        if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
136   //          OverviewRuler or = fAdaptedSourceViewer.getOverviewRuler();
137   //          orWidth = or.getWidth();
138   //          or.getControl().setBounds(clArea.width - orWidth, scrollbarHeight,
139   // orWidth, clArea.height - 3 * scrollbarHeight);
140   //        }
141   //
142   //        textWidget.setBounds(vrWidth + fGap, 0, clArea.width - vrWidth - orWidth
143   // -
144   // 2 * fGap, clArea.height);
145   //        vr.getControl().setBounds(0, 0, vrWidth, clArea.height -
146   // scrollbarHeight);
147   //
148   //      } else {
149   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
150   //        textWidget.setBounds(0, 0, clArea.width, clArea.height);
151   //      }
152   //    }
153   //  };
154   //
155   //  class AdaptedSourceViewer extends SourceViewer { // extends
156   // JavaCorrectionSourceViewer {
157   //
158   //    private List fTextConverters;
159   //
160   //    private OverviewRuler fOverviewRuler;
161   //    private boolean fIsOverviewRulerVisible;
162   //    /** The viewer's overview ruler hovering controller */
163   //    private AbstractHoverInformationControlManager
164   // fOverviewRulerHoveringController;
165   //
166   //    private boolean fIgnoreTextConverters = false;
167   //
168   //    private IVerticalRuler fCachedVerticalRuler;
169   //    private boolean fCachedIsVerticalRulerVisible;
170   //
171   //    public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int
172   // styles) {
173   //      super(parent, ruler, styles); //, CompilationUnitEditor.this);
174   //
175   //      fCachedVerticalRuler = ruler;
176   //      fCachedIsVerticalRulerVisible = (ruler != null);
177   //      fOverviewRuler = new OverviewRuler(VERTICAL_RULER_WIDTH);
178   //
179   //      delayedCreateControl(parent, styles);
180   //    }
181   //
182   //    /*
183   //     * @see ISourceViewer#showAnnotations(boolean)
184   //     */
185   //    public void showAnnotations(boolean show) {
186   //      fCachedIsVerticalRulerVisible = (show && fCachedVerticalRuler != null);
187   //      // super.showAnnotations(show);
188   //    }
189   //
190   //    public IContentAssistant getContentAssistant() {
191   //      return fContentAssistant;
192   //    }
193   //
194   //    /*
195   //     * @see ITextOperationTarget#doOperation(int)
196   //     */
197   //    public void doOperation(int operation) {
198   //
199   //      if (getTextWidget() == null)
200   //        return;
201   //
202   //      switch (operation) {
203   //        case CONTENTASSIST_PROPOSALS :
204   //          String msg = fContentAssistant.showPossibleCompletions();
205   //          setStatusLineErrorMessage(msg);
206   //          return;
207   //        case UNDO :
208   //          fIgnoreTextConverters = true;
209   //          break;
210   //        case REDO :
211   //          fIgnoreTextConverters = true;
212   //          break;
213   //      }
214   //
215   //      super.doOperation(operation);
216   //    }
217   //
218   //    public void insertTextConverter(ITextConverter textConverter, int index)
219   // {
220   //      throw new UnsupportedOperationException();
221   //    }
222   //
223   //    public void addTextConverter(ITextConverter textConverter) {
224   //      if (fTextConverters == null) {
225   //        fTextConverters = new ArrayList(1);
226   //        fTextConverters.add(textConverter);
227   //      } else if (!fTextConverters.contains(textConverter))
228   //        fTextConverters.add(textConverter);
229   //    }
230   //
231   //    public void removeTextConverter(ITextConverter textConverter) {
232   //      if (fTextConverters != null) {
233   //        fTextConverters.remove(textConverter);
234   //        if (fTextConverters.size() == 0)
235   //          fTextConverters = null;
236   //      }
237   //    }
238   //
239   //    /*
240   //     * @see TextViewer#customizeDocumentCommand(DocumentCommand)
241   //     */
242   //    protected void customizeDocumentCommand(DocumentCommand command) {
243   //      super.customizeDocumentCommand(command);
244   //      if (!fIgnoreTextConverters && fTextConverters != null) {
245   //        for (Iterator e = fTextConverters.iterator(); e.hasNext();)
246   //           ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(),
247   // command);
248   //      }
249   //      fIgnoreTextConverters = false;
250   //    }
251   //
252   //    public IVerticalRuler getVerticalRuler() {
253   //      return fCachedVerticalRuler;
254   //    }
255   //
256   //    public boolean isVerticalRulerVisible() {
257   //      return fCachedIsVerticalRulerVisible;
258   //    }
259   //
260   //    public OverviewRuler getOverviewRuler() {
261   //      return fOverviewRuler;
262   //    }
263   //
264   //    /*
265   //     * @see TextViewer#createControl(Composite, int)
266   //     */
267   //    protected void createControl(Composite parent, int styles) {
268   //      // do nothing here
269   //    }
270   //
271   //    protected void delayedCreateControl(Composite parent, int styles) {
272   //      //create the viewer
273   //      super.createControl(parent, styles);
274   //
275   //      Control control = getControl();
276   //      if (control instanceof Composite) {
277   //        Composite composite = (Composite) control;
278   //        composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this));
279   //        fOverviewRuler.createControl(composite, this);
280   //      }
281   //    }
282   //    protected void ensureOverviewHoverManagerInstalled() {
283   //      if (fOverviewRulerHoveringController == null && fAnnotationHover != null
284   // && fHoverControlCreator != null) {
285   //        fOverviewRulerHoveringController =
286   //          new OverviewRulerHoverManager(fOverviewRuler, this, fAnnotationHover,
287   // fHoverControlCreator);
288   //        fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
289   //      }
290   //    }
291   //
292   //    public void hideOverviewRuler() {
293   //      fIsOverviewRulerVisible = false;
294   //      Control control = getControl();
295   //      if (control instanceof Composite) {
296   //        Composite composite = (Composite) control;
297   //        composite.layout();
298   //      }
299   //      if (fOverviewRulerHoveringController != null) {
300   //        fOverviewRulerHoveringController.dispose();
301   //        fOverviewRulerHoveringController = null;
302   //      }
303   //    }
304   //
305   //    public void showOverviewRuler() {
306   //      fIsOverviewRulerVisible = true;
307   //      Control control = getControl();
308   //      if (control instanceof Composite) {
309   //        Composite composite = (Composite) control;
310   //        composite.layout();
311   //      }
312   //      ensureOverviewHoverManagerInstalled();
313   //    }
314   //
315   //    public boolean isOverviewRulerVisible() {
316   //      return fIsOverviewRulerVisible;
317   //    }
318   //
319   //    /*
320   //     * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
321   //     */
322   //    public void setDocument(
323   //      IDocument document,
324   //      IAnnotationModel annotationModel,
325   //      int visibleRegionOffset,
326   //      int visibleRegionLength) {
327   //      super.setDocument(document, annotationModel, visibleRegionOffset,
328   // visibleRegionLength);
329   //      fOverviewRuler.setModel(annotationModel);
330   //    }
331   //
332   //    // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
333   //    public void updateIndentationPrefixes() {
334   //      SourceViewerConfiguration configuration = getSourceViewerConfiguration();
335   //      String[] types = configuration.getConfiguredContentTypes(this);
336   //      for (int i = 0; i < types.length; i++) {
337   //        String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
338   //        if (prefixes != null && prefixes.length > 0)
339   //          setIndentPrefixes(prefixes, types[i]);
340   //      }
341   //    }
342   //
343   //    /*
344   //     * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
345   //     */
346   //    public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
347   //      if (WorkbenchHelp.isContextHelpDisplayed())
348   //        return false;
349   //      return super.requestWidgetToken(requester);
350   //    }
351   //
352   //    /*
353   //     * @see
354   // org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
355   //     */
356   //    public void configure(SourceViewerConfiguration configuration) {
357   //      super.configure(configuration);
358   //      // prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this),
359   // IDocument.DEFAULT_CONTENT_TYPE);
360   //    }
361   //
362   //    protected void handleDispose() {
363   //      fOverviewRuler = null;
364   //
365   //      if (fOverviewRulerHoveringController != null) {
366   //        fOverviewRulerHoveringController.dispose();
367   //        fOverviewRulerHoveringController = null;
368   //      }
369   //
370   //      super.handleDispose();
371   //    }
372   //
373   //  };
374   class AdaptedSourceViewer extends JavaSourceViewer {
375     private List fTextConverters;
376
377     private boolean fIgnoreTextConverters = false;
378
379     //                  private JavaCorrectionAssistant fCorrectionAssistant;
380     public AdaptedSourceViewer(Composite parent, IVerticalRuler verticalRuler,
381         IOverviewRuler overviewRuler, boolean showAnnotationsOverview,
382         int styles, IPreferenceStore store) {
383       super(parent, verticalRuler, overviewRuler, showAnnotationsOverview,
384           styles, store);
385     }
386
387     //          public AdaptedSourceViewer(Composite parent,
388     //                          IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
389     //                          boolean showAnnotationsOverview, int styles) {
390     //                  super(parent, verticalRuler, overviewRuler,
391     //                                  showAnnotationsOverview, styles);
392     //          }
393     public IContentAssistant getContentAssistant() {
394       return fContentAssistant;
395     }
396
397     /*
398      * @see ITextOperationTarget#doOperation(int)
399      */
400     public void doOperation(int operation) {
401       if (getTextWidget() == null)
402         return;
403       switch (operation) {
404       case CONTENTASSIST_PROPOSALS:
405         String msg = fContentAssistant.showPossibleCompletions();
406         setStatusLineErrorMessage(msg);
407         return;
408       //                                        case CORRECTIONASSIST_PROPOSALS:
409       //                                                fCorrectionAssistant.showPossibleCompletions();
410       //                                                return;
411       case UNDO:
412         fIgnoreTextConverters = true;
413         break;
414       case REDO:
415         fIgnoreTextConverters = true;
416         break;
417       }
418       super.doOperation(operation);
419     }
420
421     /*
422      * @see ITextOperationTarget#canDoOperation(int)
423      */
424     public boolean canDoOperation(int operation) {
425       //                                if (operation == CORRECTIONASSIST_PROPOSALS)
426       //                                        return isEditable();
427       return super.canDoOperation(operation);
428     }
429
430     /*
431      * @see TextViewer#handleDispose()
432      */
433     protected void handleDispose() {
434       //                                if (fCorrectionAssistant != null) {
435       //                                        fCorrectionAssistant.uninstall();
436       //                                        fCorrectionAssistant= null;
437       //                                }
438       super.handleDispose();
439     }
440
441     public void insertTextConverter(ITextConverter textConverter, int index) {
442       throw new UnsupportedOperationException();
443     }
444
445     public void addTextConverter(ITextConverter textConverter) {
446       if (fTextConverters == null) {
447         fTextConverters = new ArrayList(1);
448         fTextConverters.add(textConverter);
449       } else if (!fTextConverters.contains(textConverter))
450         fTextConverters.add(textConverter);
451     }
452
453     public void removeTextConverter(ITextConverter textConverter) {
454       if (fTextConverters != null) {
455         fTextConverters.remove(textConverter);
456         if (fTextConverters.size() == 0)
457           fTextConverters = null;
458       }
459     }
460
461     /*
462      * @see TextViewer#customizeDocumentCommand(DocumentCommand)
463      */
464     protected void customizeDocumentCommand(DocumentCommand command) {
465       super.customizeDocumentCommand(command);
466       if (!fIgnoreTextConverters && fTextConverters != null) {
467         for (Iterator e = fTextConverters.iterator(); e.hasNext();)
468           ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(),
469               command);
470       }
471       fIgnoreTextConverters = false;
472     }
473
474     // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
475     public void updateIndentationPrefixes() {
476       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
477       String[] types = configuration.getConfiguredContentTypes(this);
478       for (int i = 0; i < types.length; i++) {
479         String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
480         if (prefixes != null && prefixes.length > 0)
481           setIndentPrefixes(prefixes, types[i]);
482       }
483     }
484
485     /*
486      * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
487      */
488     public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
489       if (WorkbenchHelp.isContextHelpDisplayed())
490         return false;
491       return super.requestWidgetToken(requester);
492     }
493
494     /*
495      * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
496      */
497     public void configure(SourceViewerConfiguration configuration) {
498       super.configure(configuration);
499       //                                fCorrectionAssistant= new
500       // JavaCorrectionAssistant(CompilationUnitEditor.this);
501       //                                fCorrectionAssistant.install(this);
502       //TODO install SmartBracesAutoEditStrategy
503       //                                prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this),
504       // IDocument.DEFAULT_CONTENT_TYPE);
505     }
506   };
507
508   static class TabConverter implements ITextConverter {
509     private int fTabRatio;
510
511     private ILineTracker fLineTracker;
512
513     public TabConverter() {
514     }
515
516     public void setNumberOfSpacesPerTab(int ratio) {
517       fTabRatio = ratio;
518     }
519
520     public void setLineTracker(ILineTracker lineTracker) {
521       fLineTracker = lineTracker;
522     }
523
524     private int insertTabString(StringBuffer buffer, int offsetInLine) {
525       if (fTabRatio == 0)
526         return 0;
527       int remainder = offsetInLine % fTabRatio;
528       remainder = fTabRatio - remainder;
529       for (int i = 0; i < remainder; i++)
530         buffer.append(' ');
531       return remainder;
532     }
533
534     public void customizeDocumentCommand(IDocument document,
535         DocumentCommand command) {
536       String text = command.text;
537       if (text == null)
538         return;
539       int index = text.indexOf('\t');
540       if (index > -1) {
541         StringBuffer buffer = new StringBuffer();
542         fLineTracker.set(command.text);
543         int lines = fLineTracker.getNumberOfLines();
544         try {
545           for (int i = 0; i < lines; i++) {
546             int offset = fLineTracker.getLineOffset(i);
547             int endOffset = offset + fLineTracker.getLineLength(i);
548             String line = text.substring(offset, endOffset);
549             int position = 0;
550             if (i == 0) {
551               IRegion firstLine = document
552                   .getLineInformationOfOffset(command.offset);
553               position = command.offset - firstLine.getOffset();
554             }
555             int length = line.length();
556             for (int j = 0; j < length; j++) {
557               char c = line.charAt(j);
558               if (c == '\t') {
559                 position += insertTabString(buffer, position);
560               } else {
561                 buffer.append(c);
562                 ++position;
563               }
564             }
565           }
566           command.text = buffer.toString();
567         } catch (BadLocationException x) {
568         }
569       }
570     }
571   };
572
573   private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
574     final char fExitCharacter;
575
576     public ExitPolicy(char exitCharacter) {
577       fExitCharacter = exitCharacter;
578     }
579
580     /*
581      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionManager,
582      *      org.eclipse.swt.events.VerifyEvent, int, int)
583      */
584     public ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event,
585         int offset, int length) {
586       if (event.character == fExitCharacter) {
587         if (manager.anyPositionIncludes(offset, length))
588           return new ExitFlags(LinkedPositionUI.COMMIT
589               | LinkedPositionUI.UPDATE_CARET, false);
590         else
591           return new ExitFlags(LinkedPositionUI.COMMIT, true);
592       }
593       switch (event.character) {
594       case '\b':
595         if (manager.getFirstPosition().length == 0)
596           return new ExitFlags(0, false);
597         else
598           return null;
599       case '\n':
600       case '\r':
601         return new ExitFlags(LinkedPositionUI.COMMIT, true);
602       default:
603         return null;
604       }
605     }
606   }
607
608   private static class BracketLevel {
609     int fOffset;
610
611     int fLength;
612
613     LinkedPositionManager fManager;
614
615     LinkedPositionUI fEditor;
616   };
617
618   private class BracketInserter implements VerifyKeyListener,
619       LinkedPositionUI.ExitListener {
620     private boolean fCloseBracketsPHP = true;
621
622     private boolean fCloseStringsPHP = true;
623
624     private boolean fCloseBracketsHTML = true;
625
626     private boolean fCloseStringsHTML = true;
627
628     private int fOffset;
629
630     private int fLength;
631
632     public void setCloseBracketsPHPEnabled(boolean enabled) {
633       fCloseBracketsPHP = enabled;
634     }
635
636     public void setCloseStringsPHPEnabled(boolean enabled) {
637       fCloseStringsPHP = enabled;
638     }
639
640     public void setCloseBracketsHTMLEnabled(boolean enabled) {
641       fCloseBracketsHTML = enabled;
642     }
643
644     public void setCloseStringsHTMLEnabled(boolean enabled) {
645       fCloseStringsHTML = enabled;
646     }
647
648     private boolean hasIdentifierToTheRight(IDocument document, int offset) {
649       try {
650         int end = offset;
651         IRegion endLine = document.getLineInformationOfOffset(end);
652         int maxEnd = endLine.getOffset() + endLine.getLength();
653         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
654           ++end;
655         return end != maxEnd
656             && Scanner.isPHPIdentifierPart(document.getChar(end));
657       } catch (BadLocationException e) {
658         // be conservative
659         return true;
660       }
661     }
662
663     private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
664       try {
665         int start = offset;
666         IRegion startLine = document.getLineInformationOfOffset(start);
667         int minStart = startLine.getOffset();
668         while (start != minStart
669             && Character.isWhitespace(document.getChar(start - 1)))
670           --start;
671         return start != minStart
672             && Scanner.isPHPIdentifierPart(document.getChar(start - 1));
673       } catch (BadLocationException e) {
674         return true;
675       }
676     }
677
678     private boolean hasCharacterToTheRight(IDocument document, int offset,
679         char character) {
680       try {
681         int end = offset;
682         IRegion endLine = document.getLineInformationOfOffset(end);
683         int maxEnd = endLine.getOffset() + endLine.getLength();
684         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
685           ++end;
686         return end != maxEnd && document.getChar(end) == character;
687       } catch (BadLocationException e) {
688         // be conservative
689         return true;
690       }
691     }
692
693     /*
694      * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
695      */
696     public void verifyKey(VerifyEvent event) {
697       if (!event.doit)
698         return;
699       final ISourceViewer sourceViewer = getSourceViewer();
700       IDocument document = sourceViewer.getDocument();
701       final Point selection = sourceViewer.getSelectedRange();
702       final int offset = selection.x;
703       final int length = selection.y;
704       try {
705         ITypedRegion partition = document.getPartition(offset);
706         String type = partition.getType();
707         if (type.equals(IPHPPartitions.PHP_PARTITIONING)) {
708           switch (event.character) {
709           case '(':
710             if (hasCharacterToTheRight(document, offset + length, '('))
711               return;
712           // fall through
713           case '[':
714             if (!fCloseBracketsPHP)
715               return;
716             if (hasIdentifierToTheRight(document, offset + length))
717               return;
718           // fall through
719           case '"':
720             if (event.character == '"') {
721               if (!fCloseStringsPHP)
722                 return;
723               // changed for statements like echo "" print ""
724               //    if (hasIdentifierToTheLeft(document, offset)
725               // ||
726               // hasIdentifierToTheRight(document, offset +
727               // length))
728               if (hasIdentifierToTheRight(document, offset + length))
729                 return;
730             }
731             //     ITypedRegion partition=
732             // document.getPartition(offset);
733             //       if (!
734             // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
735             // &&
736             // (partition.getOffset() != offset))
737             //         return;
738             final char character = event.character;
739             final char closingCharacter = getPeerCharacter(character);
740             final StringBuffer buffer = new StringBuffer();
741             buffer.append(character);
742             buffer.append(closingCharacter);
743             document.replace(offset, length, buffer.toString());
744             LinkedPositionManager manager = new LinkedPositionManager(document);
745             manager.addPosition(offset + 1, 0);
746             fOffset = offset;
747             fLength = 2;
748             LinkedPositionUI editor = new LinkedPositionUI(sourceViewer,
749                 manager);
750             editor.setCancelListener(this);
751             editor.setExitPolicy(new ExitPolicy(closingCharacter));
752             editor.setFinalCaretOffset(offset + 2);
753             editor.enter();
754             IRegion newSelection = editor.getSelectedRegion();
755             sourceViewer.setSelectedRange(newSelection.getOffset(),
756                 newSelection.getLength());
757             event.doit = false;
758           }
759         } else if (type.equals(IPHPPartitions.HTML)
760             || type.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
761           switch (event.character) {
762           case '(':
763             if (hasCharacterToTheRight(document, offset + length, '('))
764               return;
765           // fall through
766           case '[':
767             if (!fCloseBracketsHTML)
768               return;
769             if (hasIdentifierToTheRight(document, offset + length))
770               return;
771           // fall through
772           case '"':
773             if (event.character == '"') {
774               if (!fCloseStringsHTML)
775                 return;
776               if (hasIdentifierToTheLeft(document, offset)
777                   || hasIdentifierToTheRight(document, offset + length))
778                 return;
779             }
780             //     ITypedRegion partition=
781             // document.getPartition(offset);
782             //       if (!
783             // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
784             // &&
785             // (partition.getOffset() != offset))
786             //         return;
787             final char character = event.character;
788             final char closingCharacter = getPeerCharacter(character);
789             final StringBuffer buffer = new StringBuffer();
790             buffer.append(character);
791             buffer.append(closingCharacter);
792             document.replace(offset, length, buffer.toString());
793             LinkedPositionManager manager = new LinkedPositionManager(document);
794             manager.addPosition(offset + 1, 0);
795             fOffset = offset;
796             fLength = 2;
797             LinkedPositionUI editor = new LinkedPositionUI(sourceViewer,
798                 manager);
799             editor.setCancelListener(this);
800             editor.setExitPolicy(new ExitPolicy(closingCharacter));
801             editor.setFinalCaretOffset(offset + 2);
802             editor.enter();
803             IRegion newSelection = editor.getSelectedRegion();
804             sourceViewer.setSelectedRange(newSelection.getOffset(),
805                 newSelection.getLength());
806             event.doit = false;
807           }
808         }
809       } catch (BadLocationException e) {
810       }
811     }
812
813     /*
814      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
815      */
816     public void exit(boolean accept) {
817       if (accept)
818         return;
819       // remove brackets
820       try {
821         final ISourceViewer sourceViewer = getSourceViewer();
822         IDocument document = sourceViewer.getDocument();
823         document.replace(fOffset, fLength, null);
824       } catch (BadLocationException e) {
825       }
826     }
827   }
828
829   /** The editor's save policy */
830   protected ISavePolicy fSavePolicy;
831
832   /**
833    * Listener to annotation model changes that updates the error tick in the tab
834    * image
835    */
836   private JavaEditorErrorTickUpdater fJavaEditorErrorTickUpdater;
837
838   /** The editor's paint manager */
839   //  private PaintManager fPaintManager;
840   /** The editor's bracket painter */
841   private BracketPainter fBracketPainter;
842
843   /** The editor's bracket matcher */
844   private PHPPairMatcher fBracketMatcher;
845
846   /** The editor's line painter */
847   private LinePainter fLinePainter;
848
849   /** The editor's print margin ruler painter */
850   private PrintMarginPainter fPrintMarginPainter;
851
852   /** The editor's problem painter */
853   //  private ProblemPainter fProblemPainter;
854   /** The editor's tab converter */
855   private TabConverter fTabConverter;
856
857   /** History for structure select action */
858   //private SelectionHistory fSelectionHistory;
859   /** The preference property change listener for php core. */
860   //  private IPropertyChangeListener fPropertyChangeListener = new
861   // PropertyChangeListener();
862   /** The remembered java element */
863   private IJavaElement fRememberedElement;
864
865   /** The remembered selection */
866   private ITextSelection fRememberedSelection;
867
868   /** The remembered php element offset */
869   private int fRememberedElementOffset;
870
871   /** The bracket inserter. */
872   private BracketInserter fBracketInserter = new BracketInserter();
873
874   /** The standard action groups added to the menu */
875   private GenerateActionGroup fGenerateActionGroup;
876
877   private CompositeActionGroup fContextMenuGroup;
878
879   //  private class PropertyChangeListener implements IPropertyChangeListener {
880   //    /*
881   //     * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
882   //     */
883   //    public void
884   // propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
885   // event) {
886   //      handlePreferencePropertyChanged(event);
887   //    }
888   //  }
889   /* Preference key for code formatter tab size */
890   private final static String CODE_FORMATTER_TAB_SIZE = JavaCore.FORMATTER_TAB_SIZE;
891
892   /** Preference key for matching brackets */
893   private final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
894
895   /** Preference key for matching brackets color */
896   private final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
897
898   /** Preference key for highlighting current line */
899   private final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
900
901   /** Preference key for highlight color of current line */
902   private final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
903
904   /** Preference key for showing print marging ruler */
905   private final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
906
907   /** Preference key for print margin ruler color */
908   private final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
909
910   /** Preference key for print margin ruler column */
911   private final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
912
913   /** Preference key for inserting spaces rather than tabs */
914   private final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
915
916   /** Preference key for error indication */
917   //  private final static String ERROR_INDICATION =
918   // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
919   /** Preference key for error color */
920   //  private final static String ERROR_INDICATION_COLOR =
921   // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
922   /** Preference key for warning indication */
923   //  private final static String WARNING_INDICATION =
924   // PreferenceConstants.EDITOR_WARNING_INDICATION;
925   /** Preference key for warning color */
926   //  private final static String WARNING_INDICATION_COLOR =
927   // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
928   /** Preference key for task indication */
929   private final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
930
931   /** Preference key for task color */
932   private final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
933
934   /** Preference key for bookmark indication */
935   private final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
936
937   /** Preference key for bookmark color */
938   private final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
939
940   /** Preference key for search result indication */
941   private final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
942
943   /** Preference key for search result color */
944   private final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
945
946   /** Preference key for unknown annotation indication */
947   private final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
948
949   /** Preference key for unknown annotation color */
950   private final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
951
952   /** Preference key for linked position color */
953   private final static String LINKED_POSITION_COLOR = PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
954
955   /** Preference key for shwoing the overview ruler */
956   private final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
957
958   /** Preference key for error indication in overview ruler */
959   private final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
960
961   /** Preference key for warning indication in overview ruler */
962   private final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
963
964   /** Preference key for task indication in overview ruler */
965   private final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
966
967   /** Preference key for bookmark indication in overview ruler */
968   private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
969
970   /** Preference key for search result indication in overview ruler */
971   private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
972
973   /** Preference key for unknown annotation indication in overview ruler */
974   private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
975
976   /** Preference key for automatically closing strings */
977   private final static String CLOSE_STRINGS_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_PHP;
978
979   /** Preference key for automatically wrapping Java strings */
980   private final static String WRAP_STRINGS = PreferenceConstants.EDITOR_WRAP_STRINGS;
981
982   /** Preference key for automatically closing brackets and parenthesis */
983   private final static String CLOSE_BRACKETS_PHP = PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP;
984
985   /** Preference key for automatically closing phpdocs and comments */
986   private final static String CLOSE_JAVADOCS = PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
987
988   /** Preference key for automatically adding phpdoc tags */
989   private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
990
991   /** Preference key for automatically formatting phpdocs */
992   private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
993
994   /** Preference key for automatically closing strings */
995   private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
996
997   /** Preference key for automatically closing brackets and parenthesis */
998   private final static String CLOSE_BRACKETS_HTML = PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML;
999
1000   /** Preference key for smart paste */
1001   private final static String SMART_PASTE = PreferenceConstants.EDITOR_SMART_PASTE;
1002
1003   //  private final static class AnnotationInfo {
1004   //    public String fColorPreference;
1005   //    public String fOverviewRulerPreference;
1006   //    public String fEditorPreference;
1007   //  };
1008   //  private final static Map ANNOTATION_MAP;
1009   //  static {
1010   //
1011   //    AnnotationInfo info;
1012   //    ANNOTATION_MAP = new HashMap();
1013   //
1014   //    info = new AnnotationInfo();
1015   //    info.fColorPreference = TASK_INDICATION_COLOR;
1016   //    info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
1017   //    info.fEditorPreference = TASK_INDICATION;
1018   //    ANNOTATION_MAP.put(AnnotationType.TASK, info);
1019   //
1020   //    info = new AnnotationInfo();
1021   //    info.fColorPreference = ERROR_INDICATION_COLOR;
1022   //    info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
1023   //    info.fEditorPreference = ERROR_INDICATION;
1024   //    ANNOTATION_MAP.put(AnnotationType.ERROR, info);
1025   //
1026   //    info = new AnnotationInfo();
1027   //    info.fColorPreference = WARNING_INDICATION_COLOR;
1028   //    info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
1029   //    info.fEditorPreference = WARNING_INDICATION;
1030   //    ANNOTATION_MAP.put(AnnotationType.WARNING, info);
1031   //
1032   //    info = new AnnotationInfo();
1033   //    info.fColorPreference = BOOKMARK_INDICATION_COLOR;
1034   //    info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
1035   //    info.fEditorPreference = BOOKMARK_INDICATION;
1036   //    ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
1037   //
1038   //    info = new AnnotationInfo();
1039   //    info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
1040   //    info.fOverviewRulerPreference =
1041   // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
1042   //    info.fEditorPreference = SEARCH_RESULT_INDICATION;
1043   //    ANNOTATION_MAP.put(AnnotationType.SEARCH, info);
1044   //
1045   //    info = new AnnotationInfo();
1046   //    info.fColorPreference = UNKNOWN_INDICATION_COLOR;
1047   //    info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
1048   //    info.fEditorPreference = UNKNOWN_INDICATION;
1049   //    ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
1050   //  };
1051   //
1052   //  private final static AnnotationType[] ANNOTATION_LAYERS =
1053   //    new AnnotationType[] {
1054   //      AnnotationType.UNKNOWN,
1055   //      AnnotationType.BOOKMARK,
1056   //      AnnotationType.TASK,
1057   //      AnnotationType.SEARCH,
1058   //      AnnotationType.WARNING,
1059   //      AnnotationType.ERROR };
1060   /**
1061    * Creates a new php unit editor.
1062    */
1063   public PHPUnitEditor() {
1064     super();
1065     setDocumentProvider(PHPeclipsePlugin.getDefault()
1066         .getCompilationUnitDocumentProvider());
1067     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
1068     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
1069     setOutlinerContextMenuId("#PHPOutlinerContext"); //$NON-NLS-1$
1070     // don't set help contextId, we install our own help context
1071     fSavePolicy = null;
1072     fJavaEditorErrorTickUpdater = new JavaEditorErrorTickUpdater(this);
1073   }
1074
1075   /*
1076    * @see AbstractTextEditor#createActions()
1077    */
1078   protected void createActions() {
1079     super.createActions();
1080     Action action;
1081     //          Action action= new
1082     // TextOperationAction(PHPEditorMessages.getResourceBundle(),
1083     // "CorrectionAssistProposal.", this, CORRECTIONASSIST_PROPOSALS);
1084     // //$NON-NLS-1$
1085     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.CORRECTION_ASSIST_PROPOSALS);
1086     //          setAction("CorrectionAssistProposal", action); //$NON-NLS-1$
1087     //          markAsStateDependentAction("CorrectionAssistProposal", true);
1088     // //$NON-NLS-1$
1089     //// WorkbenchHelp.setHelp(action,
1090     // IJavaHelpContextIds.QUICK_FIX_ACTION);
1091     action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(),
1092         "ContentAssistProposal.", this); //$NON-NLS-1$
1093     action
1094         .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
1095     setAction("ContentAssistProposal", action); //$NON-NLS-1$
1096     markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
1097     //          WorkbenchHelp.setHelp(action,
1098     // IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
1099     //          action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1100     //                          "ContentAssistContextInformation.", this,
1101     //                          ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
1102     //          action
1103     //                          .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
1104     //          setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
1105     //          markAsStateDependentAction("ContentAssistContextInformation", true);
1106     // //$NON-NLS-1$
1107     //          WorkbenchHelp.setHelp(action,
1108     // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
1109     //          action= new
1110     // TextOperationAction(PHPEditorMessages.getResourceBundle(),
1111     // "ContentAssistCompletePrefix.", this, CONTENTASSIST_COMPLETE_PREFIX);
1112     // //$NON-NLS-1$
1113     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_COMPLETE_PREFIX);
1114     //          setAction("ContentAssistCompletePrefix", action); //$NON-NLS-1$
1115     //          markAsStateDependentAction("ContentAssistCompletePrefix", true);
1116     // //$NON-NLS-1$
1117     //// WorkbenchHelp.setHelp(action,
1118     // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
1119     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1120         "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
1121     action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
1122     setAction("Comment", action); //$NON-NLS-1$
1123     markAsStateDependentAction("Comment", true); //$NON-NLS-1$
1124     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION);
1125     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1126         "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
1127     action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
1128     setAction("Uncomment", action); //$NON-NLS-1$
1129     markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
1130     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION);
1131
1132     action = new ToggleCommentAction(PHPEditorMessages.getResourceBundle(),
1133         "ToggleComment.", this); //$NON-NLS-1$
1134     action.setActionDefinitionId(PHPEditorActionDefinitionIds.TOGGLE_COMMENT);
1135     setAction("ToggleComment", action); //$NON-NLS-1$
1136     markAsStateDependentAction("ToggleComment", true); //$NON-NLS-1$
1137     //WorkbenchHelp.setHelp(action,
1138     // IJavaHelpContextIds.TOGGLE_COMMENT_ACTION);
1139     configureToggleCommentAction();
1140         
1141     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1142         "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
1143     action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
1144     setAction("Format", action); //$NON-NLS-1$
1145     markAsStateDependentAction("Format", true); //$NON-NLS-1$
1146     markAsSelectionDependentAction("Format", true); //$NON-NLS-1$               
1147     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION);
1148
1149 //    action = new AddBlockCommentAction(PHPEditorMessages.getResourceBundle(),
1150 //        "AddBlockComment.", this); //$NON-NLS-1$
1151 //    action
1152 //        .setActionDefinitionId(PHPEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
1153 //    setAction("AddBlockComment", action); //$NON-NLS-1$
1154 //    markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
1155 //    markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$            
1156 //    //                WorkbenchHelp.setHelp(action,
1157 //    // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
1158 //    action = new RemoveBlockCommentAction(
1159 //        PHPEditorMessages.getResourceBundle(), "RemoveBlockComment.", this); //$NON-NLS-1$
1160 //    action
1161 //        .setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);
1162 //    setAction("RemoveBlockComment", action); //$NON-NLS-1$
1163 //    markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
1164 //    markAsSelectionDependentAction("RemoveBlockComment", true); //$NON-NLS-1$         
1165     //          WorkbenchHelp.setHelp(action,
1166     // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
1167     //          action= new IndentAction(PHPEditorMessages.getResourceBundle(),
1168     // "Indent.", this, false); //$NON-NLS-1$
1169     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.INDENT);
1170     //          setAction("Indent", action); //$NON-NLS-1$
1171     //          markAsStateDependentAction("Indent", true); //$NON-NLS-1$
1172     //          markAsSelectionDependentAction("Indent", true); //$NON-NLS-1$
1173     //// WorkbenchHelp.setHelp(action, IJavaHelpContextIds.INDENT_ACTION);
1174     //          
1175     //          action= new IndentAction(PHPEditorMessages.getResourceBundle(),
1176     // "Indent.", this, true); //$NON-NLS-1$
1177     //          setAction("IndentOnTab", action); //$NON-NLS-1$
1178     //          markAsStateDependentAction("IndentOnTab", true); //$NON-NLS-1$
1179     //          markAsSelectionDependentAction("IndentOnTab", true); //$NON-NLS-1$
1180     //          
1181     if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_TAB)) {
1182       // don't replace Shift Right - have to make sure their enablement is
1183       // mutually exclusive
1184       //                        removeActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT);
1185       setActionActivationCode("IndentOnTab", '\t', -1, SWT.NONE); //$NON-NLS-1$
1186     }
1187     fGenerateActionGroup = new GenerateActionGroup(this,
1188         ITextEditorActionConstants.GROUP_EDIT);
1189     fActionGroups = new CompositeActionGroup(
1190         new ActionGroup[] { fGenerateActionGroup });
1191     //    We have to keep the context menu group separate to have better
1192     // control
1193     // over positioning
1194     fContextMenuGroup = new CompositeActionGroup(
1195         new ActionGroup[] { fGenerateActionGroup });
1196     //      rg,
1197     //      new LocalHistoryActionGroup(this,
1198     // ITextEditorActionConstants.GROUP_EDIT)});
1199
1200   }
1201
1202   /*
1203    * @see JavaEditor#getElementAt(int)
1204    */
1205   protected IJavaElement getElementAt(int offset) {
1206     return getElementAt(offset, true);
1207   }
1208
1209   /**
1210    * Returns the most narrow element including the given offset. If
1211    * <code>reconcile</code> is <code>true</code> the editor's input element
1212    * is reconciled in advance. If it is <code>false</code> this method only
1213    * returns a result if the editor's input element does not need to be
1214    * reconciled.
1215    * 
1216    * @param offset
1217    *          the offset included by the retrieved element
1218    * @param reconcile
1219    *          <code>true</code> if working copy should be reconciled
1220    */
1221   protected IJavaElement getElementAt(int offset, boolean reconcile) {
1222     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
1223         .getWorkingCopyManager();
1224     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
1225     if (unit != null) {
1226       try {
1227         if (reconcile) {
1228           synchronized (unit) {
1229             unit.reconcile();
1230           }
1231           return unit.getElementAt(offset);
1232         } else if (unit.isConsistent())
1233           return unit.getElementAt(offset);
1234       } catch (JavaModelException x) {
1235         PHPeclipsePlugin.log(x.getStatus());
1236         // nothing found, be tolerant and go on
1237       }
1238     }
1239     return null;
1240   }
1241
1242   /*
1243    * @see JavaEditor#getCorrespondingElement(IJavaElement)
1244    */
1245   protected IJavaElement getCorrespondingElement(IJavaElement element) {
1246     try {
1247       return EditorUtility.getWorkingCopy(element, true);
1248     } catch (JavaModelException x) {
1249       PHPeclipsePlugin.log(x.getStatus());
1250       // nothing found, be tolerant and go on
1251     }
1252     return null;
1253   }
1254
1255   public void createPartControl(Composite parent) {
1256     super.createPartControl(parent);
1257     //    fPaintManager = new PaintManager(getSourceViewer());
1258     LinePainter linePainter;
1259     linePainter = new LinePainter(getSourceViewer());
1260     linePainter
1261         .setHighlightColor(new Color(Display.getCurrent(), 225, 235, 224));
1262     //    fPaintManager.addPainter(linePainter);
1263     if (isBracketHighlightingEnabled())
1264       startBracketHighlighting();
1265     if (isLineHighlightingEnabled())
1266       startLineHighlighting();
1267     if (isPrintMarginVisible())
1268       showPrintMargin();
1269     //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1270     //    while (e.hasNext()) {
1271     //      AnnotationType type = (AnnotationType) e.next();
1272     //      if (isAnnotationIndicationEnabled(type))
1273     //        startAnnotationIndication(type);
1274     //    }
1275     if (isTabConversionEnabled())
1276       startTabConversion();
1277     //    if (isOverviewRulerVisible())
1278     //      showOverviewRuler();
1279     //
1280     //    Preferences preferences =
1281     // PHPeclipsePlugin.getDefault().getPluginPreferences();
1282     //    preferences.addPropertyChangeListener(fPropertyChangeListener);
1283     IPreferenceStore preferenceStore = getPreferenceStore();
1284     boolean closeBracketsPHP = preferenceStore.getBoolean(CLOSE_BRACKETS_PHP);
1285     boolean closeStringsPHP = preferenceStore.getBoolean(CLOSE_STRINGS_PHP);
1286     boolean closeBracketsHTML = preferenceStore.getBoolean(CLOSE_BRACKETS_HTML);
1287     boolean closeStringsHTML = preferenceStore.getBoolean(CLOSE_STRINGS_HTML);
1288     fBracketInserter.setCloseBracketsPHPEnabled(closeBracketsPHP);
1289     fBracketInserter.setCloseStringsPHPEnabled(closeStringsPHP);
1290     fBracketInserter.setCloseBracketsHTMLEnabled(closeBracketsHTML);
1291     fBracketInserter.setCloseStringsHTMLEnabled(closeStringsHTML);
1292     ISourceViewer sourceViewer = getSourceViewer();
1293     if (sourceViewer instanceof ITextViewerExtension)
1294       ((ITextViewerExtension) sourceViewer)
1295           .prependVerifyKeyListener(fBracketInserter);
1296   }
1297
1298   private static char getPeerCharacter(char character) {
1299     switch (character) {
1300     case '(':
1301       return ')';
1302     case ')':
1303       return '(';
1304     case '[':
1305       return ']';
1306     case ']':
1307       return '[';
1308     case '"':
1309       return character;
1310     default:
1311       throw new IllegalArgumentException();
1312     }
1313   }
1314
1315   private void startBracketHighlighting() {
1316     if (fBracketPainter == null) {
1317       ISourceViewer sourceViewer = getSourceViewer();
1318       fBracketPainter = new BracketPainter(sourceViewer);
1319       fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1320       //      fPaintManager.addPainter(fBracketPainter);
1321     }
1322   }
1323
1324   private void stopBracketHighlighting() {
1325     if (fBracketPainter != null) {
1326       //      fPaintManager.removePainter(fBracketPainter);
1327       fBracketPainter.deactivate(true);
1328       fBracketPainter.dispose();
1329       fBracketPainter = null;
1330     }
1331   }
1332
1333   private boolean isBracketHighlightingEnabled() {
1334     IPreferenceStore store = getPreferenceStore();
1335     return store.getBoolean(MATCHING_BRACKETS);
1336   }
1337
1338   private void startLineHighlighting() {
1339     if (fLinePainter == null) {
1340       ISourceViewer sourceViewer = getSourceViewer();
1341       fLinePainter = new LinePainter(sourceViewer);
1342       fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
1343       //      fPaintManager.addPainter(fLinePainter);
1344     }
1345   }
1346
1347   private void stopLineHighlighting() {
1348     if (fLinePainter != null) {
1349       //      fPaintManager.removePainter(fLinePainter);
1350       fLinePainter.deactivate(true);
1351       fLinePainter.dispose();
1352       fLinePainter = null;
1353     }
1354   }
1355
1356   private boolean isLineHighlightingEnabled() {
1357     IPreferenceStore store = getPreferenceStore();
1358     return store.getBoolean(CURRENT_LINE);
1359   }
1360
1361   private void showPrintMargin() {
1362     if (fPrintMarginPainter == null) {
1363       fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
1364       fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1365       fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(
1366           PRINT_MARGIN_COLUMN));
1367       //      fPaintManager.addPainter(fPrintMarginPainter);
1368     }
1369   }
1370
1371   private void hidePrintMargin() {
1372     if (fPrintMarginPainter != null) {
1373       //      fPaintManager.removePainter(fPrintMarginPainter);
1374       fPrintMarginPainter.deactivate(true);
1375       fPrintMarginPainter.dispose();
1376       fPrintMarginPainter = null;
1377     }
1378   }
1379
1380   private boolean isPrintMarginVisible() {
1381     IPreferenceStore store = getPreferenceStore();
1382     return store.getBoolean(PRINT_MARGIN);
1383   }
1384
1385   //  private void startAnnotationIndication(AnnotationType annotationType) {
1386   //    if (fProblemPainter == null) {
1387   //      fProblemPainter = new ProblemPainter(this, getSourceViewer());
1388   //// fPaintManager.addPainter(fProblemPainter);
1389   //    }
1390   //    fProblemPainter.setColor(annotationType, getColor(annotationType));
1391   //    fProblemPainter.paintAnnotations(annotationType, true);
1392   //    fProblemPainter.paint(IPainter.CONFIGURATION);
1393   //  }
1394   //
1395   //  private void shutdownAnnotationIndication() {
1396   //    if (fProblemPainter != null) {
1397   //
1398   //      if (!fProblemPainter.isPaintingAnnotations()) {
1399   //// fPaintManager.removePainter(fProblemPainter);
1400   //        fProblemPainter.deactivate(true);
1401   //        fProblemPainter.dispose();
1402   //        fProblemPainter = null;
1403   //      } else {
1404   //        fProblemPainter.paint(IPainter.CONFIGURATION);
1405   //      }
1406   //    }
1407   //  }
1408   //
1409   //  private void stopAnnotationIndication(AnnotationType annotationType) {
1410   //    if (fProblemPainter != null) {
1411   //      fProblemPainter.paintAnnotations(annotationType, false);
1412   //      shutdownAnnotationIndication();
1413   //    }
1414   //  }
1415   //
1416   //  private boolean isAnnotationIndicationEnabled(AnnotationType
1417   // annotationType) {
1418   //    IPreferenceStore store = getPreferenceStore();
1419   //    AnnotationInfo info = (AnnotationInfo)
1420   // ANNOTATION_MAP.get(annotationType);
1421   //    if (info != null)
1422   //      return store.getBoolean(info.fEditorPreference);
1423   //    return false;
1424   //  }
1425   //
1426   //  private boolean
1427   // isAnnotationIndicationInOverviewRulerEnabled(AnnotationType
1428   // annotationType) {
1429   //    IPreferenceStore store = getPreferenceStore();
1430   //    AnnotationInfo info = (AnnotationInfo)
1431   // ANNOTATION_MAP.get(annotationType);
1432   //    if (info != null)
1433   //      return store.getBoolean(info.fOverviewRulerPreference);
1434   //    return false;
1435   //  }
1436   //
1437   //  private void showAnnotationIndicationInOverviewRuler(AnnotationType
1438   // annotationType, boolean show) {
1439   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1440   //    OverviewRuler ruler = asv.getOverviewRuler();
1441   //    if (ruler != null) {
1442   //      ruler.setColor(annotationType, getColor(annotationType));
1443   //      ruler.showAnnotation(annotationType, show);
1444   //      ruler.update();
1445   //    }
1446   //  }
1447   //
1448   //  private void setColorInOverviewRuler(AnnotationType annotationType, Color
1449   // color) {
1450   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1451   //    OverviewRuler ruler = asv.getOverviewRuler();
1452   //    if (ruler != null) {
1453   //      ruler.setColor(annotationType, color);
1454   //      ruler.update();
1455   //    }
1456   //  }
1457
1458   private int getTabSize() {
1459     Preferences preferences = PHPeclipsePlugin.getDefault()
1460         .getPluginPreferences();
1461     return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1462   }
1463
1464   private boolean isTabConversionEnabled() {
1465     IPreferenceStore store = getPreferenceStore();
1466     return store.getBoolean(SPACES_FOR_TABS);
1467   }
1468
1469   //  private void showOverviewRuler() {
1470   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1471   //    asv.showOverviewRuler();
1472   //
1473   //    OverviewRuler overviewRuler = asv.getOverviewRuler();
1474   //    if (overviewRuler != null) {
1475   //      for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1476   //        AnnotationType type = ANNOTATION_LAYERS[i];
1477   //        overviewRuler.setLayer(type, i);
1478   //        if (isAnnotationIndicationInOverviewRulerEnabled(type))
1479   //          showAnnotationIndicationInOverviewRuler(type, true);
1480   //      }
1481   //    }
1482   //  }
1483   //
1484   //  private void hideOverviewRuler() {
1485   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1486   //    asv.hideOverviewRuler();
1487   //  }
1488   //
1489   //  private boolean isOverviewRulerVisible() {
1490   //    IPreferenceStore store = getPreferenceStore();
1491   //    return store.getBoolean(OVERVIEW_RULER);
1492   //  }
1493   private Color getColor(String key) {
1494     RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1495     return getColor(rgb);
1496   }
1497
1498   private Color getColor(RGB rgb) {
1499     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1500     return textTools.getColorManager().getColor(rgb);
1501   }
1502
1503   //  private Color getColor(AnnotationType annotationType) {
1504   //    AnnotationInfo info = (AnnotationInfo)
1505   // ANNOTATION_MAP.get(annotationType);
1506   //    if (info != null)
1507   //      return getColor(info.fColorPreference);
1508   //    return null;
1509   //  }
1510   public void dispose() {
1511     ISourceViewer sourceViewer = getSourceViewer();
1512     if (sourceViewer instanceof ITextViewerExtension)
1513       ((ITextViewerExtension) sourceViewer)
1514           .removeVerifyKeyListener(fBracketInserter);
1515     //    if (fPropertyChangeListener != null) {
1516     //      Preferences preferences =
1517     // PHPeclipsePlugin.getDefault().getPluginPreferences();
1518     //      preferences.removePropertyChangeListener(fPropertyChangeListener);
1519     //      fPropertyChangeListener = null;
1520     //    }
1521     if (fJavaEditorErrorTickUpdater != null) {
1522       fJavaEditorErrorTickUpdater.dispose();
1523       fJavaEditorErrorTickUpdater = null;
1524     }
1525     //    if (fSelectionHistory != null)
1526     //      fSelectionHistory.dispose();
1527     //    if (fPaintManager != null) {
1528     //      fPaintManager.dispose();
1529     //      fPaintManager = null;
1530     //    }
1531     if (fActionGroups != null) {
1532       fActionGroups.dispose();
1533       fActionGroups = null;
1534     }
1535     super.dispose();
1536   }
1537
1538   //  protected AnnotationType getAnnotationType(String preferenceKey) {
1539   //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1540   //    while (e.hasNext()) {
1541   //      AnnotationType type = (AnnotationType) e.next();
1542   //      AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1543   //      if (info != null) {
1544   //        if (preferenceKey.equals(info.fColorPreference)
1545   //          || preferenceKey.equals(info.fEditorPreference)
1546   //          || preferenceKey.equals(info.fOverviewRulerPreference))
1547   //          return type;
1548   //      }
1549   //    }
1550   //    return null;
1551   //  }
1552   /*
1553    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1554    */
1555   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1556     try {
1557       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1558       if (asv != null) {
1559         String p = event.getProperty();
1560         if (CLOSE_BRACKETS_PHP.equals(p)) {
1561           fBracketInserter.setCloseBracketsPHPEnabled(getPreferenceStore()
1562               .getBoolean(p));
1563           return;
1564         }
1565         if (CLOSE_STRINGS_PHP.equals(p)) {
1566           fBracketInserter.setCloseStringsPHPEnabled(getPreferenceStore()
1567               .getBoolean(p));
1568           return;
1569         }
1570         if (CLOSE_BRACKETS_HTML.equals(p)) {
1571           fBracketInserter.setCloseBracketsHTMLEnabled(getPreferenceStore()
1572               .getBoolean(p));
1573           return;
1574         }
1575         if (CLOSE_STRINGS_HTML.equals(p)) {
1576           fBracketInserter.setCloseStringsHTMLEnabled(getPreferenceStore()
1577               .getBoolean(p));
1578           return;
1579         }
1580         if (SPACES_FOR_TABS.equals(p)) {
1581           if (isTabConversionEnabled())
1582             startTabConversion();
1583           else
1584             stopTabConversion();
1585           return;
1586         }
1587         if (MATCHING_BRACKETS.equals(p)) {
1588           if (isBracketHighlightingEnabled())
1589             startBracketHighlighting();
1590           else
1591             stopBracketHighlighting();
1592           return;
1593         }
1594         if (MATCHING_BRACKETS_COLOR.equals(p)) {
1595           if (fBracketPainter != null)
1596             fBracketPainter
1597                 .setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1598           return;
1599         }
1600         if (CURRENT_LINE.equals(p)) {
1601           if (isLineHighlightingEnabled())
1602             startLineHighlighting();
1603           else
1604             stopLineHighlighting();
1605           return;
1606         }
1607         if (CURRENT_LINE_COLOR.equals(p)) {
1608           if (fLinePainter != null) {
1609             stopLineHighlighting();
1610             startLineHighlighting();
1611           }
1612           return;
1613         }
1614         if (PRINT_MARGIN.equals(p)) {
1615           if (isPrintMarginVisible())
1616             showPrintMargin();
1617           else
1618             hidePrintMargin();
1619           return;
1620         }
1621         if (PRINT_MARGIN_COLOR.equals(p)) {
1622           if (fPrintMarginPainter != null)
1623             fPrintMarginPainter
1624                 .setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1625           return;
1626         }
1627         if (PRINT_MARGIN_COLUMN.equals(p)) {
1628           if (fPrintMarginPainter != null)
1629             fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore()
1630                 .getInt(PRINT_MARGIN_COLUMN));
1631           return;
1632         }
1633         //        if (OVERVIEW_RULER.equals(p)) {
1634         //          if (isOverviewRulerVisible())
1635         //            showOverviewRuler();
1636         //          else
1637         //            hideOverviewRuler();
1638         //          return;
1639         //        }
1640         //        AnnotationType type = getAnnotationType(p);
1641         //        if (type != null) {
1642         //
1643         //          AnnotationInfo info = (AnnotationInfo)
1644         // ANNOTATION_MAP.get(type);
1645         //          if (info.fColorPreference.equals(p)) {
1646         //            Color color = getColor(type);
1647         //            if (fProblemPainter != null) {
1648         //              fProblemPainter.setColor(type, color);
1649         //              fProblemPainter.paint(IPainter.CONFIGURATION);
1650         //            }
1651         //            setColorInOverviewRuler(type, color);
1652         //            return;
1653         //          }
1654         //
1655         //          if (info.fEditorPreference.equals(p)) {
1656         //            if (isAnnotationIndicationEnabled(type))
1657         //              startAnnotationIndication(type);
1658         //            else
1659         //              stopAnnotationIndication(type);
1660         //            return;
1661         //          }
1662         //
1663         //          if (info.fOverviewRulerPreference.equals(p)) {
1664         //            if (isAnnotationIndicationInOverviewRulerEnabled(type))
1665         //              showAnnotationIndicationInOverviewRuler(type, true);
1666         //            else
1667         //              showAnnotationIndicationInOverviewRuler(type, false);
1668         //            return;
1669         //          }
1670         //        }
1671         IContentAssistant c = asv.getContentAssistant();
1672         if (c instanceof ContentAssistant)
1673           ContentAssistPreference.changeConfiguration((ContentAssistant) c,
1674               getPreferenceStore(), event);
1675       }
1676     } finally {
1677       super.handlePreferenceStoreChanged(event);
1678     }
1679   }
1680
1681   /*
1682    * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
1683    */
1684   protected void handlePreferencePropertyChanged(
1685       org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1686     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1687     if (asv != null) {
1688       String p = event.getProperty();
1689       if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1690         asv.updateIndentationPrefixes();
1691         if (fTabConverter != null)
1692           fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1693       }
1694     }
1695     super.handlePreferencePropertyChanged(event);
1696   }
1697
1698   /**
1699    * Handles a property change event describing a change of the php core's
1700    * preferences and updates the preference related editor properties.
1701    * 
1702    * @param event
1703    *          the property change event
1704    */
1705   //  protected void
1706   // handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
1707   // event) {
1708   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1709   //    if (asv != null) {
1710   //      String p = event.getProperty();
1711   //      if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1712   //        asv.updateIndentationPrefixes();
1713   //        if (fTabConverter != null)
1714   //          fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1715   //      }
1716   //    }
1717   //  }
1718   /*
1719    * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#createJavaSourceViewer(org.eclipse.swt.widgets.Composite,
1720    *      org.eclipse.jface.text.source.IVerticalRuler,
1721    *      org.eclipse.jface.text.source.IOverviewRuler, boolean, int)
1722    */
1723   protected ISourceViewer createJavaSourceViewer(Composite parent,
1724       IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
1725       boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
1726     return new AdaptedSourceViewer(parent, verticalRuler, overviewRuler,
1727         isOverviewRulerVisible, styles, store);
1728   }
1729
1730   //  protected ISourceViewer createJavaSourceViewer(Composite parent,
1731   // IVerticalRuler ruler, int styles) {
1732   //    return new AdaptedSourceViewer(parent, ruler, styles);
1733   //  }
1734   private boolean isValidSelection(int offset, int length) {
1735     IDocumentProvider provider = getDocumentProvider();
1736     if (provider != null) {
1737       IDocument document = provider.getDocument(getEditorInput());
1738       if (document != null) {
1739         int end = offset + length;
1740         int documentLength = document.getLength();
1741         return 0 <= offset && offset <= documentLength && 0 <= end
1742             && end <= documentLength;
1743       }
1744     }
1745     return false;
1746   }
1747
1748   /*
1749    * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1750    */
1751   protected boolean canHandleMove(IEditorInput originalElement,
1752       IEditorInput movedElement) {
1753     String oldExtension = ""; //$NON-NLS-1$
1754     if (originalElement instanceof IFileEditorInput) {
1755       IFile file = ((IFileEditorInput) originalElement).getFile();
1756       if (file != null) {
1757         String ext = file.getFileExtension();
1758         if (ext != null)
1759           oldExtension = ext;
1760       }
1761     }
1762     String newExtension = ""; //$NON-NLS-1$
1763     if (movedElement instanceof IFileEditorInput) {
1764       IFile file = ((IFileEditorInput) movedElement).getFile();
1765       if (file != null)
1766         newExtension = file.getFileExtension();
1767     }
1768     return oldExtension.equals(newExtension);
1769   }
1770   /*
1771          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#getInputElement()
1772          */
1773         protected IJavaElement getInputJavaElement() {
1774                 return PHPeclipsePlugin.getDefault().getWorkingCopyManager().getWorkingCopy(getEditorInput());
1775         }
1776   /*
1777    * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
1778    */
1779   public void editorContextMenuAboutToShow(IMenuManager menu) {
1780     super.editorContextMenuAboutToShow(menu);
1781     ActionContext context = new ActionContext(getSelectionProvider()
1782         .getSelection());
1783     fContextMenuGroup.setContext(context);
1784     fContextMenuGroup.fillContextMenu(menu);
1785     fContextMenuGroup.setContext(null);
1786   }
1787
1788   /*
1789    * @see JavaEditor#setOutlinePageInput(JavaOutlinePage, IEditorInput)
1790    */
1791   protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input) {
1792     if (page != null) {
1793       IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
1794           .getWorkingCopyManager();
1795       page.setInput(manager.getWorkingCopy(input));
1796     }
1797   }
1798
1799   /*
1800    * @see AbstractTextEditor#performSaveOperation(WorkspaceModifyOperation,
1801    *      IProgressMonitor)
1802    */
1803   //  protected void performSaveOperation(WorkspaceModifyOperation operation,
1804   // IProgressMonitor progressMonitor) {
1805   //    IDocumentProvider p = getDocumentProvider();
1806   //    if (p instanceof PHPDocumentProvider) {
1807   //      PHPDocumentProvider cp = (PHPDocumentProvider) p;
1808   //      cp.setSavePolicy(fSavePolicy);
1809   //    }
1810   //
1811   //    try {
1812   //      super.performSaveOperation(operation, progressMonitor);
1813   //    } finally {
1814   //      if (p instanceof PHPDocumentProvider) {
1815   //        PHPDocumentProvider cp = (PHPDocumentProvider) p;
1816   //        cp.setSavePolicy(null);
1817   //      }
1818   //    }
1819   //  }
1820   /*
1821    * @see AbstractTextEditor#doSave(IProgressMonitor)
1822    */
1823   public void doSave(IProgressMonitor progressMonitor) {
1824
1825     IDocumentProvider p = getDocumentProvider();
1826     if (p == null) {
1827       // editor has been closed
1828       return;
1829     }
1830
1831     if (p.isDeleted(getEditorInput())) {
1832
1833       if (isSaveAsAllowed()) {
1834
1835         /*
1836          * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the
1837          * editors. Changed Behavior to make sure that if called inside a
1838          * regular save (because of deletion of input element) there is a way to
1839          * report back to the caller.
1840          */
1841         performSaveAs(progressMonitor);
1842
1843       } else {
1844
1845         /*
1846          * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there
1847          * Missing resources.
1848          */
1849         Shell shell = getSite().getShell();
1850         MessageDialog
1851             .openError(
1852                 shell,
1853                 PHPEditorMessages
1854                     .getString("PHPUnitEditor.error.saving.title1"), PHPEditorMessages.getString("PHPUnitEditor.error.saving.message1")); //$NON-NLS-1$ //$NON-NLS-2$
1855       }
1856
1857     } else {
1858
1859       setStatusLineErrorMessage(null);
1860
1861       updateState(getEditorInput());
1862       validateState(getEditorInput());
1863
1864       IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
1865           .getWorkingCopyManager();
1866       ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
1867
1868       if (unit != null) {
1869         synchronized (unit) {
1870           performSave(false, progressMonitor);
1871         }
1872       } else
1873         performSave(false, progressMonitor);
1874     }
1875     ShowExternalPreviewAction a = ShowExternalPreviewAction.getInstance();
1876     if (a != null) {
1877       a.refresh();
1878     }
1879   }
1880
1881   public boolean isSaveAsAllowed() {
1882     return true;
1883   }
1884
1885   /**
1886    * The compilation unit editor implementation of this
1887    * <code>AbstractTextEditor</code> method asks the user for the workspace
1888    * path of a file resource and saves the document there. See
1889    * http://dev.eclipse.org/bugs/show_bug.cgi?id=6295
1890    * 
1891    * @param progressMonitor
1892    *          the progress monitor
1893    */
1894   protected void performSaveAs(IProgressMonitor progressMonitor) {
1895
1896     Shell shell = getSite().getShell();
1897     IEditorInput input = getEditorInput();
1898
1899     SaveAsDialog dialog = new SaveAsDialog(shell);
1900
1901     IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input)
1902         .getFile()
1903         : null;
1904     if (original != null)
1905       dialog.setOriginalFile(original);
1906
1907     dialog.create();
1908
1909     IDocumentProvider provider = getDocumentProvider();
1910     if (provider == null) {
1911       // editor has been programmatically closed while the dialog was open
1912       return;
1913     }
1914
1915     if (provider.isDeleted(input) && original != null) {
1916       String message = PHPEditorMessages
1917           .getFormattedString(
1918               "CompilationUnitEditor.warning.save.delete", new Object[] { original.getName() }); //$NON-NLS-1$
1919       dialog.setErrorMessage(null);
1920       dialog.setMessage(message, IMessageProvider.WARNING);
1921     }
1922
1923     if (dialog.open() == Window.CANCEL) {
1924       if (progressMonitor != null)
1925         progressMonitor.setCanceled(true);
1926       return;
1927     }
1928
1929     IPath filePath = dialog.getResult();
1930     if (filePath == null) {
1931       if (progressMonitor != null)
1932         progressMonitor.setCanceled(true);
1933       return;
1934     }
1935
1936     IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
1937     IFile file = workspaceRoot.getFile(filePath);
1938     final IEditorInput newInput = new FileEditorInput(file);
1939
1940     boolean success = false;
1941     try {
1942
1943       provider.aboutToChange(newInput);
1944       getDocumentProvider().saveDocument(progressMonitor, newInput,
1945           getDocumentProvider().getDocument(getEditorInput()), true);
1946       success = true;
1947
1948     } catch (CoreException x) {
1949       IStatus status = x.getStatus();
1950       if (status == null || status.getSeverity() != IStatus.CANCEL)
1951         ErrorDialog
1952             .openError(
1953                 shell,
1954                 PHPEditorMessages
1955                     .getString("CompilationUnitEditor.error.saving.title2"), PHPEditorMessages.getString("CompilationUnitEditor.error.saving.message2"), x.getStatus()); //$NON-NLS-1$ //$NON-NLS-2$
1956     } finally {
1957       provider.changed(newInput);
1958       if (success)
1959         setInput(newInput);
1960     }
1961
1962     if (progressMonitor != null)
1963       progressMonitor.setCanceled(!success);
1964   }
1965
1966   /*
1967    * @see AbstractTextEditor#doSetInput(IEditorInput)
1968    */
1969   protected void doSetInput(IEditorInput input) throws CoreException {
1970     super.doSetInput(input);
1971     configureTabConverter();
1972     configureToggleCommentAction();
1973   }
1974
1975   //    /*
1976   //     * @see
1977   // org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#installOverrideIndicator(boolean)
1978   //     * @since 3.0
1979   //     */
1980   //    protected void installOverrideIndicator(boolean waitForReconcilation) {
1981   //            IAnnotationModel model=
1982   // getDocumentProvider().getAnnotationModel(getEditorInput());
1983   //            if (!waitForReconcilation)
1984   //                    super.installOverrideIndicator(false);
1985   //            else {
1986   //                    uninstallOverrideIndicator();
1987   //                    IJavaElement inputElement= getInputJavaElement();
1988   //                    if (model == null || inputElement == null)
1989   //                            return;
1990   //                    
1991   //                    fOverrideIndicatorManager= new OverrideIndicatorManager(model,
1992   // inputElement, null);
1993   //                    addReconcileListener(fOverrideIndicatorManager);
1994   //            }
1995   //    }
1996   //    
1997   //    /*
1998   //     * @see
1999   // org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#uninstallOverrideIndicator()
2000   //     * @since 3.0
2001   //     */
2002   //    protected void uninstallOverrideIndicator() {
2003   //            if (fOverrideIndicatorManager != null)
2004   //                    removeReconcileListener(fOverrideIndicatorManager);
2005   //            super.uninstallOverrideIndicator();
2006   //    }
2007
2008   /**
2009    * Configures the toggle comment action
2010    * 
2011    * @since 3.0
2012    */
2013   private void configureToggleCommentAction() {
2014     IAction action = getAction("ToggleComment"); //$NON-NLS-1$
2015     if (action instanceof ToggleCommentAction) {
2016       ISourceViewer sourceViewer = getSourceViewer();
2017       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
2018       ((ToggleCommentAction) action).configure(sourceViewer, configuration);
2019     }
2020   }
2021
2022   private void configureTabConverter() {
2023     if (fTabConverter != null) {
2024       IDocumentProvider provider = getDocumentProvider();
2025       if (provider instanceof PHPDocumentProvider) {
2026         PHPDocumentProvider cup = (PHPDocumentProvider) provider;
2027         fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
2028       }
2029     }
2030   }
2031
2032   private void startTabConversion() {
2033     if (fTabConverter == null) {
2034       fTabConverter = new TabConverter();
2035       configureTabConverter();
2036       fTabConverter.setNumberOfSpacesPerTab(getTabSize());
2037       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2038       asv.addTextConverter(fTabConverter);
2039       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
2040       asv.updateIndentationPrefixes();
2041     }
2042   }
2043
2044   private void stopTabConversion() {
2045     if (fTabConverter != null) {
2046       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2047       asv.removeTextConverter(fTabConverter);
2048       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
2049       asv.updateIndentationPrefixes();
2050       fTabConverter = null;
2051     }
2052   }
2053
2054   /*
2055    * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean,
2056    *      org.eclipse.core.runtime.IProgressMonitor)
2057    */
2058   protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
2059     IDocumentProvider p = getDocumentProvider();
2060     if (p instanceof PHPDocumentProvider) {
2061       PHPDocumentProvider cp = (PHPDocumentProvider) p;
2062       cp.setSavePolicy(fSavePolicy);
2063     }
2064     try {
2065       super.performSave(overwrite, progressMonitor);
2066     } finally {
2067       if (p instanceof PHPDocumentProvider) {
2068         PHPDocumentProvider cp = (PHPDocumentProvider) p;
2069         cp.setSavePolicy(null);
2070       }
2071     }
2072   }
2073
2074   /*
2075    * @see AbstractTextEditor#doSaveAs
2076    */
2077   public void doSaveAs() {
2078     if (askIfNonWorkbenchEncodingIsOk()) {
2079       super.doSaveAs();
2080     }
2081   }
2082
2083   /**
2084    * Asks the user if it is ok to store in non-workbench encoding.
2085    * 
2086    * @return <true>if the user wants to continue
2087    */
2088   private boolean askIfNonWorkbenchEncodingIsOk() {
2089     IDocumentProvider provider = getDocumentProvider();
2090     if (provider instanceof IStorageDocumentProvider) {
2091       IEditorInput input = getEditorInput();
2092       IStorageDocumentProvider storageProvider = (IStorageDocumentProvider) provider;
2093       String encoding = storageProvider.getEncoding(input);
2094       String defaultEncoding = storageProvider.getDefaultEncoding();
2095       if (encoding != null && !encoding.equals(defaultEncoding)) {
2096         Shell shell = getSite().getShell();
2097         String title = PHPEditorMessages
2098             .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.title"); //$NON-NLS-1$
2099         String msg;
2100         if (input != null)
2101           msg = MessageFormat
2102               .format(
2103                   PHPEditorMessages
2104                       .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message1"),
2105                   new String[] { input.getName(), encoding }); //$NON-NLS-1$
2106         else
2107           msg = MessageFormat
2108               .format(
2109                   PHPEditorMessages
2110                       .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message2"),
2111                   new String[] { encoding }); //$NON-NLS-1$
2112         return MessageDialog.openQuestion(shell, title, msg);
2113       }
2114     }
2115     return true;
2116   }
2117
2118   /*
2119    * @see IReconcilingParticipant#reconciled()
2120    */
2121   public void reconciled() {
2122     if (synchronizeOutlineOnCursorMove()) {
2123       Shell shell = getSite().getShell();
2124       if (shell != null && !shell.isDisposed()) {
2125         shell.getDisplay().asyncExec(new Runnable() {
2126           public void run() {
2127             synchronizeOutlinePageSelection();
2128           }
2129         });
2130       }
2131     }
2132   }
2133
2134   protected void updateStateDependentActions() {
2135     super.updateStateDependentActions();
2136     fGenerateActionGroup.editorStateChanged();
2137   }
2138
2139   private boolean synchronizeOutlineOnCursorMove() {
2140     return PreferenceConstants.getPreferenceStore().getBoolean(
2141         PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE);
2142   }
2143
2144   /**
2145    * Returns the updated java element for the old java element.
2146    */
2147   private IJavaElement findElement(IJavaElement element) {
2148     if (element == null)
2149       return null;
2150     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
2151         .getWorkingCopyManager();
2152     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
2153     if (unit != null) {
2154       try {
2155         synchronized (unit) {
2156           unit.reconcile();
2157         }
2158         IJavaElement[] findings = unit.findElements(element);
2159         if (findings != null && findings.length > 0)
2160           return findings[0];
2161       } catch (JavaModelException x) {
2162         PHPeclipsePlugin.log(x.getStatus());
2163         // nothing found, be tolerant and go on
2164       }
2165     }
2166     return null;
2167   }
2168
2169   /**
2170    * Returns the offset of the given Java element.
2171    */
2172   private int getOffset(IJavaElement element) {
2173     if (element instanceof ISourceReference) {
2174       ISourceReference sr = (ISourceReference) element;
2175       try {
2176         ISourceRange srcRange = sr.getSourceRange();
2177         if (srcRange != null)
2178           return srcRange.getOffset();
2179       } catch (JavaModelException e) {
2180       }
2181     }
2182     return -1;
2183   }
2184
2185   /*
2186    * @see AbstractTextEditor#rememberSelection()
2187    */
2188   protected void rememberSelection() {
2189     ISelectionProvider sp = getSelectionProvider();
2190     fRememberedSelection = (sp == null ? null : (ITextSelection) sp
2191         .getSelection());
2192     if (fRememberedSelection != null) {
2193       fRememberedElement = getElementAt(fRememberedSelection.getOffset(), true);
2194       fRememberedElementOffset = getOffset(fRememberedElement);
2195     }
2196   }
2197
2198   /*
2199    * @see AbstractTextEditor#restoreSelection()
2200    */
2201   protected void restoreSelection() {
2202     try {
2203       if (getSourceViewer() == null || fRememberedSelection == null)
2204         return;
2205       IJavaElement newElement = findElement(fRememberedElement);
2206       int newOffset = getOffset(newElement);
2207       int delta = (newOffset > -1 && fRememberedElementOffset > -1) ? newOffset
2208           - fRememberedElementOffset : 0;
2209       if (isValidSelection(delta + fRememberedSelection.getOffset(),
2210           fRememberedSelection.getLength()))
2211         selectAndReveal(delta + fRememberedSelection.getOffset(),
2212             fRememberedSelection.getLength());
2213     } finally {
2214       fRememberedSelection = null;
2215       fRememberedElement = null;
2216       fRememberedElementOffset = -1;
2217     }
2218   }
2219
2220   //    /*
2221   //     * @see
2222   // org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
2223   //     * @since 3.0
2224   //     */
2225   //    public void aboutToBeReconciled() {
2226   //
2227   //            // Notify AST provider
2228   //            PHPeclipsePlugin.getDefault().getASTProvider().aboutToBeReconciled(getInputJavaElement());
2229   //            
2230   //            // Notify listeners
2231   //            Object[] listeners = fReconcilingListeners.getListeners();
2232   //            for (int i = 0, length= listeners.length; i < length; ++i)
2233   //                    ((IJavaReconcilingListener)listeners[i]).aboutToBeReconciled();
2234   //    }
2235   //    
2236   //    /*
2237   //     * @see
2238   // org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit,
2239   // boolean, IProgressMonitor)
2240   //     * @since 3.0
2241   //     */
2242   //    public void reconciled(net.sourceforge.phpdt.core.dom.CompilationUnit
2243   // ast, boolean forced, IProgressMonitor progressMonitor) {
2244   //
2245   //            // Always notify AST provider
2246   //            PHPeclipsePlugin.getDefault().getASTProvider().reconciled(ast,
2247   // getInputJavaElement());
2248   //            
2249   //            // Notify listeners
2250   //            Object[] listeners = fReconcilingListeners.getListeners();
2251   //            for (int i = 0, length= listeners.length; i < length; ++i)
2252   //                    ((IJavaReconcilingListener)listeners[i]).reconciled(ast, forced,
2253   // progressMonitor);
2254   //
2255   //            // Update Java Outline page selection
2256   //            if (!forced && !progressMonitor.isCanceled()) {
2257   //                    Shell shell= getSite().getShell();
2258   //                    if (shell != null && !shell.isDisposed()) {
2259   //                            shell.getDisplay().asyncExec(new Runnable() {
2260   //                                    public void run() {
2261   //                                            selectionChanged();
2262   //                                    }
2263   //                            });
2264   //                    }
2265   //            }
2266   //    }
2267 }