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