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