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