KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > editorsupport > win32 > OleEditor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.editorsupport.win32;
12
13 import java.io.File JavaDoc;
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.util.Vector JavaDoc;
16
17 import org.eclipse.core.resources.IFile;
18 import org.eclipse.core.resources.IProject;
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.resources.IResourceChangeEvent;
21 import org.eclipse.core.resources.IResourceChangeListener;
22 import org.eclipse.core.resources.IResourceDelta;
23 import org.eclipse.core.resources.ResourcesPlugin;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.Status;
29 import org.eclipse.jface.action.IMenuManager;
30 import org.eclipse.jface.dialogs.ErrorDialog;
31 import org.eclipse.jface.dialogs.MessageDialog;
32 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
33 import org.eclipse.jface.resource.ImageDescriptor;
34 import org.eclipse.jface.resource.JFaceColors;
35 import org.eclipse.jface.window.Window;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.SWTException;
38 import org.eclipse.swt.custom.BusyIndicator;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.ole.win32.OLE;
41 import org.eclipse.swt.ole.win32.OleAutomation;
42 import org.eclipse.swt.ole.win32.OleClientSite;
43 import org.eclipse.swt.ole.win32.OleFrame;
44 import org.eclipse.swt.ole.win32.Variant;
45 import org.eclipse.swt.widgets.Composite;
46 import org.eclipse.swt.widgets.Display;
47 import org.eclipse.swt.widgets.Menu;
48 import org.eclipse.swt.widgets.MenuItem;
49 import org.eclipse.swt.widgets.Shell;
50 import org.eclipse.ui.IEditorInput;
51 import org.eclipse.ui.IEditorSite;
52 import org.eclipse.ui.IFileEditorInput;
53 import org.eclipse.ui.IPartListener;
54 import org.eclipse.ui.IPathEditorInput;
55 import org.eclipse.ui.IWorkbench;
56 import org.eclipse.ui.IWorkbenchActionConstants;
57 import org.eclipse.ui.IWorkbenchPart;
58 import org.eclipse.ui.IWorkbenchWindow;
59 import org.eclipse.ui.PartInitException;
60 import org.eclipse.ui.PlatformUI;
61 import org.eclipse.ui.actions.WorkspaceModifyOperation;
62 import org.eclipse.ui.dialogs.SaveAsDialog;
63 import org.eclipse.ui.ide.ResourceUtil;
64 import org.eclipse.ui.internal.WorkbenchPlugin;
65 import org.eclipse.ui.part.EditorPart;
66 import org.eclipse.ui.part.FileEditorInput;
67
68 /**
69  */

70 public class OleEditor extends EditorPart {
71
72     /**
73      * The resource listener updates the receiver when
74      * a change has occurred.
75      */

76     private IResourceChangeListener resourceListener = new IResourceChangeListener() {
77
78         /*
79          * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
80          */

81         public void resourceChanged(IResourceChangeEvent event) {
82             IResourceDelta mainDelta = event.getDelta();
83             if (mainDelta == null)
84                 return;
85             IResourceDelta affectedElement = mainDelta.findMember(resource
86                     .getFullPath());
87             if (affectedElement != null)
88                 processDelta(affectedElement);
89         }
90
91         /*
92          * Process the delta for the receiver
93          */

94         private boolean processDelta(final IResourceDelta delta) {
95
96             Runnable JavaDoc changeRunnable = null;
97
98             switch (delta.getKind()) {
99             case IResourceDelta.REMOVED:
100                 if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) {
101                     changeRunnable = new Runnable JavaDoc() {
102                         public void run() {
103                             IPath path = delta.getMovedToPath();
104                             IFile newFile = delta.getResource().getWorkspace()
105                                     .getRoot().getFile(path);
106                             if (newFile != null) {
107                                 sourceChanged(newFile);
108                             }
109                         }
110                     };
111                 } else {
112                     changeRunnable = new Runnable JavaDoc() {
113                         public void run() {
114                             sourceDeleted = true;
115                             getSite().getPage().closeEditor(OleEditor.this,
116                                     true);
117                         }
118                     };
119
120                 }
121
122                 break;
123             }
124
125             if (changeRunnable != null)
126                 update(changeRunnable);
127
128             return true; // because we are sitting on files anyway
129
}
130
131     };
132
133     private OleFrame clientFrame;
134
135     private OleClientSite clientSite;
136
137     private File JavaDoc source;
138
139     private IFile resource;
140
141     private Image oleTitleImage;
142
143     //The sourceDeleted flag makes sure that the receiver is not
144
//dirty when shutting down
145
boolean sourceDeleted = false;
146
147     //The sourceChanged flag indicates whether or not the save from the ole component
148
//can be used or if the input changed
149
boolean sourceChanged = false;
150
151     /**
152      * Keep track of whether we have an active client so we do not
153      * deactivate multiple times
154      */

155     private boolean clientActive = false;
156
157     /**
158      * Keep track of whether we have activated OLE or not as some applications
159      * will only allow single activations.
160      */

161     private boolean oleActivated = false;
162
163     private IPartListener partListener = new IPartListener() {
164         public void partActivated(IWorkbenchPart part) {
165             activateClient(part);
166         }
167
168         public void partBroughtToTop(IWorkbenchPart part) {
169         }
170
171         public void partClosed(IWorkbenchPart part) {
172         }
173
174         public void partOpened(IWorkbenchPart part) {
175         }
176
177         public void partDeactivated(IWorkbenchPart part) {
178             deactivateClient(part);
179         }
180     };
181
182     private static final String JavaDoc RENAME_ERROR_TITLE = OleMessages
183             .getString("OleEditor.errorSaving"); //$NON-NLS-1$
184

185     private static final String JavaDoc OLE_EXCEPTION_TITLE = OleMessages
186             .getString("OleEditor.oleExceptionTitle"); //$NON-NLS-1$
187

188     private static final String JavaDoc OLE_EXCEPTION_MESSAGE = OleMessages
189             .getString("OleEditor.oleExceptionMessage"); //$NON-NLS-1$
190

191     private static final String JavaDoc OLE_CREATE_EXCEPTION_MESSAGE = OleMessages
192             .getString("OleEditor.oleCreationExceptionMessage"); //$NON-NLS-1$
193

194     private static final String JavaDoc OLE_CREATE_EXCEPTION_REASON = OleMessages
195             .getString("OleEditor.oleCreationExceptionReason"); //$NON-NLS-1$
196

197     private static final String JavaDoc SAVE_ERROR_TITLE = OleMessages
198             .getString("OleEditor.savingTitle"); //$NON-NLS-1$
199

200     private static final String JavaDoc SAVE_ERROR_MESSAGE = OleMessages
201             .getString("OleEditor.savingMessage"); //$NON-NLS-1$
202

203     /**
204      * Return a new ole editor.
205      */

206     public OleEditor() {
207         //Do nothing
208
}
209
210     private void activateClient(IWorkbenchPart part) {
211         if (part == this) {
212             oleActivate();
213             this.clientActive = true;
214         }
215     }
216
217     /**
218      * createPartControl method comment.
219      */

220     public void createPartControl(Composite parent) {
221
222         // Create a frame.
223
clientFrame = new OleFrame(parent, SWT.CLIP_CHILDREN);
224         clientFrame.setBackground(JFaceColors.getBannerBackground(clientFrame
225                 .getDisplay()));
226
227         initializeWorkbenchMenus();
228
229         createClientSite();
230     }
231
232     /**
233      * Create the client site for the receiver
234      */

235
236     private void createClientSite() {
237         //If there was an OLE Error or nothing has been created yet
238
if (clientFrame == null || clientFrame.isDisposed())
239             return;
240         // Create a OLE client site.
241
try {
242             clientSite = new OleClientSite(clientFrame, SWT.NONE, source);
243         } catch (SWTException exception) {
244
245             IStatus errorStatus = new Status(IStatus.ERROR,
246                     WorkbenchPlugin.PI_WORKBENCH, IStatus.ERROR,
247                     OLE_CREATE_EXCEPTION_REASON, exception);
248             //ErrorDialog.openError(null, OLE_EXCEPTION_TITLE, OLE_CREATE_EXCEPTION_REASON, errorStatus);
249
ErrorDialog.openError(null, OLE_EXCEPTION_TITLE, OLE_CREATE_EXCEPTION_MESSAGE, errorStatus);
250             return;
251         }
252         clientSite.setBackground(JFaceColors.getBannerBackground(clientFrame
253                 .getDisplay()));
254
255     }
256
257     private void deactivateClient(IWorkbenchPart part) {
258         //Check the client active flag. Set it to false when we have deactivated
259
//to prevent multiple de-activations.
260
if (part == this && clientActive) {
261             if (clientSite != null)
262                 clientSite.deactivateInPlaceClient();
263             this.clientActive = false;
264             this.oleActivated = false;
265         }
266     }
267
268     /**
269      * Display an error dialog with the supplied title and message.
270      * @param title
271      * @param message
272      */

273     private void displayErrorDialog(String JavaDoc title, String JavaDoc message) {
274         Shell parent = null;
275         if (getClientSite() != null)
276             parent = getClientSite().getShell();
277         MessageDialog.openError(parent, title, message);
278     }
279
280     /**
281      * @see IWorkbenchPart#dispose
282      */

283     public void dispose() {
284         if (resource != null) {
285             ResourcesPlugin.getWorkspace().removeResourceChangeListener(
286                     resourceListener);
287             resource = null;
288         }
289
290         //can dispose the title image because it was created in init
291
if (oleTitleImage != null) {
292             oleTitleImage.dispose();
293             oleTitleImage = null;
294         }
295
296         if (getSite() != null && getSite().getPage() != null)
297             getSite().getPage().removePartListener(partListener);
298
299     }
300
301     /**
302      * Print this object's contents
303      */

304     public void doPrint() {
305         if (clientSite == null)
306             return;
307         BusyIndicator.showWhile(clientSite.getDisplay(), new Runnable JavaDoc() {
308             public void run() {
309                 clientSite.exec(OLE.OLECMDID_PRINT,
310                         OLE.OLECMDEXECOPT_PROMPTUSER, null, null);
311                 // note: to check for success: above == SWTOLE.S_OK
312
}
313         });
314     }
315
316     /**
317      * Save the viewer's contents to the source file system file
318      */

319     public void doSave(final IProgressMonitor monitor) {
320         if (clientSite == null)
321             return;
322         BusyIndicator.showWhile(clientSite.getDisplay(), new Runnable JavaDoc() {
323
324             /*
325              * (non-Javadoc)
326              * @see java.lang.Runnable#run()
327              */

328             public void run() {
329
330                 //Do not try and use the component provided save if the source has
331
//changed in Eclipse
332
if (!sourceChanged) {
333                     int result = clientSite.queryStatus(OLE.OLECMDID_SAVE);
334                     if ((result & OLE.OLECMDF_ENABLED) != 0) {
335                         result = clientSite.exec(OLE.OLECMDID_SAVE,
336                                 OLE.OLECMDEXECOPT_PROMPTUSER, null, null);
337                         if (result == OLE.S_OK) {
338                             try {
339                                 resource.refreshLocal(IResource.DEPTH_ZERO,
340                                         monitor);
341                             } catch (CoreException ex) {
342                                 //Do nothing on a failed refresh
343
}
344                             return;
345                         }
346                         displayErrorDialog(OLE_EXCEPTION_TITLE,
347                                 OLE_EXCEPTION_MESSAGE + String.valueOf(result));
348                         return;
349                     }
350                 }
351                 if (saveFile(source)) {
352                     try {
353                         resource.refreshLocal(IResource.DEPTH_ZERO, monitor);
354                     } catch (CoreException ex) {
355                         //Do nothing on a failed refresh
356
}
357                 } else
358                     displayErrorDialog(SAVE_ERROR_TITLE, SAVE_ERROR_MESSAGE
359                             + source.getName());
360             }
361         });
362     }
363
364     /**
365      * Save the viewer's contents into the provided resource.
366      */

367     public void doSaveAs() {
368         if (clientSite == null)
369             return;
370         WorkspaceModifyOperation op = saveNewFileOperation();
371         Shell shell = clientSite.getShell();
372         try {
373             new ProgressMonitorDialog(shell).run(false, true, op);
374         } catch (InterruptedException JavaDoc interrupt) {
375             //Nothing to reset so do nothing
376
} catch (InvocationTargetException JavaDoc invocationException) {
377             MessageDialog.openError(shell, RENAME_ERROR_TITLE,
378                     invocationException.getTargetException().getMessage());
379         }
380
381     }
382
383     /**
384      * Answer self's client site
385      *
386      * @return org.eclipse.swt.ole.win32.OleClientSite
387      */

388     public OleClientSite getClientSite() {
389         return clientSite;
390     }
391
392     /**
393      * Answer the file system representation of self's input element
394      *
395      * @return java.io.File
396      */

397     public File JavaDoc getSourceFile() {
398         return source;
399     }
400
401     private void handleWord() {
402         OleAutomation dispInterface = new OleAutomation(clientSite);
403         // Get Application
404
int[] appId = dispInterface
405                 .getIDsOfNames(new String JavaDoc[] { "Application" }); //$NON-NLS-1$
406
if (appId != null) {
407             Variant pVarResult = dispInterface.getProperty(appId[0]);
408             if (pVarResult != null) {
409                 OleAutomation application = pVarResult.getAutomation();
410                 int[] dispid = application
411                         .getIDsOfNames(new String JavaDoc[] { "DisplayScrollBars" }); //$NON-NLS-1$
412
if (dispid != null) {
413                     Variant rgvarg = new Variant(true);
414                     application.setProperty(dispid[0], rgvarg);
415                 }
416                 application.dispose();
417             }
418         }
419         dispInterface.dispose();
420     }
421
422     /* (non-Javadoc)
423      * Initializes the editor when created from scratch.
424      *
425      * This method is called soon after part construction and marks
426      * the start of the extension lifecycle. At the end of the
427      * extension lifecycle <code>shutdown</code> will be invoked
428      * to terminate the lifecycle.
429      *
430      * @param container an interface for communication with the part container
431      * @param input The initial input element for the editor. In most cases
432      * it is an <code>IFile</code> but other types are acceptable.
433      * @see IWorkbenchPart#shutdown
434      */

435     public void init(IEditorSite site, IEditorInput input)
436             throws PartInitException {
437         
438         validatePathEditorInput(input);
439
440         // Save input.
441
setSite(site);
442         setInputWithNotify(input);
443
444         // Update titles.
445
setPartName(input.getName());
446         setTitleToolTip(input.getToolTipText());
447         ImageDescriptor desc = input.getImageDescriptor();
448         if (desc != null) {
449             oleTitleImage = desc.createImage();
450             setTitleImage(oleTitleImage);
451         }
452
453         // Listen for part activation.
454
site.getPage().addPartListener(partListener);
455
456     }
457     
458     /**
459      * Validates the given input
460      *
461      * @param input the editor input to validate
462      * @throws PartInitException if the editor input is not OK
463      */

464     private boolean validatePathEditorInput(IEditorInput input) throws PartInitException {
465         // Check input type.
466
if (!(input instanceof IPathEditorInput))
467             throw new PartInitException(OleMessages.format(
468                     "OleEditor.invalidInput", new Object JavaDoc[] { input })); //$NON-NLS-1$
469

470         IPath path= ((IPathEditorInput)input).getPath();
471
472         //Cannot create this with a file and no physical location
473
if (path == null
474                 || !(new File JavaDoc(path.toOSString()).exists()))
475             throw new PartInitException(
476                     OleMessages
477                             .format(
478                                     "OleEditor.noFileInput", new Object JavaDoc[] { path.toOSString() })); //$NON-NLS-1$
479
return true;
480     }
481     
482     /**
483      * Initialize the workbench menus for proper merging
484      */

485     protected void initializeWorkbenchMenus() {
486         //If there was an OLE Error or nothing has been created yet
487
if (clientFrame == null || clientFrame.isDisposed())
488             return;
489         // Get the browser menu bar. If one does not exist then
490
// create it.
491
Shell shell = clientFrame.getShell();
492         Menu menuBar = shell.getMenuBar();
493         if (menuBar == null) {
494             menuBar = new Menu(shell, SWT.BAR);
495             shell.setMenuBar(menuBar);
496         }
497
498         // Swap the file and window menus.
499
MenuItem[] windowMenu = new MenuItem[1];
500         MenuItem[] fileMenu = new MenuItem[1];
501         Vector JavaDoc containerItems = new Vector JavaDoc();
502
503         IWorkbenchWindow window = getSite().getWorkbenchWindow();
504
505         for (int i = 0; i < menuBar.getItemCount(); i++) {
506             MenuItem item = menuBar.getItem(i);
507             String JavaDoc id = ""; //$NON-NLS-1$
508
if (item.getData() instanceof IMenuManager)
509                 id = ((IMenuManager) item.getData()).getId();
510             if (id.equals(IWorkbenchActionConstants.M_FILE))
511                 fileMenu[0] = item;
512             else if (id.equals(IWorkbenchActionConstants.M_WINDOW))
513                 windowMenu[0] = item;
514             else {
515                 if (window.isApplicationMenu(id)) {
516                     containerItems.addElement(item);
517                 }
518             }
519         }
520         MenuItem[] containerMenu = new MenuItem[containerItems.size()];
521         containerItems.copyInto(containerMenu);
522         clientFrame.setFileMenus(fileMenu);
523         clientFrame.setContainerMenus(containerMenu);
524         clientFrame.setWindowMenus(windowMenu);
525     }
526
527     /*
528      * (non-Javadoc)
529      * @see org.eclipse.ui.ISaveablePart#isDirty()
530      */

531     public boolean isDirty() {
532         /*Return only if we have a clientSite which is dirty
533          as this can be asked before anything is opened*/

534         return this.clientSite != null;
535     }
536
537     /*
538      * (non-Javadoc)
539      * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
540      */

541     public boolean isSaveAsAllowed() {
542         return true;
543     }
544
545     /**
546      *Since we don't know when a change has been made, always answer true
547      * @return <code>false</code> if it was not opened and <code>true</code>
548      * only if it is dirty
549      */

550     public boolean isSaveNeeded() {
551         return getClientSite() != null && isDirty();
552     }
553
554     /**
555      * Save the supplied file using the SWT API.
556      * @param file java.io.File
557      * @return <code>true</code> if the save was successful
558      */

559     private boolean saveFile(File JavaDoc file) {
560
561         File JavaDoc tempFile = new File JavaDoc(file.getAbsolutePath() + ".tmp"); //$NON-NLS-1$
562
file.renameTo(tempFile);
563         boolean saved = false;
564         if (OLE.isOleFile(file) || usesStorageFiles(clientSite.getProgramID())) {
565             saved = clientSite.save(file, true);
566         } else {
567             saved = clientSite.save(file, false);
568         }
569
570         if (saved) {
571             // save was successful so discard the backup
572
tempFile.delete();
573             return true;
574         }
575         // save failed so restore the backup
576
tempFile.renameTo(file);
577         return false;
578     }
579
580     /**
581      * Save the new File using the client site.
582      * @return WorkspaceModifyOperation
583      */

584     private WorkspaceModifyOperation saveNewFileOperation() {
585
586         return new WorkspaceModifyOperation() {
587             public void execute(final IProgressMonitor monitor)
588                     throws CoreException {
589                 SaveAsDialog dialog = new SaveAsDialog(clientFrame.getShell());
590                 IFile sFile = ResourceUtil.getFile(getEditorInput());
591                 if (sFile != null) {
592                     dialog.setOriginalFile(sFile);
593                     dialog.open();
594     
595                     IPath newPath = dialog.getResult();
596                     if (newPath == null)
597                         return;
598     
599                     if (dialog.getReturnCode() == Window.OK) {
600                         String JavaDoc projectName = newPath.segment(0);
601                         newPath = newPath.removeFirstSegments(1);
602                         IProject project = resource.getWorkspace().getRoot()
603                                 .getProject(projectName);
604                         newPath = project.getLocation().append(newPath);
605                         File JavaDoc newFile = newPath.toFile();
606                         if (saveFile(newFile)) {
607                             IFile newResource = resource.getWorkspace().getRoot()
608                                     .getFileForLocation(newPath);
609                             if (newResource != null) {
610                                 sourceChanged(newResource);
611                                 newResource.refreshLocal(IResource.DEPTH_ZERO,
612                                         monitor);
613                             }
614                         } else {
615                             displayErrorDialog(SAVE_ERROR_TITLE, SAVE_ERROR_MESSAGE
616                                     + newFile.getName());
617                             return;
618                         }
619                     }
620                 }
621             }
622         };
623
624     }
625
626     /*
627      * (non-Javadoc)
628      * @see org.eclipse.ui.IWorkbenchPart#setFocus()
629      */

630     public void setFocus() {
631         //Do not take focus
632
}
633
634     /**
635      * Make ole active so that the controls are rendered.
636      */

637     private void oleActivate() {
638         //If there was an OLE Error or nothing has been created yet
639
if (clientSite == null || clientFrame == null
640                 || clientFrame.isDisposed())
641             return;
642
643         if (!oleActivated) {
644             clientSite.doVerb(OLE.OLEIVERB_SHOW);
645             oleActivated = true;
646             String JavaDoc progId = clientSite.getProgramID();
647             if (progId != null && progId.startsWith("Word.Document")) { //$NON-NLS-1$
648
handleWord();
649             }
650         }
651     }
652
653     /* (non-Javadoc)
654      * @see org.eclipse.ui.part.EditorPart#setInputWithNotify(org.eclipse.ui.IEditorInput)
655      */

656     protected void setInputWithNotify(IEditorInput input) {
657         if (input instanceof IPathEditorInput)
658             source = new File JavaDoc(((IPathEditorInput)input).getPath().toOSString());
659         
660         if (input instanceof IFileEditorInput) {
661             if (resource == null)
662                 ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceListener);
663             resource = ((IFileEditorInput)input).getFile();
664         } else if (resource != null) {
665             ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceListener);
666             resource = null;
667         }
668         
669         super.setInputWithNotify(input);
670     }
671
672     /**
673      * See if it is one of the known types that use OLE Storage.
674      * @param progID the type to test
675      * @return <code>true</code> if it is one of the known types
676      */

677     private static boolean usesStorageFiles(String JavaDoc progID) {
678         return (progID != null && (progID.startsWith("Word.", 0) //$NON-NLS-1$
679
|| progID.startsWith("MSGraph", 0) //$NON-NLS-1$
680
|| progID.startsWith("PowerPoint", 0) //$NON-NLS-1$
681
|| progID.startsWith("Excel", 0))); //$NON-NLS-1$
682
}
683
684     /**
685      * The source has changed to the newFile. Update
686      * editors and set any required flags
687      * @param newFile The file to get the new contents from.
688      */

689     private void sourceChanged(IFile newFile) {
690
691         FileEditorInput newInput = new FileEditorInput(newFile);
692         setInputWithNotify(newInput);
693         sourceChanged = true;
694         setPartName(newInput.getName());
695
696     }
697
698     /*
699      * See IEditorPart.isSaveOnCloseNeeded()
700      */

701     public boolean isSaveOnCloseNeeded() {
702         return !sourceDeleted && super.isSaveOnCloseNeeded();
703     }
704
705     /**
706      * Posts the update code "behind" the running operation.
707      *
708      * @param runnable the update code
709      */

710     private void update(Runnable JavaDoc runnable) {
711         IWorkbench workbench = PlatformUI.getWorkbench();
712         IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
713         if (windows != null && windows.length > 0) {
714             Display display = windows[0].getShell().getDisplay();
715             display.asyncExec(runnable);
716         } else
717             runnable.run();
718     }
719
720 }
721
Popular Tags