Improved ${cursor} handling in HTML and TPL (smarty) files
[phpeclipse.git] / net.sourceforge.phpeclipse.webbrowser / src / net / sourceforge / phpeclipse / webbrowser / internal / WebBrowserEditor.java
1 /**
2  * Copyright (c) 2003 IBM Corporation and others.
3  * All rights reserved.   This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *    IBM - Initial API and implementation
10  */
11 package net.sourceforge.phpeclipse.webbrowser.internal;
12
13 import java.net.URL;
14
15 import net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput;
16 import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
17
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IMarker;
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.IResourceChangeEvent;
22 import org.eclipse.core.resources.IResourceChangeListener;
23 import org.eclipse.core.resources.IResourceDelta;
24 import org.eclipse.core.resources.IResourceDeltaVisitor;
25 import org.eclipse.core.resources.ResourcesPlugin;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.jface.action.IAction;
28 import org.eclipse.jface.dialogs.IDialogConstants;
29 import org.eclipse.jface.dialogs.MessageDialog;
30 import org.eclipse.jface.resource.ImageDescriptor;
31 import org.eclipse.swt.graphics.Image;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.ui.IEditorInput;
35 import org.eclipse.ui.IEditorPart;
36 import org.eclipse.ui.IEditorReference;
37 import org.eclipse.ui.IEditorSite;
38 import org.eclipse.ui.IFileEditorInput;
39 import org.eclipse.ui.IWorkbenchPage;
40 import org.eclipse.ui.IWorkbenchWindow;
41 import org.eclipse.ui.part.EditorPart;
42 /**
43  * An integrated Web browser, defined as an editor to make
44  * better use of the desktop.
45  */
46 public class WebBrowserEditor extends EditorPart {
47         public static final String WEB_BROWSER_EDITOR_ID = "net.sourceforge.phpeclipse.webbrowser";
48         protected WebBrowser webBrowser;
49         protected String initialURL;
50         protected Image image;
51
52         protected TextAction cutAction;
53         protected TextAction copyAction;
54         protected TextAction pasteAction;
55         
56         protected IResourceChangeListener resourceListener;
57
58         /**
59          * WebBrowserEditor constructor comment.
60          */
61         public WebBrowserEditor() {
62                 super();
63         }
64         
65         /**
66          * Creates the SWT controls for this workbench part.
67          * <p>
68          * Clients should not call this method (the workbench calls this method at
69          * appropriate times).
70          * </p>
71          * <p>
72          * For implementors this is a multi-step process:
73          * <ol>
74          *   <li>Create one or more controls within the parent.</li>
75          *   <li>Set the parent layout as needed.</li>
76          *   <li>Register any global actions with the <code>IActionService</code>.</li>
77          *   <li>Register any popup menus with the <code>IActionService</code>.</li>
78          *   <li>Register a selection provider with the <code>ISelectionService</code>
79          *     (optional). </li>
80          * </ol>
81          * </p>
82          *
83          * @param parent the parent control
84          */
85         public void createPartControl(Composite parent) {
86                 IWebBrowserEditorInput input = getWebBrowserEditorInput();
87                 
88                 
89                 if (input == null || input.isToolbarVisible() == false)
90                         webBrowser = new WebBrowser(parent, false, input.isStatusbarVisible());
91                 else {
92                         webBrowser = new WebBrowser(parent, true, input.isStatusbarVisible());
93                         cutAction = new TextAction(webBrowser, TextAction.CUT);
94                         copyAction = new TextAction(webBrowser, TextAction.COPY);
95                         pasteAction = new TextAction(webBrowser, TextAction.PASTE);
96                 }
97                 
98                 webBrowser.setURL(initialURL);
99                 webBrowser.editor = this;
100         }
101         
102         public void dispose() {
103                 if (image != null && !image.isDisposed())
104                         image.dispose();
105                 image = null;
106
107                 if (resourceListener != null)
108                         ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceListener);
109         }
110         
111         /* (non-Javadoc)
112          * Saves the contents of this editor.
113          * <p>
114          * Subclasses must override this method to implement the open-save-close lifecycle
115          * for an editor.  For greater details, see <code>IEditorPart</code>
116          * </p>
117          *
118          * @see IEditorPart
119          */
120         public void doSave(IProgressMonitor monitor) { }
121
122         /* (non-Javadoc)
123          * Saves the contents of this editor to another object.
124          * <p>
125          * Subclasses must override this method to implement the open-save-close lifecycle
126          * for an editor.  For greater details, see <code>IEditorPart</code>
127          * </p>
128          *
129          * @see IEditorPart
130          */
131         public void doSaveAs() { }
132         
133         /**
134          * Returns the copy action.
135          *
136          * @return org.eclipse.jface.action.IAction
137          */
138         public IAction getCopyAction() {
139                 return copyAction;
140         }
141         
142         /**
143          * Returns the cut action.
144          *
145          * @return org.eclipse.jface.action.IAction
146          */
147         public IAction getCutAction() {
148                 return cutAction;
149         }
150         
151         /**
152          * Returns the paste action.
153          *
154          * @return org.eclipse.jface.action.IAction
155          */
156         public IAction getPasteAction() {
157                 return pasteAction;
158         }
159         
160         /**
161          * Returns the web editor input, if available.
162          *
163          * @return net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput
164          */
165         protected IWebBrowserEditorInput getWebBrowserEditorInput() {
166                 IEditorInput input = getEditorInput();
167                 if (input instanceof IWebBrowserEditorInput)
168                         return (IWebBrowserEditorInput) input;
169                 return null;
170         }
171         
172         /* (non-Javadoc)
173          * Sets the cursor and selection state for this editor to the passage defined
174          * by the given marker.
175          * <p>
176          * Subclasses may override.  For greater details, see <code>IEditorPart</code>
177          * </p>
178          *
179          * @see IEditorPart
180          */
181         public void gotoMarker(IMarker marker) { }
182         
183         /* (non-Javadoc)
184          * Initializes the editor part with a site and input.
185          * <p>
186          * Subclasses of <code>EditorPart</code> must implement this method.  Within
187          * the implementation subclasses should verify that the input type is acceptable
188          * and then save the site and input.  Here is sample code:
189          * </p>
190          * <pre>
191          *              if (!(input instanceof IFileEditorInput))
192          *                      throw new PartInitException("Invalid Input: Must be IFileEditorInput");
193          *              setSite(site);
194          *              setInput(editorInput);
195          * </pre>
196          */
197         public void init(IEditorSite site, IEditorInput input) {
198                 Trace.trace(Trace.FINEST, "Opening browser: " + input);
199                 if (input instanceof IFileEditorInput) {
200                         IFileEditorInput fei = (IFileEditorInput) input;
201                         IFile file = fei.getFile();
202                         URL url = null;
203                         try {
204                                 if (file != null && file.exists())
205                                         url = file.getLocation().toFile().toURL();
206                         } catch (Exception e) {
207                                 Trace.trace(Trace.SEVERE, "Error getting URL to file");
208                         }
209                         addResourceListener(file);
210                         input = new WebBrowserEditorInput(url, WebBrowserEditorInput.SHOW_ALL | WebBrowserEditorInput.SAVE_URL);
211                 }
212                 if (input instanceof IWebBrowserEditorInput) {
213                         IWebBrowserEditorInput wbei = (IWebBrowserEditorInput) input;
214                         initialURL = null;
215                         if (wbei.getURL() != null)
216                                 initialURL = wbei.getURL().toExternalForm();
217                         if (webBrowser != null) {
218                                 webBrowser.setURL(initialURL);
219                                 site.getWorkbenchWindow().getActivePage().bringToTop(this);
220                         }
221         
222                         setPartName(wbei.getName());
223                         setTitleToolTip(wbei.getToolTipText());
224
225                         Image oldImage = image;
226                         ImageDescriptor id = wbei.getImageDescriptor();
227                         image = id.createImage();
228
229                         setTitleImage(image);
230                         if (oldImage != null && !oldImage.isDisposed())
231                                 oldImage.dispose();
232                 }
233                 setSite(site);
234                 setInput(input);
235         }
236         
237         /* (non-Javadoc)
238          * Returns whether the contents of this editor have changed since the last save
239          * operation.
240          * <p>
241          * Subclasses must override this method to implement the open-save-close lifecycle
242          * for an editor.  For greater details, see <code>IEditorPart</code>
243          * </p>
244          *
245          * @see IEditorPart
246          */
247         public boolean isDirty() {
248                 return false;
249         }
250         
251         /* (non-Javadoc)
252          * Returns whether the "save as" operation is supported by this editor.
253          * <p>
254          * Subclasses must override this method to implement the open-save-close lifecycle
255          * for an editor.  For greater details, see <code>IEditorPart</code>
256          * </p>
257          *
258          * @see IEditorPart
259          */
260         public boolean isSaveAsAllowed() {
261                 return false;
262         }
263         
264         /**
265          * Returns true if this editor has a toolbar.
266          *
267          * @return boolean
268          */
269         public boolean isToolbarVisible() {
270                 IWebBrowserEditorInput input = getWebBrowserEditorInput();
271                 if (input == null || input.isToolbarVisible())
272                         return true;
273                 else
274                         return false;
275         }
276         
277         /**
278          * Open the input in the internal Web browser.
279          */
280         public static void open(IWebBrowserEditorInput input) {
281                 IWorkbenchWindow workbenchWindow = WebBrowserUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow();
282                 IWorkbenchPage page = workbenchWindow.getActivePage();
283
284                 try {
285                         IEditorReference[] editors = page.getEditorReferences();
286                         int size = editors.length;
287                         for (int i = 0; i < size; i++) {
288                                 if (WEB_BROWSER_EDITOR_ID.equals(editors[i].getId())) {
289                                         IEditorPart editor = editors[i].getEditor(true);
290                                         if (editor != null && editor instanceof WebBrowserEditor) {
291                                                 WebBrowserEditor webEditor = (WebBrowserEditor) editor;
292                                                 if (input.canReplaceInput(webEditor.getWebBrowserEditorInput())) {
293                                                         editor.init(editor.getEditorSite(), input);
294                                                         return;
295                                                 }
296                                         }
297                                 }
298                         }
299                         
300                         page.openEditor(input, WebBrowserEditor.WEB_BROWSER_EDITOR_ID);
301                 } catch (Exception e) {
302                         Trace.trace(Trace.SEVERE, "Error opening Web browser", e);
303                 }
304         }
305         
306         /**
307          * Asks this part to take focus within the workbench.
308          * <p>
309          * Clients should not call this method (the workbench calls this method at
310          * appropriate times).
311          * </p>
312          */
313         public void setFocus() {
314                 if (webBrowser != null) {
315                         if (webBrowser.combo != null)
316                                 webBrowser.combo.setFocus();
317                         else
318                                 webBrowser.browser.setFocus();
319                         webBrowser.updateHistory();
320                 }
321         }
322         
323         /**
324          * Update the actions.
325          */
326         protected void updateActions() {
327                 if (cutAction != null)
328                         cutAction.update();
329                 if (copyAction != null)
330                         copyAction.update();
331                 if (pasteAction != null)
332                         pasteAction.update();
333         }
334
335         /**
336          * Close the editor correctly.
337          */
338         protected void closeEditor() {
339                 Display.getDefault().asyncExec(new Runnable() {
340                         public void run() {
341                                 getEditorSite().getPage().closeEditor(WebBrowserEditor.this, false);
342                         }
343                 });
344         }
345         
346         /**
347          * Adds a resource change listener to see if the file is deleted.
348          */
349         protected void addResourceListener(final IResource resource) {
350                 if (resource == null)
351                         return;
352         
353                 resourceListener = new IResourceChangeListener() {
354                         public void resourceChanged(IResourceChangeEvent event) {
355                                 try {
356                                         event.getDelta().accept(new IResourceDeltaVisitor() {
357                                                 public boolean visit(IResourceDelta delta) {
358                                                         IResource res = delta.getResource();
359                                                                                                                 
360                                                         if (res == null || !res.equals(resource))
361                                                                 return true;
362
363                                                         if (delta.getKind() != IResourceDelta.REMOVED)
364                                                                 return true;
365                                                         
366                                                         Display.getDefault().asyncExec(new Runnable() {
367                                                                 public void run() {
368                                                                         String title = WebBrowserUIPlugin.getResource("%dialogResourceDeletedTitle");
369                                                                         String message = WebBrowserUIPlugin.getResource("%dialogResourceDeletedMessage", resource.getName());
370                                                                         String[] labels = new String[] {WebBrowserUIPlugin.getResource("%dialogResourceDeletedIgnore"), IDialogConstants.CLOSE_LABEL};
371                                                                         MessageDialog dialog = new MessageDialog(getEditorSite().getShell(), title, null, message, MessageDialog.INFORMATION, labels, 0);
372
373                                                                         if (dialog.open() != 0)
374                                                                                 closeEditor();
375                                                                 }
376                                                         });
377                                                         return false;
378                                                 }
379                                         });
380                                 } catch (Exception e) {
381                                         Trace.trace(Trace.SEVERE, "Error listening for resource deletion", e);
382                                 }
383                         }
384                 };
385                 ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener);
386         }
387 }