Improved completion processor
[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.phpeclipse.IPreferenceConstants;
15 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
16 import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner;
17 import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
18 import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.help.IHelp;
22 import org.eclipse.help.IHelpResource;
23 import org.eclipse.jface.action.Action;
24 import org.eclipse.jface.action.IAction;
25 import org.eclipse.jface.action.MenuManager;
26 import org.eclipse.jface.preference.IPreferenceStore;
27 import org.eclipse.jface.preference.PreferenceConverter;
28 import org.eclipse.jface.text.BadLocationException;
29 import org.eclipse.jface.text.IDocument;
30 import org.eclipse.jface.text.ITextOperationTarget;
31 import org.eclipse.jface.text.ITextSelection;
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.editors.text.TextEditor;
44 import org.eclipse.ui.help.WorkbenchHelp;
45 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
46 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
47 import org.eclipse.ui.texteditor.TextOperationAction;
48 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
49 /**
50  * PHP specific text editor.
51  */
52 public class PHPEditor extends TextEditor {
53
54   protected PHPActionGroup actionGroup;
55   /** The outline page */
56   private PHPContentOutlinePage fOutlinePage;
57   private IPreferenceStore phpPrefStore;
58
59   /** The line number ruler column */
60   private LineNumberRulerColumn fLineNumberRulerColumn;
61
62   /**
63    * Default constructor.
64    */
65   public PHPEditor() {
66     super();
67   }
68
69   public PHPContentOutlinePage getfOutlinePage() {
70     return fOutlinePage; 
71   }
72   /** The <code>JavaEditor</code> implementation of this 
73    * <code>AbstractTextEditor</code> method extend the 
74    * actions to add those specific to the receiver
75    */
76   protected void createActions() {
77     super.createActions();
78     setAction(
79       "ContentAssistProposal",
80       new TextOperationAction(
81         PHPEditorMessages.getResourceBundle(),
82         "ContentAssistProposal.",
83         this,
84         ISourceViewer.CONTENTASSIST_PROPOSALS));
85     setAction(
86       "ContentAssistTip",
87       new TextOperationAction(
88         PHPEditorMessages.getResourceBundle(),
89         "ContentAssistTip.",
90         this,
91         ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION));
92
93     Action action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX);
94     action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
95     setAction("Comment", action);
96
97     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX);
98     action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
99     setAction("Uncomment", action);
100
101     actionGroup = new PHPActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
102
103   }
104
105   /** The <code>JavaEditor</code> implementation of this 
106    * <code>AbstractTextEditor</code> method performs any extra 
107    * disposal actions required by the java editor.
108    */
109   public void dispose() {
110     PHPEditorEnvironment.disconnect(this);
111     if (fOutlinePage != null)
112       fOutlinePage.setInput(null);
113     super.dispose();
114   }
115
116   /** The <code>PHPEditor</code> implementation of this 
117    * <code>AbstractTextEditor</code> method performs any extra 
118    * revert behavior required by the php editor.
119    */
120   public void doRevertToSaved() {
121     super.doRevertToSaved();
122     if (fOutlinePage != null)
123       fOutlinePage.update();
124   }
125
126   /** The <code>PHPEditor</code> implementation of this 
127    * <code>AbstractTextEditor</code> method performs any extra 
128    * save behavior required by the php editor.
129    */
130   public void doSave(IProgressMonitor monitor) {
131     super.doSave(monitor);
132     // compile or not, according to the user preferences
133     IPreferenceStore store = phpPrefStore;
134     if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
135       IAction a = PHPParserAction.getInstance();
136       if (a != null)
137         a.run();
138     }
139     if (fOutlinePage != null)
140       fOutlinePage.update();
141   }
142
143   /** The <code>PHPEditor</code> implementation of this 
144    * <code>AbstractTextEditor</code> method performs any extra 
145    * save as behavior required by the php editor.
146    */
147   public void doSaveAs() {
148     super.doSaveAs();
149     if (fOutlinePage != null)
150       fOutlinePage.update();
151   }
152
153   /** The <code>PHPEditor</code> implementation of this 
154    * <code>AbstractTextEditor</code> method performs sets the 
155    * input of the outline page after AbstractTextEditor has set input.
156    */
157   public void doSetInput(IEditorInput input) throws CoreException {
158     super.doSetInput(input);
159     if (fOutlinePage != null)
160       fOutlinePage.setInput(input);
161   }
162
163   /** The <code>JavaEditor</code> implementation of this 
164    * <code>AbstractTextEditor</code> method adds any 
165    * JavaEditor specific entries.
166    */
167   public void editorContextMenuAboutToShow(MenuManager menu) {
168     super.editorContextMenuAboutToShow(menu);
169     //  addAction(menu, "ContentAssistProposal"); //$NON-NLS-1$
170     //  addAction(menu, "ContentAssistTip"); //$NON-NLS-1$
171     actionGroup.fillContextMenu(menu);
172   }
173
174   /** The <code>JavaEditor</code> implementation of this 
175    * <code>AbstractTextEditor</code> method performs gets
176    * the java content outline page if request is for a an 
177    * outline page.
178    */
179   public Object getAdapter(Class required) {
180     if (IContentOutlinePage.class.equals(required)) {
181       if (fOutlinePage == null) {
182         fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
183         if (getEditorInput() != null)
184           fOutlinePage.setInput(getEditorInput());
185       }
186       return fOutlinePage;
187     }
188     return super.getAdapter(required);
189   }
190
191   public void openContextHelp() {
192     IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
193     ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
194     int pos = selection.getOffset();
195     String word = getFunctionName(doc, pos);
196     openContextHelp(word);
197   }
198
199   private void openContextHelp(String word) {
200     open(word);
201   }
202
203   public static void open(String word) {
204     IHelp help = WorkbenchHelp.getHelpSupport();
205     if (help != null) {
206       IHelpResource helpResource = new PHPFunctionHelpResource(word);
207       WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
208     } else {
209       //   showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
210     }
211   }
212
213   private String getFunctionName(IDocument doc, int pos) {
214     Point word = PHPWordExtractor.findWord(doc, pos);
215     if (word != null) {
216       try {
217         return doc.get(word.x, word.y).replace('_', '-');
218       } catch (BadLocationException e) {
219       }
220     }
221     return "";
222   }
223
224   /*
225      * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
226      */
227   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
228
229     try {
230
231       ISourceViewer sourceViewer = getSourceViewer();
232       if (sourceViewer == null)
233         return;
234
235       String property = event.getProperty();
236
237       //      if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
238       //        Object value= event.getNewValue();
239       //        if (value instanceof Integer) {
240       //          sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
241       //        } else if (value instanceof String) {
242       //          sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
243       //        }
244       //        return;
245       //      }
246
247       if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
248         if (isLineNumberRulerVisible())
249           showLineNumberRuler();
250         else
251           hideLineNumberRuler();
252         return;
253       }
254
255       if (fLineNumberRulerColumn != null
256         && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
257           || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
258           || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
259
260         initializeLineNumberRulerColumn(fLineNumberRulerColumn);
261       }
262
263     } finally {
264       super.handlePreferenceStoreChanged(event);
265     }
266   }
267   /**
268    * Shows the line number ruler column.
269    */
270   private void showLineNumberRuler() {
271     IVerticalRuler v = getVerticalRuler();
272     if (v instanceof CompositeRuler) {
273       CompositeRuler c = (CompositeRuler) v;
274       c.addDecorator(1, createLineNumberRulerColumn());
275     }
276   }
277
278   /**
279   * Return whether the line number ruler column should be 
280   * visible according to the preference store settings.
281   * @return <code>true</code> if the line numbers should be visible
282   */
283   private boolean isLineNumberRulerVisible() {
284     // IPreferenceStore store= getPreferenceStore();
285     return phpPrefStore.getBoolean(IPreferenceConstants.LINE_NUMBER_RULER);
286   }
287   /**
288    * Hides the line number ruler column.
289    */
290   private void hideLineNumberRuler() {
291     IVerticalRuler v = getVerticalRuler();
292     if (v instanceof CompositeRuler) {
293       CompositeRuler c = (CompositeRuler) v;
294       c.removeDecorator(1);
295     }
296   }
297
298   /**
299   * Initializes the given line number ruler column from the preference store.
300   * @param rulerColumn the ruler column to be initialized
301   */
302   protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
303     //   JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
304     PHPColorProvider manager = PHPEditorEnvironment.getPHPColorProvider();
305
306     if (phpPrefStore != null) {
307
308       RGB rgb = null;
309       // foreground color
310       if (phpPrefStore.contains(IPreferenceConstants.LINE_NUMBER_COLOR)) {
311         if (phpPrefStore.isDefault(IPreferenceConstants.LINE_NUMBER_COLOR))
312           rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR);
313         else
314           rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.LINE_NUMBER_COLOR);
315       }
316       rulerColumn.setForeground(manager.getColor(rgb));
317
318       rgb = null;
319       // background color
320       if (!phpPrefStore.getBoolean(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
321         if (phpPrefStore.contains(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) {
322           if (phpPrefStore.isDefault(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND))
323             rgb = PreferenceConverter.getDefaultColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
324           else
325             rgb = PreferenceConverter.getColor(phpPrefStore, IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
326         }
327         rulerColumn.setBackground(manager.getColor(rgb));
328       }
329
330     }
331   }
332
333   /**
334    * Creates a new line number ruler column that is appropriately initialized.
335    */
336   protected IVerticalRulerColumn createLineNumberRulerColumn() {
337     fLineNumberRulerColumn = new LineNumberRulerColumn();
338     initializeLineNumberRulerColumn(fLineNumberRulerColumn);
339     return fLineNumberRulerColumn;
340   }
341
342   /*
343    * @see AbstractTextEditor#createVerticalRuler()
344    */
345   protected IVerticalRuler createVerticalRuler() {
346     CompositeRuler ruler = new CompositeRuler();
347     ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
348     if (isLineNumberRulerVisible())
349       ruler.addDecorator(1, createLineNumberRulerColumn());
350     return ruler;
351   }
352
353   /* (non-Javadoc)
354    * Method declared on AbstractTextEditor
355    */
356   protected void initializeEditor() {
357     PHPEditorEnvironment.connect(this);
358
359     setSourceViewerConfiguration(new PHPSourceViewerConfiguration());
360     setRangeIndicator(new DefaultRangeIndicator());
361     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
362     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
363     // setDocumentProvider(PHPeclipsePlugin.getCompilationUnitDocumentProvider());
364     phpPrefStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
365
366     phpPrefStore.addPropertyChangeListener(new IPropertyChangeListener() {
367       public void propertyChange(PropertyChangeEvent event) {
368         PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner();
369         if (scanner != null) {
370           scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider());
371         }
372         if (getSourceViewer() != null) {
373           getSourceViewer().invalidateTextPresentation();
374         }
375
376         String property = event.getProperty();
377         if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
378           if (isLineNumberRulerVisible())
379             showLineNumberRuler();
380           else
381             hideLineNumberRuler();
382           return;
383         }
384       }
385     });
386   }
387 }