de893a872dd3c890dc9c0595e74cd3c3a06eafa1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 /**********************************************************************
4 Copyright (c) 2000, 2002 IBM Corp. and others.
5 All rights reserved. This program and the accompanying materials
6 are made available under the terms of the Common Public License v1.0
7 which accompanies this distribution, and is available at
8 http://www.eclipse.org/legal/cpl-v10.html
9
10 Contributors:
11     IBM Corporation - Initial implementation
12     Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
14 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
15 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
16 import net.sourceforge.phpeclipse.IPreferenceConstants;
17 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
18 import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner;
19 import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
20 import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
21
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.jface.action.Action;
25 import org.eclipse.jface.action.IAction;
26 import org.eclipse.jface.action.MenuManager;
27 import org.eclipse.jface.preference.IPreferenceStore;
28 import org.eclipse.jface.preference.PreferenceConverter;
29 import org.eclipse.jface.text.BadLocationException;
30 import org.eclipse.jface.text.IDocument;
31 import org.eclipse.jface.text.ITextOperationTarget;
32 import org.eclipse.jface.text.source.AnnotationRulerColumn;
33 import org.eclipse.jface.text.source.CompositeRuler;
34 import org.eclipse.jface.text.source.ISourceViewer;
35 import org.eclipse.jface.text.source.IVerticalRuler;
36 import org.eclipse.jface.text.source.IVerticalRulerColumn;
37 import org.eclipse.jface.text.source.LineNumberRulerColumn;
38 import org.eclipse.jface.util.IPropertyChangeListener;
39 import org.eclipse.jface.util.PropertyChangeEvent;
40 import org.eclipse.swt.graphics.Point;
41 import org.eclipse.swt.graphics.RGB;
42 import org.eclipse.ui.IEditorInput;
43 import org.eclipse.ui.actions.ActionContext;
44 import org.eclipse.ui.actions.ActionGroup;
45 import org.eclipse.ui.editors.text.TextEditor;
46 import org.eclipse.ui.texteditor.ContentAssistAction;
47 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
48 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
49 import org.eclipse.ui.texteditor.TextOperationAction;
50 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
51 /**
52  * PHP specific text editor.
53  */
54 public class PHPEditor extends TextEditor {
55
56   // protected PHPActionGroup fActionGroups;
57   /** The outline page */
58   private PHPContentOutlinePage fOutlinePage;
59   private IPreferenceStore phpPrefStore;
60
61   /** The line number ruler column */
62   private LineNumberRulerColumn fLineNumberRulerColumn;
63
64   protected CompositeActionGroup fActionGroups;
65   /** The standard action groups added to the menu */
66   private GenerateActionGroup fGenerateActionGroup;
67   private CompositeActionGroup fContextMenuGroup;
68   /**
69    * Default constructor.
70    */
71   public PHPEditor() {
72     super();
73     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
74   }
75
76   /**
77    *  Returns the standard action group of this editor.
78    */
79   protected ActionGroup getActionGroup() {
80     return fActionGroups;
81   } 
82   
83   public PHPContentOutlinePage getfOutlinePage() {
84     return fOutlinePage;
85   }
86
87   /** The <code>PHPEditor</code> implementation of this 
88    * <code>AbstractTextEditor</code> method extend the 
89    * actions to add those specific to the receiver
90    */
91   protected void createActions() {
92     super.createActions();
93     
94         Action action;
95 //    setAction(
96 //      "ContentAssistProposal",
97 //      new TextOperationAction(
98 //        PHPEditorMessages.getResourceBundle(),
99 //        "ContentAssistProposal.",
100 //        this,
101 //        ISourceViewer.CONTENTASSIST_PROPOSALS));
102         action= new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
103         action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);            
104         setAction("ContentAssistProposal", action); //$NON-NLS-1$
105         
106
107 //      System.out.println(action.getId());
108 //      System.out.println(action.getActionDefinitionId());
109         
110     setAction(
111       "ContentAssistTip",
112       new TextOperationAction(
113         PHPEditorMessages.getResourceBundle(),
114         "ContentAssistTip.",
115         this,
116         ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION));
117
118     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX);
119     action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
120     setAction("Comment", action);
121         
122 //      System.out.println(action.getId());
123 //      System.out.println(action.getActionDefinitionId());
124         
125     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX);
126     action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
127     setAction("Uncomment", action);
128
129 //      System.out.println(action.getId());
130 //      System.out.println(action.getActionDefinitionId());
131         
132
133   //  fActionGroups = new PHPActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
134
135     markAsStateDependentAction("Comment", true); //$NON-NLS-1$
136     markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
137
138     fGenerateActionGroup= new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
139
140     fActionGroups= new CompositeActionGroup(
141       new ActionGroup[] { fGenerateActionGroup }
142       );
143   
144     
145     // We have to keep the context menu group separate to have better control over positioning
146     fContextMenuGroup= new CompositeActionGroup(new ActionGroup[] {
147       fGenerateActionGroup });
148 //      rg, 
149 //      new LocalHistoryActionGroup(this, ITextEditorActionConstants.GROUP_EDIT)});
150   }
151
152   /** The <code>PHPEditor</code> implementation of this 
153    * <code>AbstractTextEditor</code> method performs any extra 
154    * disposal actions required by the php editor.
155    */
156   public void dispose() {
157     PHPEditorEnvironment.disconnect(this);
158     if (fOutlinePage != null)
159       fOutlinePage.setInput(null);
160       
161     if (fActionGroups != null)
162       fActionGroups.dispose();  
163       
164     super.dispose();
165   }
166
167   /** The <code>PHPEditor</code> implementation of this 
168    * <code>AbstractTextEditor</code> method performs any extra 
169    * revert behavior required by the php editor.
170    */
171   public void doRevertToSaved() {
172     super.doRevertToSaved();
173     if (fOutlinePage != null)
174       fOutlinePage.update();
175   }
176
177   /** The <code>PHPEditor</code> implementation of this 
178    * <code>AbstractTextEditor</code> method performs any extra 
179    * save behavior required by the php editor.
180    */
181   public void doSave(IProgressMonitor monitor) {
182     super.doSave(monitor);
183     // compile or not, according to the user preferences
184     IPreferenceStore store = phpPrefStore;
185     if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
186       IAction a = PHPParserAction.getInstance();
187       if (a != null)
188         a.run();
189     }
190     if (fOutlinePage != null)
191       fOutlinePage.update();
192   }
193
194   /** The <code>PHPEditor</code> implementation of this 
195    * <code>AbstractTextEditor</code> method performs any extra 
196    * save as behavior required by the php editor.
197    */
198   public void doSaveAs() {
199     super.doSaveAs();
200     if (fOutlinePage != null)
201       fOutlinePage.update();
202   }
203
204   /** The <code>PHPEditor</code> implementation of this 
205    * <code>AbstractTextEditor</code> method performs sets the 
206    * input of the outline page after AbstractTextEditor has set input.
207    */
208   public void doSetInput(IEditorInput input) throws CoreException {
209     super.doSetInput(input);
210     if (fOutlinePage != null)
211       fOutlinePage.setInput(input);
212   }
213
214   /** The <code>PHPEditor</code> implementation of this 
215    * <code>AbstractTextEditor</code> method adds any 
216    * PHPEditor specific entries.
217    */
218   public void editorContextMenuAboutToShow(MenuManager menu) {
219     super.editorContextMenuAboutToShow(menu);
220     //  addAction(menu, "ContentAssistProposal"); //$NON-NLS-1$
221     //  addAction(menu, "ContentAssistTip"); //$NON-NLS-1$
222     
223     // fActionGroups.fillContextMenu(menu);
224     
225     ActionContext context= new ActionContext(getSelectionProvider().getSelection());
226     fContextMenuGroup.setContext(context);
227     fContextMenuGroup.fillContextMenu(menu);
228     fContextMenuGroup.setContext(null);
229   }
230
231   protected void updateStateDependentActions() {
232     super.updateStateDependentActions();
233     fGenerateActionGroup.editorStateChanged();
234   }
235   
236   /** The <code>PHPEditor</code> implementation of this 
237    * <code>AbstractTextEditor</code> method performs gets
238    * the java content outline page if request is for a an 
239    * outline page.
240    */
241   public Object getAdapter(Class required) {
242     if (IContentOutlinePage.class.equals(required)) {
243       if (fOutlinePage == null) {
244         fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
245         if (getEditorInput() != null)
246           fOutlinePage.setInput(getEditorInput());
247       }
248       return fOutlinePage;
249     }
250     return super.getAdapter(required);
251   }
252
253   //  public void openContextHelp() {
254   //    IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
255   //    ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
256   //    int pos = selection.getOffset();
257   //    String word = getFunctionName(doc, pos);
258   //    openContextHelp(word);
259   //  }
260   //
261   //  private void openContextHelp(String word) {
262   //    open(word);
263   //  }
264   //
265   //  public static void open(String word) {
266   //    IHelp help = WorkbenchHelp.getHelpSupport();
267   //    if (help != null) {
268   //      IHelpResource helpResource = new PHPFunctionHelpResource(word);
269   //      WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
270   //    } else {
271   //      //   showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
272   //    }
273   //  }
274
275   private String getFunctionName(IDocument doc, int pos) {
276     Point word = PHPWordExtractor.findWord(doc, pos);
277     if (word != null) {
278       try {
279         return doc.get(word.x, word.y).replace('_', '-');
280       } catch (BadLocationException e) {
281       }
282     }
283     return "";
284   }
285
286   /*
287      * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
288      */
289   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
290
291     try {
292
293       ISourceViewer sourceViewer = getSourceViewer();
294       if (sourceViewer == null)
295         return;
296
297       String property = event.getProperty();
298
299       //      if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
300       //        Object value= event.getNewValue();
301       //        if (value instanceof Integer) {
302       //          sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
303       //        } else if (value instanceof String) {
304       //          sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
305       //        }
306       //        return;
307       //      }
308
309       if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
310         if (isLineNumberRulerVisible())
311           showLineNumberRuler();
312         else
313           hideLineNumberRuler();
314         return;
315       }
316
317       if (fLineNumberRulerColumn != null
318         && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
319           || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
320           || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
321
322         initializeLineNumberRulerColumn(fLineNumberRulerColumn);
323       }
324
325     } finally {
326       super.handlePreferenceStoreChanged(event);
327     }
328   }
329   /**
330    * Shows the line number ruler column.
331    */
332   private void showLineNumberRuler() {
333     IVerticalRuler v = getVerticalRuler();
334     if (v instanceof CompositeRuler) {
335       CompositeRuler c = (CompositeRuler) v;
336       c.addDecorator(1, createLineNumberRulerColumn());
337     }
338   }
339
340   /**
341   * Return whether the line number ruler column should be 
342   * visible according to the preference store settings.
343   * @return <code>true</code> if the line numbers should be visible
344   */
345   private boolean isLineNumberRulerVisible() {
346     // IPreferenceStore store= getPreferenceStore();
347     return phpPrefStore.getBoolean(IPreferenceConstants.LINE_NUMBER_RULER);
348   }
349   /**
350    * Hides the line number ruler column.
351    */
352   private void hideLineNumberRuler() {
353     IVerticalRuler v = getVerticalRuler();
354     if (v instanceof CompositeRuler) {
355       CompositeRuler c = (CompositeRuler) v;
356       try {
357         c.removeDecorator(1);
358       } catch (Throwable e) {
359       }
360     }
361   }
362
363   /**
364   * Initializes the given line number ruler column from the preference store.
365   * @param rulerColumn the ruler column to be initialized
366   */
367   protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
368     //   JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
369     PHPColorProvider manager = PHPEditorEnvironment.getPHPColorProvider();
370
371     if (phpPrefStore != null) {
372
373       RGB rgb = null;
374       // foreground color
375       if (phpPrefStore.contains(IPreferenceConstants.LINE_NUMBER_COLOR)) {
376         if (phpPrefStore.isDefault(IPreferenceConstants.LINE_NUMBER_COLOR))
377           rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR);
378         else
379           rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR);
380       }
381       rulerColumn.setForeground(manager.getColor(rgb));
382
383       rgb = null;
384       // background color
385       if (!phpPrefStore.getBoolean(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
386         if (phpPrefStore.contains(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) {
387           if (phpPrefStore.isDefault(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND))
388             rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
389           else
390             rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
391         }
392         rulerColumn.setBackground(manager.getColor(rgb));
393       }
394
395     }
396   }
397
398   /**
399    * Creates a new line number ruler column that is appropriately initialized.
400    */
401   protected IVerticalRulerColumn createLineNumberRulerColumn() {
402     fLineNumberRulerColumn = new LineNumberRulerColumn();
403     initializeLineNumberRulerColumn(fLineNumberRulerColumn);
404     return fLineNumberRulerColumn;
405   }
406
407   /*
408    * @see AbstractTextEditor#createVerticalRuler()
409    */
410   protected IVerticalRuler createVerticalRuler() {
411     CompositeRuler ruler = new CompositeRuler();
412     ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
413     if (isLineNumberRulerVisible())
414       ruler.addDecorator(1, createLineNumberRulerColumn());
415     return ruler;
416   }
417
418   /* (non-Javadoc)
419    * Method declared on AbstractTextEditor
420    */
421   protected void initializeEditor() {
422     PHPEditorEnvironment.connect(this);
423
424     setSourceViewerConfiguration(new PHPSourceViewerConfiguration());
425     setRangeIndicator(new DefaultRangeIndicator());
426     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
427     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
428     // setDocumentProvider(PHPeclipsePlugin.getCompilationUnitDocumentProvider());
429     phpPrefStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
430
431     phpPrefStore.addPropertyChangeListener(new IPropertyChangeListener() {
432       public void propertyChange(PropertyChangeEvent event) {
433         PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner();
434         if (scanner != null) {
435           scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider());
436         }
437         if (getSourceViewer() != null) {
438           getSourceViewer().invalidateTextPresentation();
439         }
440
441         String property = event.getProperty();
442         if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
443           if (isLineNumberRulerVisible())
444             showLineNumberRuler();
445           else
446             hideLineNumberRuler();
447           return;
448         }
449       }
450     });
451   }
452 }