Source Code Cross Referenced for SaveableHelper.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » internal » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui workbench » org.eclipse.ui.internal 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2004, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.ui.internal;
011:
012:        import java.lang.reflect.InvocationTargetException;
013:        import java.util.ArrayList;
014:        import java.util.Collection;
015:        import java.util.HashSet;
016:        import java.util.Iterator;
017:        import java.util.List;
018:        import java.util.Set;
019:
020:        import org.eclipse.core.runtime.CoreException;
021:        import org.eclipse.core.runtime.IProgressMonitor;
022:        import org.eclipse.core.runtime.IStatus;
023:        import org.eclipse.core.runtime.OperationCanceledException;
024:        import org.eclipse.core.runtime.Status;
025:        import org.eclipse.core.runtime.SubMonitor;
026:        import org.eclipse.core.runtime.SubProgressMonitor;
027:        import org.eclipse.core.runtime.jobs.IJobChangeEvent;
028:        import org.eclipse.core.runtime.jobs.Job;
029:        import org.eclipse.core.runtime.jobs.JobChangeAdapter;
030:        import org.eclipse.jface.dialogs.IDialogConstants;
031:        import org.eclipse.jface.dialogs.MessageDialog;
032:        import org.eclipse.jface.operation.IRunnableContext;
033:        import org.eclipse.jface.operation.IRunnableWithProgress;
034:        import org.eclipse.jface.window.IShellProvider;
035:        import org.eclipse.osgi.util.NLS;
036:        import org.eclipse.ui.ISaveablePart;
037:        import org.eclipse.ui.ISaveablePart2;
038:        import org.eclipse.ui.ISaveablesLifecycleListener;
039:        import org.eclipse.ui.ISaveablesSource;
040:        import org.eclipse.ui.IWorkbenchPart;
041:        import org.eclipse.ui.IWorkbenchWindow;
042:        import org.eclipse.ui.PlatformUI;
043:        import org.eclipse.ui.Saveable;
044:        import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
045:        import org.eclipse.ui.internal.misc.StatusUtil;
046:        import org.eclipse.ui.progress.IJobRunnable;
047:        import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
048:        import org.eclipse.ui.statushandlers.StatusManager;
049:
050:        /**
051:         * Helper class for prompting to save dirty views or editors.
052:         * 
053:         * @since 3.0.1
054:         */
055:        public class SaveableHelper {
056:
057:            /**
058:             * The helper must prompt.
059:             */
060:            public static final int USER_RESPONSE = -1;
061:
062:            private static int AutomatedResponse = USER_RESPONSE;
063:
064:            /**
065:             * FOR USE BY THE AUTOMATED TEST HARNESS ONLY.
066:             * 
067:             * Sets the response to use when <code>savePart</code> is called with <code>confirm=true</code>. 
068:             * 
069:             * @param response 0 for yes, 1 for no, 2 for cancel, -1 for default (prompt)
070:             */
071:            public static void testSetAutomatedResponse(int response) {
072:                AutomatedResponse = response;
073:            }
074:
075:            /**
076:             * FOR USE BY THE AUTOMATED TEST HARNESS ONLY.
077:             * 
078:             * Sets the response to use when <code>savePart</code> is called with <code>confirm=true</code>. 
079:             * 
080:             * @return 0 for yes, 1 for no, 2 for cancel, -1 for default (prompt)
081:             */
082:            public static int testGetAutomatedResponse() {
083:                return AutomatedResponse;
084:            }
085:
086:            /**
087:             * Saves the workbench part.
088:             * 
089:             * @param saveable the part
090:             * @param part the same part
091:             * @param window the workbench window
092:             * @param confirm request confirmation
093:             * @return <code>true</code> for continue, <code>false</code> if the operation
094:             * was canceled.
095:             */
096:            static boolean savePart(final ISaveablePart saveable,
097:                    IWorkbenchPart part, IWorkbenchWindow window,
098:                    boolean confirm) {
099:                // Short circuit.
100:                if (!saveable.isDirty()) {
101:                    return true;
102:                }
103:
104:                // If confirmation is required ..
105:                if (confirm) {
106:                    int choice = AutomatedResponse;
107:                    if (choice == USER_RESPONSE) {
108:                        if (saveable instanceof  ISaveablePart2) {
109:                            choice = ((ISaveablePart2) saveable)
110:                                    .promptToSaveOnClose();
111:                        }
112:                        if (choice == USER_RESPONSE
113:                                || choice == ISaveablePart2.DEFAULT) {
114:                            String message = NLS
115:                                    .bind(
116:                                            WorkbenchMessages.EditorManager_saveChangesQuestion,
117:                                            part.getTitle());
118:                            // Show a dialog.
119:                            String[] buttons = new String[] {
120:                                    IDialogConstants.YES_LABEL,
121:                                    IDialogConstants.NO_LABEL,
122:                                    IDialogConstants.CANCEL_LABEL };
123:                            MessageDialog d = new MessageDialog(window
124:                                    .getShell(),
125:                                    WorkbenchMessages.Save_Resource, null,
126:                                    message, MessageDialog.QUESTION, buttons, 0);
127:                            choice = d.open();
128:                        }
129:                    }
130:
131:                    // Branch on the user choice.
132:                    // The choice id is based on the order of button labels above.
133:                    switch (choice) {
134:                    case ISaveablePart2.YES: //yes
135:                        break;
136:                    case ISaveablePart2.NO: //no
137:                        return true;
138:                    default:
139:                    case ISaveablePart2.CANCEL: //cancel
140:                        return false;
141:                    }
142:                }
143:
144:                if (saveable instanceof  ISaveablesSource) {
145:                    return saveModels((ISaveablesSource) saveable, window,
146:                            confirm);
147:                }
148:
149:                // Create save block.
150:                IRunnableWithProgress progressOp = new IRunnableWithProgress() {
151:                    public void run(IProgressMonitor monitor) {
152:                        IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
153:                                monitor);
154:                        saveable.doSave(monitorWrap);
155:                    }
156:                };
157:
158:                // Do the save.
159:                return runProgressMonitorOperation(WorkbenchMessages.Save,
160:                        progressOp, window);
161:            }
162:
163:            /**
164:             * Saves the selected dirty models from the given model source.
165:             * 
166:             * @param modelSource the model source
167:             * @param window the workbench window
168:             * @param confirm 
169:             * @return <code>true</code> for continue, <code>false</code> if the operation
170:             *   was canceled or an error occurred while saving.
171:             */
172:            private static boolean saveModels(ISaveablesSource modelSource,
173:                    final IWorkbenchWindow window, final boolean confirm) {
174:                Saveable[] selectedModels = modelSource.getActiveSaveables();
175:                final ArrayList dirtyModels = new ArrayList();
176:                for (int i = 0; i < selectedModels.length; i++) {
177:                    Saveable model = selectedModels[i];
178:                    if (model.isDirty()) {
179:                        dirtyModels.add(model);
180:                    }
181:                }
182:                if (dirtyModels.isEmpty()) {
183:                    return true;
184:                }
185:
186:                // Create save block.
187:                IRunnableWithProgress progressOp = new IRunnableWithProgress() {
188:                    public void run(IProgressMonitor monitor) {
189:                        IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
190:                                monitor);
191:                        monitorWrap.beginTask(WorkbenchMessages.Save,
192:                                dirtyModels.size());
193:                        for (Iterator i = dirtyModels.iterator(); i.hasNext();) {
194:                            Saveable model = (Saveable) i.next();
195:                            // handle case where this model got saved as a result of saving another
196:                            if (!model.isDirty()) {
197:                                monitor.worked(1);
198:                                continue;
199:                            }
200:                            doSaveModel(model, new SubProgressMonitor(
201:                                    monitorWrap, 1), window, confirm);
202:                            if (monitor.isCanceled()) {
203:                                break;
204:                            }
205:                        }
206:                        monitorWrap.done();
207:                    }
208:                };
209:
210:                // Do the save.
211:                return runProgressMonitorOperation(WorkbenchMessages.Save,
212:                        progressOp, window);
213:            }
214:
215:            /**
216:             * Saves the workbench part ... this is similar to 
217:             * {@link SaveableHelper#savePart(ISaveablePart, IWorkbenchPart, IWorkbenchWindow, boolean) }
218:             * except that the {@link ISaveablePart2#DEFAULT } case must cause the
219:             * calling function to allow this part to participate in the default saving
220:             * mechanism.
221:             * 
222:             * @param saveable the part
223:             * @param window the workbench window
224:             * @param confirm request confirmation
225:             * @return the ISaveablePart2 constant
226:             */
227:            static int savePart(final ISaveablePart2 saveable,
228:                    IWorkbenchWindow window, boolean confirm) {
229:                // Short circuit.
230:                if (!saveable.isDirty()) {
231:                    return ISaveablePart2.YES;
232:                }
233:
234:                // If confirmation is required ..
235:                if (confirm) {
236:                    int choice = AutomatedResponse;
237:                    if (choice == USER_RESPONSE) {
238:                        choice = saveable.promptToSaveOnClose();
239:                    }
240:
241:                    // Branch on the user choice.
242:                    // The choice id is based on the order of button labels above.
243:                    if (choice != ISaveablePart2.YES) {
244:                        return (choice == USER_RESPONSE ? ISaveablePart2.DEFAULT
245:                                : choice);
246:                    }
247:                }
248:
249:                // Create save block.
250:                IRunnableWithProgress progressOp = new IRunnableWithProgress() {
251:                    public void run(IProgressMonitor monitor) {
252:                        IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
253:                                monitor);
254:                        saveable.doSave(monitorWrap);
255:                    }
256:                };
257:
258:                // Do the save.
259:                if (!runProgressMonitorOperation(WorkbenchMessages.Save,
260:                        progressOp, window)) {
261:                    return ISaveablePart2.CANCEL;
262:                }
263:                return ISaveablePart2.YES;
264:            }
265:
266:            /**
267:             * Runs a progress monitor operation. Returns true if success, false if
268:             * canceled.
269:             */
270:            static boolean runProgressMonitorOperation(String opName,
271:                    IRunnableWithProgress progressOp, IWorkbenchWindow window) {
272:                return runProgressMonitorOperation(opName, progressOp, window,
273:                        window);
274:            }
275:
276:            /**
277:             * Runs a progress monitor operation.
278:             * Returns true if success, false if canceled or an error occurred.
279:             */
280:            static boolean runProgressMonitorOperation(String opName,
281:                    final IRunnableWithProgress progressOp,
282:                    final IRunnableContext runnableContext,
283:                    final IShellProvider shellProvider) {
284:                final boolean[] success = new boolean[] { false };
285:                IRunnableWithProgress runnable = new IRunnableWithProgress() {
286:                    public void run(IProgressMonitor monitor)
287:                            throws InvocationTargetException,
288:                            InterruptedException {
289:                        progressOp.run(monitor);
290:                        // Only indicate success if the monitor wasn't canceled
291:                        if (!monitor.isCanceled())
292:                            success[0] = true;
293:                    }
294:                };
295:
296:                try {
297:                    runnableContext.run(false, true, runnable);
298:                } catch (InvocationTargetException e) {
299:                    String title = NLS.bind(
300:                            WorkbenchMessages.EditorManager_operationFailed,
301:                            opName);
302:                    Throwable targetExc = e.getTargetException();
303:                    WorkbenchPlugin.log(title, new Status(IStatus.WARNING,
304:                            PlatformUI.PLUGIN_ID, 0, title, targetExc));
305:                    StatusUtil.handleStatus(title, targetExc,
306:                            StatusManager.SHOW, shellProvider.getShell());
307:                    // Fall through to return failure
308:                } catch (InterruptedException e) {
309:                    // The user pressed cancel. Fall through to return failure
310:                } catch (OperationCanceledException e) {
311:                    // The user pressed cancel. Fall through to return failure
312:                }
313:                return success[0];
314:            }
315:
316:            /**
317:             * Returns whether the model source needs saving. This is true if any of
318:             * the active models are dirty. This logic must correspond with 
319:             * {@link #saveModels} above.
320:             * 
321:             * @param modelSource
322:             *            the model source
323:             * @return <code>true</code> if save is required, <code>false</code>
324:             *         otherwise
325:             * @since 3.2
326:             */
327:            public static boolean needsSave(ISaveablesSource modelSource) {
328:                Saveable[] selectedModels = modelSource.getActiveSaveables();
329:                for (int i = 0; i < selectedModels.length; i++) {
330:                    Saveable model = selectedModels[i];
331:                    if (model.isDirty()
332:                            && !((InternalSaveable) model)
333:                                    .isSavingInBackground()) {
334:                        return true;
335:                    }
336:                }
337:                return false;
338:            }
339:
340:            /**
341:             * @param model
342:             * @param progressMonitor
343:             * @param shellProvider
344:             * @param blockUntilSaved
345:             */
346:            public static void doSaveModel(final Saveable model,
347:                    IProgressMonitor progressMonitor,
348:                    final IShellProvider shellProvider, boolean blockUntilSaved) {
349:                try {
350:                    Job backgroundSaveJob = ((InternalSaveable) model)
351:                            .getBackgroundSaveJob();
352:                    if (backgroundSaveJob != null) {
353:                        boolean canceled = waitForBackgroundSaveJob(model);
354:                        if (canceled) {
355:                            progressMonitor.setCanceled(true);
356:                            return;
357:                        }
358:                        // return early if the saveable is no longer dirty
359:                        if (!model.isDirty()) {
360:                            return;
361:                        }
362:                    }
363:                    final IJobRunnable[] backgroundSaveRunnable = new IJobRunnable[1];
364:                    try {
365:                        SubMonitor subMonitor = SubMonitor.convert(
366:                                progressMonitor, 3);
367:                        backgroundSaveRunnable[0] = model.doSave(subMonitor
368:                                .newChild(2), shellProvider);
369:                        if (backgroundSaveRunnable[0] == null) {
370:                            // no further work needs to be done
371:                            return;
372:                        }
373:                        if (blockUntilSaved) {
374:                            // for now, block on close by running the runnable in the UI
375:                            // thread
376:                            IStatus result = backgroundSaveRunnable[0]
377:                                    .run(subMonitor.newChild(1));
378:                            if (!result.isOK()) {
379:                                StatusUtil.handleStatus(result,
380:                                        StatusManager.SHOW, shellProvider
381:                                                .getShell());
382:                                progressMonitor.setCanceled(true);
383:                            }
384:                            return;
385:                        }
386:                        // for the job family, we use the model object because based on
387:                        // the family we can display the busy state with an animated tab
388:                        // (see the calls to showBusyForFamily() below).
389:                        Job saveJob = new Job(
390:                                NLS
391:                                        .bind(
392:                                                WorkbenchMessages.EditorManager_backgroundSaveJobName,
393:                                                model.getName())) {
394:                            public boolean belongsTo(Object family) {
395:                                if (family instanceof  DynamicFamily) {
396:                                    return ((DynamicFamily) family)
397:                                            .contains(model);
398:                                }
399:                                return family.equals(model);
400:                            }
401:
402:                            protected IStatus run(IProgressMonitor monitor) {
403:                                return backgroundSaveRunnable[0].run(monitor);
404:                            }
405:                        };
406:                        // we will need the associated parts (for disabling their UI)
407:                        ((InternalSaveable) model)
408:                                .setBackgroundSaveJob(saveJob);
409:                        SaveablesList saveablesList = (SaveablesList) PlatformUI
410:                                .getWorkbench().getService(
411:                                        ISaveablesLifecycleListener.class);
412:                        final IWorkbenchPart[] parts = saveablesList
413:                                .getPartsForSaveable(model);
414:
415:                        // this will cause the parts tabs to show the ongoing background operation
416:                        for (int i = 0; i < parts.length; i++) {
417:                            IWorkbenchPart workbenchPart = parts[i];
418:                            IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService) workbenchPart
419:                                    .getSite()
420:                                    .getAdapter(
421:                                            IWorkbenchSiteProgressService.class);
422:                            progressService.showBusyForFamily(model);
423:                        }
424:                        model.disableUI(parts, blockUntilSaved);
425:                        // Add a listener for enabling the UI after the save job has
426:                        // finished, and for displaying an error dialog if
427:                        // necessary.
428:                        saveJob.addJobChangeListener(new JobChangeAdapter() {
429:                            public void done(final IJobChangeEvent event) {
430:                                ((InternalSaveable) model)
431:                                        .setBackgroundSaveJob(null);
432:                                shellProvider.getShell().getDisplay()
433:                                        .asyncExec(new Runnable() {
434:                                            public void run() {
435:                                                notifySaveAction(parts);
436:                                                model.enableUI(parts);
437:                                            }
438:                                        });
439:                            }
440:                        });
441:                        // Finally, we are ready to schedule the job.
442:                        saveJob.schedule();
443:                        // the job was started - notify the save actions,
444:                        // this is done through the workbench windows, which
445:                        // we can get from the parts...
446:                        notifySaveAction(parts);
447:                    } catch (CoreException e) {
448:                        StatusUtil.handleStatus(e.getStatus(),
449:                                StatusManager.SHOW, shellProvider.getShell());
450:                        progressMonitor.setCanceled(true);
451:                    }
452:                } finally {
453:                    progressMonitor.done();
454:                }
455:            }
456:
457:            private static void notifySaveAction(final IWorkbenchPart[] parts) {
458:                Set wwindows = new HashSet();
459:                for (int i = 0; i < parts.length; i++) {
460:                    wwindows.add(parts[i].getSite().getWorkbenchWindow());
461:                }
462:                for (Iterator it = wwindows.iterator(); it.hasNext();) {
463:                    WorkbenchWindow wwin = (WorkbenchWindow) it.next();
464:                    wwin.fireBackgroundSaveStarted();
465:                }
466:            }
467:
468:            /**
469:             * Waits for the background save job (if any) of the given saveable to complete.
470:             * This may open a progress dialog with the option to cancel.
471:             * 
472:             * @param modelToSave
473:             * @return true if the user canceled.
474:             */
475:            private static boolean waitForBackgroundSaveJob(final Saveable model) {
476:                List models = new ArrayList();
477:                models.add(model);
478:                return waitForBackgroundSaveJobs(models);
479:            }
480:
481:            /**
482:             * Waits for the background save jobs (if any) of the given saveables to complete.
483:             * This may open a progress dialog with the option to cancel.
484:             * 
485:             * @param modelsToSave
486:             * @return true if the user canceled.
487:             */
488:            public static boolean waitForBackgroundSaveJobs(
489:                    final List modelsToSave) {
490:                // block if any of the saveables is still saving in the background
491:                try {
492:                    PlatformUI.getWorkbench().getProgressService()
493:                            .busyCursorWhile(new IRunnableWithProgress() {
494:                                public void run(IProgressMonitor monitor)
495:                                        throws InterruptedException {
496:                                    Job.getJobManager().join(
497:                                            new DynamicFamily(modelsToSave),
498:                                            monitor);
499:                                }
500:                            });
501:                } catch (InvocationTargetException e) {
502:                    StatusUtil.handleStatus(e, StatusManager.SHOW
503:                            | StatusManager.LOG);
504:                } catch (InterruptedException e) {
505:                    return true;
506:                }
507:                // remove saveables that are no longer dirty from the list
508:                for (Iterator it = modelsToSave.iterator(); it.hasNext();) {
509:                    Saveable model = (Saveable) it.next();
510:                    if (!model.isDirty()) {
511:                        it.remove();
512:                    }
513:                }
514:                return false;
515:            }
516:
517:            private static class DynamicFamily extends HashSet {
518:                private static final long serialVersionUID = 1L;
519:
520:                public DynamicFamily(Collection collection) {
521:                    super(collection);
522:                }
523:            }
524:
525:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.