aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWojciech Sudol2014-03-03 06:17:37 (EST)
committerPaul Webster2014-03-03 10:44:05 (EST)
commit7f165e814eb09f295f449362beb5f4e80ad47f52 (patch)
tree6ba35e2223abf05ac39708f5bb4db88558e66fb6
parentc88f1112a3569cf9232a90fac548c58af269a5a2 (diff)
downloadeclipse.platform.ui-7f165e814eb09f295f449362beb5f4e80ad47f52.zip
eclipse.platform.ui-7f165e814eb09f295f449362beb5f4e80ad47f52.tar.gz
eclipse.platform.ui-7f165e814eb09f295f449362beb5f4e80ad47f52.tar.bz2
Bug 401655 - [Progress] Create e4 based Progress Viewrefs/changes/40/21240/14
Refactor the workbench Progress view to run on Eclipse4. Includes: - Progress support - Eclipse4 ProgressView - progress toolbar - replaces 3.x services with their 4.x equivalents - progress view preferences dialog - example model fragments - explicit singletons replaced with dependency injection - general refactoring - remove dos line endings Change-Id: If30658d0150b9933165546629cfe17f94ee41caa Signed-off-by: Wojciech Sudol <wojciech.sudol@pl.ibm.com>
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.classpath7
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.gitignore1
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.project33
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.ui.prefs54
-rw-r--r--bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.pde.core.prefs3
-rw-r--r--bundles/org.eclipse.e4.ui.progress/META-INF/MANIFEST.MF28
-rw-r--r--bundles/org.eclipse.e4.ui.progress/OSGI-INF/progress.xml8
-rw-r--r--bundles/org.eclipse.e4.ui.progress/build.properties13
-rw-r--r--bundles/org.eclipse.e4.ui.progress/examples/programmatic_progress_view.e4xmi18
-rw-r--r--bundles/org.eclipse.e4.ui.progress/examples/progress_view.e4xmi39
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_rem.pngbin0 -> 461 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_remall.pngbin0 -> 594 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_stop.pngbin0 -> 250 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_rem.pngbin0 -> 461 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.pngbin0 -> 641 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_stop.pngbin0 -> 287 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/errorstate.pngbin0 -> 629 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/lockedstate.pngbin0 -> 636 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_error.pngbin0 -> 679 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_none.pngbin0 -> 479 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_ok.pngbin0 -> 403 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_task.pngbin0 -> 237 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/pview.pngbin0 -> 469 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/sleeping.pngbin0 -> 294 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/icons/full/progress/waiting.pngbin0 -> 722 bytes
-rw-r--r--bundles/org.eclipse.e4.ui.progress/plugin.xml5
-rw-r--r--bundles/org.eclipse.e4.ui.progress/pom.xml21
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ClearAllHandler.java31
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IDisposableAction.java26
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IElementCollector.java52
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IJobRunnable.java42
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressConstants.java165
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressService.java162
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenPreferenceDialogHandler.java36
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenProgressViewHandler.java29
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgrammaticProgressView.java157
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressView.java77
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressViewAddon.java33
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/UIJob.java188
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AbstractProgressViewer.java33
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationItem.java179
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationManager.java264
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/BlockedJobsDialog.java474
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ContentProviderFactory.java43
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/DetailedProgressViewer.java540
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ErrorInfo.java147
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/FinishedJobs.java425
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/GroupInfo.java292
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IAnimationProcessor.java65
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobBusyListener.java34
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobProgressManagerListener.java65
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IProgressUpdateCollector.java43
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ImageTools.java58
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfo.java478
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfoFactory.java31
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobTreeElement.java121
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobsViewPreferenceDialog.java95
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/PreferenceStore.java171
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Preferences.java45
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationItem.java406
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationProcessor.java161
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressCanvasViewer.java279
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressContentProvider.java98
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressInfoItem.java1035
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressLabelProvider.java38
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManager.java1028
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManagerUtil.java489
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMessages.java88
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorFocusJobDialog.java541
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorJobsDialog.java511
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressRegion.java348
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceCreationFunction.java24
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceImpl.java353
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewUpdater.java469
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerContentProvider.java250
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerLabelProvider.java43
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Services.java156
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/StatusAdapterHelper.java76
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/SubTaskInfo.java108
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/TaskInfo.java158
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ViewSettingsDialog.java86
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/WorkbenchDialogBlockedHandler.java109
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/EventLoopProgressMonitor.java194
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/PlatformUI.java25
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/Policy.java28
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusAdapter.java137
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusUtil.java195
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/TrimUtil.java54
-rw-r--r--bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/messages.properties76
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/.classpath7
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/.cvsignore1
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/.project28
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.core.runtime.prefs2
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/META-INF/MANIFEST.MF23
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/about.html28
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/build.properties6
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/icons/job_view.gifbin0 -> 159 bytes
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/icons/sample.gifbin0 -> 983 bytes
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/icons/suspend.gifbin0 -> 373 bytes
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/icons/tree_view.gifbin0 -> 314 bytes
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/job_factory_view.e4xmi9
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/plugin.xml16
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/pom.xml21
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/programmatic_progress_view.e4xmi18
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/progress_view.e4xmi39
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJob.java141
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJobRule.java43
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/UITestJob.java60
-rw-r--r--examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/views/JobsView.java597
111 files changed, 13447 insertions, 0 deletions
diff --git a/bundles/org.eclipse.e4.ui.progress/.classpath b/bundles/org.eclipse.e4.ui.progress/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.progress/.gitignore b/bundles/org.eclipse.e4.ui.progress/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/bundles/org.eclipse.e4.ui.progress/.project b/bundles/org.eclipse.e4.ui.progress/.project
new file mode 100644
index 0000000..cba6b1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.e4.ui.progress</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ds.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c537b63
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..9c8a13a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,54 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..706f07e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+pluginProject.extensions=true
+resolve.requirebundle=false
diff --git a/bundles/org.eclipse.e4.ui.progress/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.progress/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5923b56
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/META-INF/MANIFEST.MF
@@ -0,0 +1,28 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Progress
+Bundle-SymbolicName: org.eclipse.e4.ui.progress;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Require-Bundle: org.eclipse.core.jobs;bundle-version="3.5.400",
+ org.eclipse.equinox.common;bundle-version="3.6.200",
+ org.eclipse.osgi;bundle-version="3.10.0",
+ javax.inject;bundle-version="1.0.0",
+ org.eclipse.e4.core.di;bundle-version="1.3.0",
+ org.eclipse.e4.ui.di;bundle-version="1.0.0",
+ org.eclipse.jface;bundle-version="3.10.0",
+ com.ibm.icu;bundle-version="50.1.1",
+ org.eclipse.e4.ui.workbench,
+ org.eclipse.e4.core.commands,
+ org.eclipse.e4.core.services,
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.ui.model.workbench,
+ org.eclipse.e4.ui.workbench.swt,
+ org.eclipse.core.runtime;bundle-version="3.10.0",
+ org.eclipse.swt,
+ org.eclipse.e4.core.di.extensions;bundle-version="0.12.0",
+ org.eclipse.e4.ui.services
+Import-Package: javax.annotation;version="1.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.e4.ui.progress
+Service-Component: OSGI-INF/progress.xml
diff --git a/bundles/org.eclipse.e4.ui.progress/OSGI-INF/progress.xml b/bundles/org.eclipse.e4.ui.progress/OSGI-INF/progress.xml
new file mode 100644
index 0000000..125fe58
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/OSGI-INF/progress.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.ui.progress">
+ <implementation class="org.eclipse.e4.ui.progress.internal.ProgressServiceCreationFunction"/>
+ <service>
+ <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+ </service>
+ <property name="service.context.key" type="String" value="org.eclipse.e4.ui.progress.IProgressService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.progress/build.properties b/bundles/org.eclipse.e4.ui.progress/build.properties
new file mode 100644
index 0000000..31dc406
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/build.properties
@@ -0,0 +1,13 @@
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ fragment.e4xmi,\
+ bin/,\
+ plugin.xml,\
+ contacts.e4xmi,\
+ messages.properties,\
+ icons/,\
+ OSGi-INF/,\
+ OSGi-INF/reference.xml,\
+ OSGI-INF/progress.xml
+source.. = src/
diff --git a/bundles/org.eclipse.e4.ui.progress/examples/programmatic_progress_view.e4xmi b/bundles/org.eclipse.e4.ui.progress/examples/programmatic_progress_view.e4xmi
new file mode 100644
index 0000000..d00f988
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/examples/programmatic_progress_view.e4xmi
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_igBBMG_1EeO3G4cNJzljEA">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_iZEnQIQjEeOJOIhruxA5nw" featurename="addons" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="application:Addon" xmi:id="_zd72cIQjEeOJOIhruxA5nw" elementId="org.eclipse.e4.demo.contacts.jobs.addon.progressmanager" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressViewAddon"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="children" parentElementId="org.eclipse.e4.demo.contacts.partstacks.second" positionInList="first">
+ <elements xsi:type="basic:Part" xmi:id="_j3Yf8G_5EeO3G4cNJzljEA" elementId="org.eclipse.e4.ui.progress.ProgressView" containerData="" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgrammaticProgressView" label="E4 Progress" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/progress/pview.png" closeable="true">
+ <tags>View</tags>
+ <tags>categoryTag:General</tags>
+ <tags>active</tags>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="trimBars" parentElementId="org.eclipse.e4.demo.contacts.main" positionInList="">
+ <elements xsi:type="basic:TrimBar" xmi:id="_lcYOoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.trimbar.0" side="Bottom">
+ <children xsi:type="menu:ToolControl" xmi:id="_peGXoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.toolcontrol.0" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.internal.ProgressRegion"/>
+ </elements>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/bundles/org.eclipse.e4.ui.progress/examples/progress_view.e4xmi b/bundles/org.eclipse.e4.ui.progress/examples/progress_view.e4xmi
new file mode 100644
index 0000000..a35c8be
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/examples/progress_view.e4xmi
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:commands="http://www.eclipse.org/ui/2010/UIModel/application/commands" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_igBBMG_1EeO3G4cNJzljEA">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_iZEnQIQjEeOJOIhruxA5nw" featurename="addons" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="application:Addon" xmi:id="_zd72cIQjEeOJOIhruxA5nw" elementId="org.eclipse.e4.demo.contacts.jobs.addon.progressmanager" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressViewAddon"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="children" parentElementId="org.eclipse.e4.demo.contacts.partstacks.second" positionInList="first">
+ <elements xsi:type="basic:Part" xmi:id="_j3Yf8G_5EeO3G4cNJzljEA" elementId="org.eclipse.e4.ui.progress.ProgressView" containerData="" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressView" label="E4 Progress" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/progress/pview.png" closeable="true">
+ <tags>View</tags>
+ <tags>categoryTag:General</tags>
+ <tags>active</tags>
+ <handlers xmi:id="_LA4DQHX1EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.handlers.clearAll" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ClearAllHandler" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ <handlers xmi:id="_BYE10HYdEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handler.showPreferences" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.OpenPreferenceDialogHandler" command="_IX1dQHYdEeOGuo0e7MGxvQ"/>
+ <menus xmi:id="_rv030HYYEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.menu">
+ <tags>ViewMenu</tags>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_FgL3gHYZEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handledmenuitem.0" label="Clear All" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_Qe7jYHYhEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handledmenuitem.1" label="Preferences" command="_IX1dQHYdEeOGuo0e7MGxvQ"/>
+ </menus>
+ <toolbar xmi:id="_a-JNsHX0EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.toolbar">
+ <children xsi:type="menu:HandledToolItem" xmi:id="_hTniAHX0EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.toolbar.clearAll" label="" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ </toolbar>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8IDN0HX0EeOL1rlhtuWd8w" featurename="commands" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="commands:Command" xmi:id="_Cf0oMHX1EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.commands.clearAll" commandName="Clear All" description="Clear All"/>
+ <elements xsi:type="commands:Command" xmi:id="_IX1dQHYdEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.commands.showPreferences" commandName="Show Preferences" description="Show Preferences"/>
+ <elements xsi:type="commands:Command" xmi:id="_726IYJWOEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.commands.openProgressView" commandName="Open Progress View"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="trimBars" parentElementId="org.eclipse.e4.demo.contacts.main" positionInList="">
+ <elements xsi:type="basic:TrimBar" xmi:id="_lcYOoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.trimbar.0" side="Bottom">
+ <children xsi:type="menu:ToolControl" xmi:id="_peGXoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.toolcontrol.0" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.internal.ProgressRegion"/>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_2nrN8JWPEeOLZ7rxqbmDow" featurename="handlers" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="commands:Handler" xmi:id="_h2PmYJWPEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.handlers.openProgressView" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.OpenProgressViewHandler" command="_726IYJWOEeOLZ7rxqbmDow"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="__pfzwJWPEeOLZ7rxqbmDow" featurename="bindings" parentElementId="_SeXUEO8EEd6FC9cDb6iV7x">
+ <elements xsi:type="commands:KeyBinding" xmi:id="_JKsdMJWQEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.keybinding.openProgressView" keySequence="M1+P" command="_726IYJWOEeOLZ7rxqbmDow"/>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_rem.png b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_rem.png
new file mode 100644
index 0000000..c5df1cd
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_rem.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_remall.png b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_remall.png
new file mode 100644
index 0000000..e7ac19a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_remall.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_stop.png b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_stop.png
new file mode 100644
index 0000000..570f479
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_stop.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_rem.png b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_rem.png
new file mode 100644
index 0000000..c5df1cd
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_rem.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png
new file mode 100644
index 0000000..5b5869d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_stop.png b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_stop.png
new file mode 100644
index 0000000..8068384
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_stop.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/errorstate.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/errorstate.png
new file mode 100644
index 0000000..56d01c4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/errorstate.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/lockedstate.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/lockedstate.png
new file mode 100644
index 0000000..eb528bb
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/lockedstate.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_error.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_error.png
new file mode 100644
index 0000000..d6eda68
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_error.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_none.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_none.png
new file mode 100644
index 0000000..e4d0b00
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_none.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_ok.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_ok.png
new file mode 100644
index 0000000..8096d77
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_ok.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_task.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_task.png
new file mode 100644
index 0000000..32b333a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_task.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/pview.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/pview.png
new file mode 100644
index 0000000..03b71f6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/pview.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/sleeping.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/sleeping.png
new file mode 100644
index 0000000..db0635c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/sleeping.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/icons/full/progress/waiting.png b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/waiting.png
new file mode 100644
index 0000000..eebf3cf
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/waiting.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.progress/plugin.xml b/bundles/org.eclipse.e4.ui.progress/plugin.xml
new file mode 100644
index 0000000..1c07c67
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+>
+</plugin>
diff --git a/bundles/org.eclipse.e4.ui.progress/pom.xml b/bundles/org.eclipse.e4.ui.progress/pom.xml
new file mode 100644
index 0000000..df11148
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012, 2014 Eclipse Foundation and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Distribution License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/org/documents/edl-v10.php
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>eclipse.platform.ui</artifactId>
+ <groupId>eclipse.platform.ui</groupId>
+ <version>4.4.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+ <groupId>org.eclipse.e4</groupId>
+ <artifactId>org.eclipse.e4.ui.progress</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ClearAllHandler.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ClearAllHandler.java
new file mode 100644
index 0000000..8ceec6b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ClearAllHandler.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.progress.internal.FinishedJobs;
+
+
+/**
+ * Removes finished jobs from the progress view.
+ *
+ * @noreference
+ */
+public class ClearAllHandler {
+
+ @Execute
+ public static void clearAll(FinishedJobs finishedJobs) {
+ finishedJobs.clearAll();
+ }
+
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IDisposableAction.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IDisposableAction.java
new file mode 100644
index 0000000..3ff6038
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IDisposableAction.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Interface for a workbench action.
+ */
+public interface IDisposableAction extends IAction {
+ /**
+ * Disposes of this action. Once disposed, this action cannot be used.
+ * This operation has no effect if the action has already been
+ * disposed.
+ */
+ public void dispose();
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IElementCollector.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IElementCollector.java
new file mode 100644
index 0000000..72a71ef
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IElementCollector.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * IElementCollector is a type that allows for the incremental update of a
+ * collection of objects. This used for updating trees incrementally with
+ * a progress monitor so that the update can be reported.
+ *
+ * @see org.eclipse.ui.progress.IDeferredWorkbenchAdapter
+ * @see org.eclipse.ui.progress.DeferredTreeContentManager
+ * @since 3.0
+ */
+public interface IElementCollector {
+ /**
+ * Add the element to the IElementCollector. Send any progress information
+ * to monitor.
+ *
+ * @param element
+ * The element being added
+ * @param monitor
+ * The monitor to send updates to.
+ */
+ public void add(Object element, IProgressMonitor monitor);
+
+ /**
+ * Add the elements to the IElementCollector. Send any progress information
+ * to monitor.
+ *
+ * @param elements
+ * The elements being added
+ * @param monitor
+ * The monitor to send updates to.
+ */
+ public void add(Object[] elements, IProgressMonitor monitor);
+
+ /**
+ * The element collection is done. Clean up any temporary state.
+ *
+ */
+ public void done();
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IJobRunnable.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IJobRunnable.java
new file mode 100644
index 0000000..df3a414
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IJobRunnable.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Interface for runnables that can be run as jobs.
+ *
+ * @since 3.3
+ */
+public interface IJobRunnable {
+
+ /**
+ * Executes this runnable. Returns the result of the execution.
+ * <p>
+ * The provided monitor can be used to report progress and respond to
+ * cancellation. If the progress monitor has been canceled, the runnable should
+ * finish its execution at the earliest convenience and return a result
+ * status of severity <code>IStatus.CANCEL</code>. The singleton cancel
+ * status <code>Status.CANCEL_STATUS</code> can be used for this purpose.
+ * <p>
+ *
+ * @param monitor
+ * the monitor to be used for reporting progress and responding
+ * to cancelation. The monitor is never <code>null</code>
+ * @return resulting status of the run. The result must not be
+ * <code>null</code>
+ */
+ public IStatus run(IProgressMonitor monitor);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressConstants.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressConstants.java
new file mode 100644
index 0000000..a87a0d0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressConstants.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.core.runtime.QualifiedName;
+
+/**
+ * Constants relating to progress UI functionality of the workbench plug-in.
+ * <p>
+ * The four constants define property keys that are used to associate
+ * UI related information with Jobs (<code>org.eclipse.core.runtime.jobs.Job</code>).
+ *
+ * @see org.eclipse.core.runtime.jobs.Job#setProperty
+ * @since 3.0
+ */
+public interface IProgressConstants {
+
+ /**
+ * Common prefix for properties defined in this interface.
+ */
+ static final String PROPERTY_PREFIX = "org.eclipse.ui"; //$NON-NLS-1$
+
+ static final String PLUGIN_ID = "org.eclipse.e4.ui.progress"; //$NON-NLS-1$
+
+
+ /**
+ * This property provides a hint to the progress UI to keep Jobs
+ * in the UI after they have finished. This can be used to communicate results of a Job
+ * back to the user.
+ * <p>
+ * The property must be of type <code>Boolean</code> and the hint is used
+ * if its value is <code>true</code>.
+ * </p>
+ */
+ public static final QualifiedName KEEP_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "keep"); //$NON-NLS-1$
+
+ /**
+ * The KEEPONE_PROPERTY is an extension to the KEEP_PROPERTY, that provides a hint
+ * to the progress UI to ensure that only a single Job of a Job family is kept in the
+ * set of kept Jobs. That is, whenever a Job that has the KEEPONE_PROPERTY starts or finishes,
+ * all other kept Jobs of the same family are removed first.
+ * <p>
+ * Membership to family is determined using a Job's <code>belongsTo</code>
+ * method. The progress service will pass each job that currently exists in the
+ * view to the <code>belongsTo</code> method of a newly added job. Clients who
+ * set the <code>KEEPONE_PROPERTY</code> must implement a <code>belongsTo</code>
+ * method that determines if the passed job is of the same family as their job
+ * and return <code>true</code> if it is.
+ * </p>
+ * <p>
+ * Please note that other Jobs of the same family are only removed if they have finished.
+ * Non finished jobs of the same family are left alone.
+ * </p>
+ **/
+ public static final QualifiedName KEEPONE_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "keepone"); //$NON-NLS-1$
+
+ /**
+ * This property is used to associate an <code>IAction</code> with a Job. If
+ * the Job is shown in the UI, the action might be represented as a button
+ * or hyper link to allow the user to trigger a job specific action, like
+ * showing the Job's results.
+ * <p>
+ * The progress UI will track the enabled state of the action and its
+ * tooltip text.
+ * </p>
+ * <p>
+ * If the action implements <code>ActionFactory.IWorkbenchAction</code>, its
+ * <code>dispose</code> method will be called as soon as the Job is finally
+ * removed from the set of kept jobs.
+ * </p>
+ * <p>
+ * Note: Only one of <code>ACTION_PROPERTY</code> or
+ * <code>COMMAND_PROPERTY</code> should be used
+ * </p>
+ *
+ * @see org.eclipse.jface.action.IAction
+ **/
+ public static final QualifiedName ACTION_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "action"); //$NON-NLS-1$
+
+ /**
+ * This property is used to associate an <code>ImageDescriptor</code> with a Job.
+ * If the Job is shown in the UI, this descriptor is used to create an icon that
+ * represents the Job.
+ * <p>
+ * Please note, that this property is only used if no <code>ImageDescriptor</code> has been
+ * registered for the Job family with the <code>IProgressService</code>.
+ * </p>
+ * @see org.eclipse.jface.resource.ImageDescriptor
+ * @see org.eclipse.e4.ui.progress.IProgressService
+ **/
+ public static final QualifiedName ICON_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "icon"); //$NON-NLS-1$
+
+ /**
+ * This is a property set on a user job if the user has not decided to
+ * run the job in the background.
+ * The value is set to <code>true</code> when the job starts and set to
+ * <code>false</code> if the user subsequently decides to complete the job in the
+ * background.
+ * <p>
+ * This property is not intended to be set by clients.
+ * </p>
+ * @see org.eclipse.core.runtime.jobs.Job#isUser()
+ */
+ public static final QualifiedName PROPERTY_IN_DIALOG = new QualifiedName(
+ IProgressConstants.PROPERTY_PREFIX, "inDialog"); //$NON-NLS-1$
+
+ /**
+ * This property provides a hint to the progress UI to not prompt on errors
+ * immediately but instead make the errors available through the progress UI.
+ * <p>
+ * The property must be of type <code>Boolean</code> and the hint is used
+ * if its value is <code>true</code>.
+ * </p>
+ * @since 3.1
+ */
+ public static final QualifiedName NO_IMMEDIATE_ERROR_PROMPT_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "delayErrorPrompt"); //$NON-NLS-1$
+
+ /**
+ * Stores whether or not system jobs are being shown.
+ *
+ * @since 3.1
+ */
+ public static final String SHOW_SYSTEM_JOBS = "SHOW_SYSTEM_JOBS";//$NON-NLS-1$
+
+ /**
+ * This property is used to associate a <code>ParameterizedCommand</code>
+ * with a Job. If the Job is shown in the UI, the command might be
+ * represented as a button or hyper link to allow the user to trigger a job
+ * specific action, like showing the Job's results.
+ * <p>
+ * Note: Only one of <code>ACTION_PROPERTY</code> or
+ * <code>COMMAND_PROPERTY</code> should be used
+ * </p>
+ *
+ * @see org.eclipse.core.commands.ParameterizedCommand
+ **/
+ public static final QualifiedName COMMAND_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "command"); //$NON-NLS-1$
+
+ /**
+ * This property provides a hint to the progress UI to show the progress of
+ * the job in the application TaskBar
+ * <p>
+ * The property must be of type <code>Boolean</code> and the hint is used if
+ * its value is <code>true</code>.
+ * </p>
+ */
+ public static final QualifiedName SHOW_IN_TASKBAR_ICON_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "inTaskBarIcon"); //$NON-NLS-1$
+
+ public static final String RUN_IN_BACKGROUND = "RUN_IN_BACKGROUND";
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressService.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressService.java
new file mode 100644
index 0000000..dd0b13b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/IProgressService.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.ProgressProvider;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The progress service is the primary interface to the workbench progress
+ * support. It can be obtained from the workbench and then used to show progress
+ * for both background operations and operations that run in the UI thread.
+ * <p>
+ * All methods on the progress service must be called from the UI thread.
+ * </p>
+ * <p>
+ * This service can be acquired from your service locator:
+ * <pre>
+ * IProgressService service = (IProgressService) getSite().getService(IProgressService.class);
+ * </pre>
+ * <ul>
+ * <li>This service is available globally.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * <strong>NOTE</strong> The progress service must be referenced at least once
+ * before it will become the progress provider for the {@link IJobManager} in
+ * the workbench. This connection is done lazily so that RCP applications will
+ * not have to use the {@link IProgressService} as the {@link ProgressProvider}
+ * to the jobs framework if they do not wish to reference it.
+ * </p>
+ *
+ * @see IJobManager#setProgressProvider(org.eclipse.core.runtime.jobs.ProgressProvider)
+ *
+ * @since 3.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IProgressService extends IRunnableContext {
+
+ /**
+ * The time at which an operation becomes considered a long
+ * operation. Used to determine when the busy cursor will
+ * be replaced with a progress monitor.
+ * @return int
+ * @see IProgressService#busyCursorWhile(IRunnableWithProgress)
+ */
+ public int getLongOperationTime();
+
+ /**
+ * Register the ImageDescriptor to be the icon used for
+ * all jobs that belong to family within the workbench.
+ * @param icon ImageDescriptor that will be used when the job is being displayed
+ * @param family The family to associate with
+ * @see Job#belongsTo(Object)
+ */
+ public void registerIconForFamily(ImageDescriptor icon, Object family);
+
+ /**
+ * Runs the given operation in the UI thread using the given runnable context.
+ * The given scheduling rule, if any, will be acquired for the duration of the operation.
+ * If the rule is not available when this method is called, a progress dialog will be
+ * displayed that gives users control over the background processes that may
+ * be blocking the runnable from proceeding.
+ * <p>
+ * This method can act as a wrapper for uses of <tt>IRunnableContext</tt>
+ * where the <tt>fork</tt> parameter was <tt>false</tt>.
+ * <p>
+ * Note: Running long operations in the UI thread is generally not
+ * recommended. This can result in the UI becoming unresponsive for
+ * the duration of the operation. Where possible, <tt>busyCursorWhile</tt>
+ * should be used instead.
+ * </p>
+ * <p>
+ * Modal dialogs should also be avoided in the runnable as there will already
+ * be a modal progress dialog open when this operation runs.
+ * </p>
+ * @see org.eclipse.jface.dialogs.Dialog
+ * @see org.eclipse.swt.SWT#APPLICATION_MODAL
+ *
+ * @param context The runnable context to run the operation in
+ * @param runnable The operation to run
+ * @param rule A scheduling rule, or <code>null</code>
+ * @throws InvocationTargetException wraps any exception or error which occurs
+ * while running the runnable
+ * @throws InterruptedException propagated by the context if the runnable
+ * acknowledges cancelation by throwing this exception.
+ *
+ */
+ public void runInUI(IRunnableContext context,
+ IRunnableWithProgress runnable, ISchedulingRule rule)
+ throws InvocationTargetException, InterruptedException;
+
+ /**
+ * Get the icon that has been registered for a Job by
+ * checking if the job belongs to any of the registered
+ * families.
+ * @param job
+ * @return Icon or <code>null</code> if there isn't one.
+ * @see IProgressService#registerIconForFamily(ImageDescriptor,Object)
+ */
+ public Image getIconFor(Job job);
+
+ /**
+ * Set the cursor to busy and run the runnable in a non-UI Thread.
+ * The calling thread will be blocked for the duration of the execution
+ * of the supplied runnable.
+ *
+ * After the cursor has been running for
+ * <code>getLongOperationTime()</code> replace it with
+ * a ProgressMonitorDialog so that the user may cancel.
+ * Do not open the ProgressMonitorDialog if there is already a modal
+ * dialog open.
+ *
+ * @param runnable The runnable to execute and show the progress for.
+ * @see IProgressService#getLongOperationTime
+ * @throws InvocationTargetException
+ * @throws InterruptedException
+ */
+ public void busyCursorWhile(IRunnableWithProgress runnable)
+ throws InvocationTargetException, InterruptedException;
+
+ /**
+ * This specialization of IRunnableContext#run(boolean, boolean,
+ * IRunnableWithProgress) might run the runnable asynchronously
+ * if <code>fork</code> is <code>true</code>.
+ *
+ * @since 3.2
+ */
+ public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException;
+
+ /**
+ * Open a dialog on job when it starts to run and close it
+ * when the job is finished. Wait for ProgressManagerUtil#SHORT_OPERATION_TIME
+ * before opening the dialog. Do not open if it is already done or
+ * if the user has set a preference to always run in the background.
+ *
+ * Parent the dialog from the shell.
+ *
+ * @param shell The Shell to parent the dialog from or
+ * <code>null</code> if the active shell is to be used.
+ * @param job The Job that will be reported in the dialog. job
+ * must not be <code>null</code>.
+ */
+ public void showInDialog(Shell shell, Job job);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenPreferenceDialogHandler.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenPreferenceDialogHandler.java
new file mode 100644
index 0000000..07a791a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenPreferenceDialogHandler.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.progress.internal.JobsViewPreferenceDialog;
+import org.eclipse.e4.ui.progress.internal.PreferenceStore;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.swt.widgets.Shell;
+
+
+/**
+ * Opens the progress view preference dialog.
+ *
+ * @noreference
+ */
+public class OpenPreferenceDialogHandler {
+
+ @Execute
+ public void openPreferenceDialog(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell, PreferenceStore preferences) {
+ new JobsViewPreferenceDialog(shell, preferences).open();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenProgressViewHandler.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenProgressViewHandler.java
new file mode 100644
index 0000000..6704f8b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/OpenProgressViewHandler.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.progress.internal.ProgressManagerUtil;
+
+
+/**
+ * Opens the progress view.
+ *
+ * @noreference
+ */
+public class OpenProgressViewHandler {
+
+ @Execute
+ public void openProgressView() {
+ ProgressManagerUtil.openProgressView();
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgrammaticProgressView.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgrammaticProgressView.java
new file mode 100644
index 0000000..1d18d94
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgrammaticProgressView.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MHandler;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.progress.internal.DetailedProgressViewer;
+import org.eclipse.e4.ui.progress.internal.FinishedJobs;
+import org.eclipse.e4.ui.progress.internal.ProgressManager;
+import org.eclipse.e4.ui.progress.internal.ProgressManagerUtil;
+import org.eclipse.e4.ui.progress.internal.ProgressViewUpdater;
+import org.eclipse.e4.ui.progress.internal.ProgressViewerContentProvider;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @noreference
+ */
+public class ProgrammaticProgressView {
+
+ private static final String CLEAR_ALL_ICON_URI = "platform:/plugin/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png";
+
+ DetailedProgressViewer viewer;
+
+ @Inject
+ ESelectionService selectionService;
+
+ @Inject
+ EModelService modelService;
+
+ MApplication application;
+ MPart part;
+
+ ISelectionChangedListener selectionListener;
+
+ private MCommand clearAllCommand;
+ private MCommand showPreferencesCommand;
+
+ @PostConstruct
+ public void createPartControl(Composite parent, MApplication application,
+ MPart part, ProgressManager progressManager,
+ IProgressService progressService, FinishedJobs finishedJobs,
+ ProgressViewUpdater viewUpdater) {
+ this.application = application;
+ this.part = part;
+ viewer = new DetailedProgressViewer(parent, SWT.MULTI | SWT.H_SCROLL,
+ progressService, finishedJobs);
+ viewer.setComparator(ProgressManagerUtil.getProgressViewerComparator());
+
+ viewer.getControl().setLayoutData(
+ new GridData(SWT.FILL, SWT.FILL, true, true));
+
+// helpSystem.setHelp(parent, IWorkbenchHelpContextIds.RESPONSIVE_UI);
+
+ ProgressViewerContentProvider provider = new ProgressViewerContentProvider(
+ viewer, finishedJobs, viewUpdater, progressManager, true, true);
+ viewer.setContentProvider(provider);
+ viewer.setInput(progressManager);
+
+ selectionListener = new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (selectionService != null)
+ selectionService.setSelection(event.getSelection());
+ }
+ };
+ viewer.addSelectionChangedListener(selectionListener);
+
+ createCommands();
+ createViewMenu();
+
+ }
+
+ @Focus
+ public void setFocus() {
+ if (viewer != null) {
+ viewer.setFocus();
+ }
+ }
+
+ private void createCommands() {
+ clearAllCommand = modelService.createModelElement(MCommand.class);
+ clearAllCommand.setElementId("clearAllCommand");
+ clearAllCommand.setCommandName("clearAllCommand");
+ application.getCommands().add(clearAllCommand);
+
+ showPreferencesCommand = modelService.createModelElement(MCommand.class);
+ showPreferencesCommand.setElementId("showPreferencesCommand");
+ showPreferencesCommand.setCommandName("showPreferencesCommand");
+ application.getCommands().add(showPreferencesCommand);
+
+ MHandler clearAllHandler = modelService.createModelElement(MHandler.class);
+ clearAllHandler.setCommand(clearAllCommand);
+ clearAllHandler.setContributionURI("bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ClearAllHandler");
+ part.getHandlers().add(clearAllHandler);
+
+ MHandler showPreferencesHandler = modelService.createModelElement(MHandler.class);
+ showPreferencesHandler.setCommand(showPreferencesCommand);
+ showPreferencesHandler.setContributionURI("bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ShowPreferencesHandler");
+ part.getHandlers().add(showPreferencesHandler);
+
+ }
+
+ private void createViewMenu() {
+
+
+ MHandledToolItem clearAllButton = modelService.createModelElement(MHandledToolItem.class);
+ clearAllButton.setIconURI(CLEAR_ALL_ICON_URI);
+ clearAllButton.setCommand(clearAllCommand);
+
+ MToolBar toolBar = modelService.createModelElement(MToolBar.class);
+ toolBar.getChildren().add(clearAllButton);
+ part.setToolbar(toolBar);
+
+ MHandledMenuItem clearAllMenuItem = modelService.createModelElement(MHandledMenuItem.class);
+ clearAllMenuItem.setLabel("Clear All");
+ clearAllMenuItem.setIconURI(CLEAR_ALL_ICON_URI);
+ clearAllMenuItem.setCommand(clearAllCommand);
+
+ MHandledMenuItem preferencesMenuItem = modelService.createModelElement(MHandledMenuItem.class);
+ preferencesMenuItem.setLabel("Preferences");
+ preferencesMenuItem.setCommand(showPreferencesCommand);
+
+ MMenu menu = modelService.createModelElement(MMenu.class);
+ menu.getTags().add("ViewMenu"); // required
+ menu.getChildren().add(clearAllMenuItem);
+ menu.getChildren().add(preferencesMenuItem);
+
+ part.getMenus().add(menu);
+
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressView.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressView.java
new file mode 100644
index 0000000..f790d42
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressView.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.progress.internal.DetailedProgressViewer;
+import org.eclipse.e4.ui.progress.internal.FinishedJobs;
+import org.eclipse.e4.ui.progress.internal.ProgressManager;
+import org.eclipse.e4.ui.progress.internal.ProgressManagerUtil;
+import org.eclipse.e4.ui.progress.internal.ProgressViewUpdater;
+import org.eclipse.e4.ui.progress.internal.ProgressViewerContentProvider;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @noreference
+ */
+public class ProgressView {
+
+ DetailedProgressViewer viewer;
+
+ @Inject
+ ESelectionService selectionService;
+
+ ISelectionChangedListener selectionListener;
+
+ @PostConstruct
+ public void createPartControl(Composite parent, ProgressManager progressManager,
+ IProgressService progressService, FinishedJobs finishedJobs,
+ ProgressViewUpdater viewUpdater) {
+ viewer = new DetailedProgressViewer(parent, SWT.MULTI | SWT.H_SCROLL,
+ progressService, finishedJobs);
+ viewer.setComparator(ProgressManagerUtil.getProgressViewerComparator());
+
+ viewer.getControl().setLayoutData(
+ new GridData(SWT.FILL, SWT.FILL, true, true));
+
+// helpSystem.setHelp(parent, IWorkbenchHelpContextIds.RESPONSIVE_UI);
+
+ ProgressViewerContentProvider provider = new ProgressViewerContentProvider(
+ viewer, finishedJobs, viewUpdater, progressManager, true, true);
+ viewer.setContentProvider(provider);
+ viewer.setInput(progressManager);
+
+ selectionListener = new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (selectionService != null)
+ selectionService.setSelection(event.getSelection());
+ }
+ };
+ viewer.addSelectionChangedListener(selectionListener);
+ }
+
+ @Focus
+ public void setFocus() {
+ if (viewer != null) {
+ viewer.setFocus();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressViewAddon.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressViewAddon.java
new file mode 100644
index 0000000..6ffc67c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/ProgressViewAddon.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress;
+
+import javax.annotation.PostConstruct;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.progress.internal.PreferenceStore;
+import org.eclipse.e4.ui.progress.internal.ProgressManager;
+import org.eclipse.e4.ui.progress.internal.Services;
+
+public class ProgressViewAddon {
+
+ @PostConstruct
+ public void init(MApplication application, IEclipseContext context) {
+ IEclipseContext appContext = application.getContext();
+ appContext.set(PreferenceStore.class, ContextInjectionFactory.make(PreferenceStore.class, appContext));
+ ContextInjectionFactory.make(Services.class, context);
+ ProgressManager progressManager = ContextInjectionFactory.make(ProgressManager.class, context);
+ appContext.set(ProgressManager.class, progressManager);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/UIJob.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/UIJob.java
new file mode 100644
index 0000000..37b79a2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/UIJob.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.e4.ui.progress.internal.ProgressMessages;
+import org.eclipse.e4.ui.progress.internal.Services;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.e4.ui.progress.internal.legacy.StatusUtil;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * The UIJob is a Job that runs within the UI Thread via an asyncExec.
+ *
+ * @since 3.0
+ */
+public abstract class UIJob extends Job {
+ private Display cachedDisplay;
+
+ /**
+ * Create a new instance of the receiver with the supplied name. The display
+ * used will be the one from the workbench if this is available. UIJobs with
+ * this constructor will determine their display at runtime.
+ *
+ * @param name
+ * the job name
+ *
+ */
+ public UIJob(String name) {
+ super(name);
+ }
+
+ /**
+ * Create a new instance of the receiver with the supplied Display.
+ *
+ * @param jobDisplay
+ * the display
+ * @param name
+ * the job name
+ * @see Job
+ */
+ public UIJob(Display jobDisplay, String name) {
+ this(name);
+ setDisplay(jobDisplay);
+ }
+
+ /**
+ * Convenience method to return a status for an exception.
+ *
+ * @param exception
+ * @return IStatus an error status built from the exception
+ * @see Job
+ */
+ public static IStatus errorStatus(Throwable exception) {
+ return getStatus(exception);
+ }
+
+ /**
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ * Note: this message is marked final. Implementors should use
+ * runInUIThread() instead.
+ */
+ public final IStatus run(final IProgressMonitor monitor) {
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ UISynchronize uiSynchronize = getUiSynchronize();
+ if (uiSynchronize == null) {
+ return Status.CANCEL_STATUS;
+ }
+ uiSynchronize.asyncExec(new Runnable() {
+ public void run() {
+ IStatus result = null;
+ Throwable throwable = null;
+ try {
+ //As we are in the UI Thread we can
+ //always know what to tell the job.
+ setThread(Thread.currentThread());
+ if (monitor.isCanceled()) {
+ result = Status.CANCEL_STATUS;
+ } else {
+ // TODO E4 - missing e4 replacement
+ // UIStats.start(UIStats.UI_JOB, getName());
+ result = runInUIThread(monitor);
+ }
+
+ } catch(Throwable t){
+ throwable = t;
+ } finally {
+ // TODO E4 - missing e4 replacement
+ // UIStats.end(UIStats.UI_JOB, UIJob.this, getName());
+ if (result == null) {
+ result = new Status(IStatus.ERROR,
+ IProgressConstants.PLUGIN_ID, IStatus.ERROR,
+ ProgressMessages.InternalError,
+ throwable);
+ }
+ done(result);
+ }
+ }
+ });
+ return Job.ASYNC_FINISH;
+ }
+
+ /**
+ * Run the job in the UI Thread.
+ *
+ * @param monitor
+ * @return IStatus
+ */
+ public abstract IStatus runInUIThread(IProgressMonitor monitor);
+
+ /**
+ * Sets the display to execute the asyncExec in. Generally this is not'
+ * used if there is a valid display available via PlatformUI.isWorkbenchRunning().
+ *
+ * @param runDisplay
+ * Display
+ * @see UIJob#getDisplay()
+ * @see PlatformUI#isWorkbenchRunning()
+ */
+ public void setDisplay(Display runDisplay) {
+ Assert.isNotNull(runDisplay);
+ cachedDisplay = runDisplay;
+ }
+
+ /**
+ * Returns the display for use by the receiver when running in an
+ * asyncExec. If it is not set then the display set in the workbench
+ * is used.
+ * If the display is null the job will not be run.
+ *
+ * @return Display or <code>null</code>.
+ */
+ public Display getDisplay() {
+ if (cachedDisplay == null) {
+ cachedDisplay = Services.getInstance().getDisplay();
+ }
+ if (cachedDisplay == null) {
+ cachedDisplay = Display.getCurrent();
+ }
+ if (cachedDisplay == null) {
+ cachedDisplay = Display.getDefault();
+ }
+ return cachedDisplay;
+ }
+
+ public static IStatus getStatus(Throwable t) {
+ String message = StatusUtil.getLocalizedMessage(t);
+
+ return newError(message, t);
+ }
+
+ public static IStatus newError(String message, Throwable t) {
+ String pluginId = IProgressConstants.PLUGIN_ID;
+ int errorCode = IStatus.OK;
+
+ // If this was a CoreException, keep the original plugin ID and error
+ // code
+ if (t instanceof CoreException) {
+ CoreException ce = (CoreException) t;
+ pluginId = ce.getStatus().getPlugin();
+ errorCode = ce.getStatus().getCode();
+ }
+
+ return new Status(IStatus.ERROR, pluginId, errorCode, message,
+ StatusUtil.getCause(t));
+ }
+
+ protected UISynchronize getUiSynchronize() {
+ return Services.getInstance().getUISynchronize();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AbstractProgressViewer.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AbstractProgressViewer.java
new file mode 100644
index 0000000..4183014
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AbstractProgressViewer.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+
+/**
+ * The AbstractProgressViewer is the abstract superclass of the viewers that
+ * show progress.
+ *
+ */
+public abstract class AbstractProgressViewer extends StructuredViewer {
+
+ /**
+ * Add the elements to the receiver.
+ * @param elements
+ */
+ public abstract void add(Object[] elements);
+
+ /**
+ * Remove the elements from the receiver.
+ * @param elements
+ */
+ public abstract void remove(Object[] elements);
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationItem.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationItem.java
new file mode 100644
index 0000000..2176bad
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationItem.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The AnimationItem is the class that manages the animation for the progress.
+ */
+public abstract class AnimationItem {
+
+ private AnimationManager animationManager;
+
+ interface IAnimationContainer {
+ /**
+ * The animation has started.
+ */
+ public abstract void animationStart();
+
+ /**
+ * The animation has ended.
+ */
+ public abstract void animationDone();
+ }
+
+ //Create a containter that does nothing by default
+ IAnimationContainer animationContainer = new IAnimationContainer() {
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AnimationItem.IAnimationContainer#animationDone()
+ */
+ public void animationDone() {
+ //Do nothing by default
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AnimationItem.IAnimationContainer#animationStart()
+ */
+ public void animationStart() {
+ //Do nothing by default
+ }
+ };
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param workbenchWindow
+ * the window being created
+ */
+ public AnimationItem(AnimationManager animationManager) {
+ this.animationManager = animationManager;
+ }
+
+ /**
+ * Create the canvas that will display the image.
+ *
+ * @param parent
+ */
+ public void createControl(Composite parent) {
+
+ Control animationItem = createAnimationItem(parent);
+
+ animationItem.addMouseListener(new MouseListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent arg0) {
+ ProgressManagerUtil.openProgressView();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDown(MouseEvent arg0) {
+ //Do nothing
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseUp(MouseEvent arg0) {
+ //Do nothing
+ }
+ });
+ animationItem.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ animationManager.removeItem(AnimationItem.this);
+ }
+ });
+ animationManager.addItem(this);
+ }
+
+ /**
+ * Create the animation item control.
+ * @param parent the parent Composite
+ * @return Control
+ */
+ protected abstract Control createAnimationItem(Composite parent);
+
+ /**
+ * Paint the image in the canvas.
+ *
+ * @param event
+ * The PaintEvent that generated this call.
+ * @param image
+ * The image to display
+ * @param imageData
+ * The array of ImageData. Required to show an animation.
+ */
+ void paintImage(PaintEvent event, Image image, ImageData imageData) {
+ event.gc.drawImage(image, 0, 0);
+ }
+
+ /**
+ * Get the SWT control for the receiver.
+ *
+ * @return Control
+ */
+ public abstract Control getControl();
+
+ /**
+ * The animation has begun.
+ */
+ void animationStart() {
+ animationContainer.animationStart();
+ }
+
+ /**
+ * The animation has ended.
+ */
+ void animationDone() {
+ animationContainer.animationDone();
+ }
+
+ /**
+ * Get the preferred width of the receiver.
+ *
+ * @return int
+ */
+ public int getPreferredWidth() {
+ return animationManager.getPreferredWidth() + 5;
+ }
+
+ /**
+ * Set the container that will be updated when this runs.
+ * @param container The animationContainer to set.
+ */
+ void setAnimationContainer(IAnimationContainer container) {
+ this.animationContainer = container;
+ }
+
+ /**
+ * @return Returns the window.
+ */
+// public WorkbenchWindow getWindow() {
+// return window;
+// }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationManager.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationManager.java
new file mode 100644
index 0000000..534aff1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/AnimationManager.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The AnimationManager is the class that keeps track of the animation items to
+ * update.
+ */
+@Creatable
+@Singleton
+public class AnimationManager {
+
+ boolean animated = false;
+
+ private IJobProgressManagerListener listener;
+
+ IAnimationProcessor animationProcessor;
+
+ Job animationUpdateJob;
+
+ @Inject
+ ProgressManager progressManager;
+
+ /**
+ * Get the background color to be used.
+ *
+ * @param control
+ * The source of the display.
+ * @return Color
+ */
+ static Color getItemBackgroundColor(Control control) {
+ return control.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
+ }
+
+ @PostConstruct
+ void init() {
+
+ animationProcessor = new ProgressAnimationProcessor(this);
+
+ animationUpdateJob = new UIJob(ProgressMessages.AnimationManager_AnimationStart) {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+
+ if (animated) {
+ animationProcessor.animationStarted();
+ } else {
+ animationProcessor.animationFinished();
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ animationUpdateJob.setSystem(true);
+
+ listener = getProgressListener();
+ progressManager.addListener(listener);
+
+
+ }
+
+ /**
+ * Add an item to the list
+ *
+ * @param item
+ */
+ void addItem(final AnimationItem item) {
+ animationProcessor.addItem(item);
+ }
+
+ /**
+ * Remove an item from the list
+ *
+ * @param item
+ */
+ void removeItem(final AnimationItem item) {
+ animationProcessor.removeItem(item);
+ }
+
+ /**
+ * Return whether or not the current state is animated.
+ *
+ * @return boolean
+ */
+ boolean isAnimated() {
+ return animated;
+ }
+
+ /**
+ * Set whether or not the receiver is animated.
+ *
+ * @param boolean
+ */
+ void setAnimated(final boolean bool) {
+ animated = bool;
+ animationUpdateJob.schedule(100);
+ }
+
+ /**
+ * Dispose the images in the receiver.
+ */
+ void dispose() {
+ setAnimated(false);
+ progressManager.removeListener(listener);
+ }
+
+ private IJobProgressManagerListener getProgressListener() {
+ return new IJobProgressManagerListener() {
+ Set jobs = Collections.synchronizedSet(new HashSet());
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#addJob(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void addJob(JobInfo info) {
+ incrementJobCount(info);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshJobInfo(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void refreshJobInfo(JobInfo info) {
+ int state = info.getJob().getState();
+ if (state == Job.RUNNING) {
+ addJob(info);
+ } else {
+ removeJob(info);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshAll()
+ */
+ public void refreshAll() {
+ jobs.clear();
+ setAnimated(false);
+ JobInfo[] currentInfos = progressManager.getJobInfos(showsDebug());
+ for (int i = 0; i < currentInfos.length; i++) {
+ addJob(currentInfos[i]);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#remove(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void removeJob(JobInfo info) {
+ decrementJobCount(info.getJob());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#showsDebug()
+ */
+ public boolean showsDebug() {
+ return false;
+ }
+
+ private void incrementJobCount(JobInfo info) {
+ //Don't count the animate job itself
+ if (isNotTracked(info)) {
+ return;
+ }
+ if (jobs.isEmpty()) {
+ setAnimated(true);
+ }
+ jobs.add(info.getJob());
+ }
+
+ /*
+ * Decrement the job count for the job
+ */
+ private void decrementJobCount(Job job) {
+ jobs.remove(job);
+ if (jobs.isEmpty()) {
+ setAnimated(false);
+ }
+ }
+
+ /**
+ * If this is one of our jobs or not running then don't bother.
+ */
+ private boolean isNotTracked(JobInfo info) {
+ //We always track errors
+ Job job = info.getJob();
+ return job.getState() != Job.RUNNING
+ || animationProcessor.isProcessorJob(job);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#addGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void addGroup(GroupInfo info) {
+ //Don't care about groups
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#removeGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void removeGroup(GroupInfo group) {
+ //Don't care about groups
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void refreshGroup(GroupInfo info) {
+ //Don't care about groups
+ }
+ };
+ }
+
+ /**
+ * Get the preferred width for widgets displaying the animation.
+ *
+ * @return int. Return 0 if there is no image data.
+ */
+ int getPreferredWidth() {
+ return animationProcessor.getPreferredWidth();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/BlockedJobsDialog.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/BlockedJobsDialog.java
new file mode 100644
index 0000000..1c9bf63
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/BlockedJobsDialog.java
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.jface.dialogs.IconAndMessageDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The BlockedJobsDialog class displays a dialog that provides information on
+ * the running jobs.
+ */
+public class BlockedJobsDialog extends IconAndMessageDialog {
+ /**
+ * The singleton dialog instance. A singleton avoids the possibility of
+ * recursive dialogs being created. The singleton is created when a dialog
+ * is requested, and cleared when the dialog is disposed.
+ */
+ protected static BlockedJobsDialog singleton;
+
+ /**
+ * The running jobs progress viewer.
+ */
+ private DetailedProgressViewer viewer;
+
+ /**
+ * The name of the task that is being blocked.
+ */
+ private String blockedTaskName = ProgressMessages.SubTaskInfo_UndefinedTaskName;
+
+ /**
+ * The Cancel button control.
+ */
+ private Button cancelSelected;
+
+ /**
+ * The cursor for the buttons.
+ */
+ private Cursor arrowCursor;
+
+ /**
+ * The cursor for the Shell.
+ */
+ private Cursor waitCursor;
+
+ private IProgressMonitor blockingMonitor;
+
+ private JobTreeElement blockedElement = new BlockedUIElement();
+
+ private IProgressService progressService;
+
+ private FinishedJobs finishedJobs;
+
+ private ProgressManager progressManager;
+
+ private ProgressViewUpdater progressViewUpdater;
+
+ /**
+ * The BlockedUIElement is the JobTreeElement that represents the blocked
+ * job in the dialog.
+ */
+ private class BlockedUIElement extends JobTreeElement {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren()
+ */
+ Object[] getChildren() {
+ return ProgressManagerUtil.EMPTY_OBJECT_ARRAY;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString()
+ */
+ String getDisplayString() {
+ if (blockedTaskName == null || blockedTaskName.length() == 0) {
+ return ProgressMessages.BlockedJobsDialog_UserInterfaceTreeElement;
+ }
+ return blockedTaskName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayImage()
+ */
+ public Image getDisplayImage() {
+ return JFaceResources.getImage(ProgressManager.WAITING_JOB_KEY);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren()
+ */
+ boolean hasChildren() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive()
+ */
+ boolean isActive() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ boolean isJobInfo() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#cancel()
+ */
+ public void cancel() {
+ blockingMonitor.setCanceled(true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isCancellable()
+ */
+ public boolean isCancellable() {
+ return true;
+ }
+ }
+
+ /**
+ * Creates a progress monitor dialog under the given shell. It also sets the
+ * dialog's message. The dialog is opened automatically after a reasonable
+ * delay. When no longer needed, the dialog must be closed by calling
+ * <code>close(IProgressMonitor)</code>, where the supplied monitor is
+ * the same monitor passed to this factory method.
+ *
+ * @param parentShell
+ * The parent shell, or <code>null</code> to create a top-level
+ * shell. If the parentShell is not null we will open immediately
+ * as parenting has been determined. If it is <code>null</code>
+ * then the dialog will not open until there is no modal shell
+ * blocking it.
+ * @param blockedMonitor
+ * The monitor that is currently blocked
+ * @param reason
+ * A status describing why the monitor is blocked
+ * @param taskName
+ * A name to give the blocking task in the dialog
+ * @return BlockedJobsDialog
+ */
+ public static BlockedJobsDialog createBlockedDialog(Shell parentShell,
+ IProgressMonitor blockedMonitor, IStatus reason, String taskName,
+ IProgressService progressService, FinishedJobs finishedJobs,
+ ProgressViewUpdater viewUpdater, ProgressManager progressManager) {
+ // use an existing dialog if available
+ if (singleton != null) {
+ return singleton;
+ }
+ singleton = new BlockedJobsDialog(parentShell, blockedMonitor, reason,
+ progressService, finishedJobs, viewUpdater, progressManager);
+
+ if (taskName == null || taskName.length() == 0)
+ singleton
+ .setBlockedTaskName(ProgressMessages.BlockedJobsDialog_UserInterfaceTreeElement);
+ else
+ singleton.setBlockedTaskName(taskName);
+
+ /**
+ * If there is no parent shell we have not been asked for a parent so we
+ * want to avoid blocking. If there is a parent then it is OK to open.
+ */
+ if (parentShell == null) {
+ // create the job that will open the dialog after a delay.
+ Job dialogJob = new UIJob(
+ ProgressMessages.EventLoopProgressMonitor_OpenDialogJobName) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (singleton == null) {
+ return Status.CANCEL_STATUS;
+ }
+ if (ProgressManagerUtil.rescheduleIfModalShellOpen(this,
+ Services.getInstance().getProgressService())) {
+ return Status.CANCEL_STATUS;
+ }
+ singleton.open();
+ return Status.OK_STATUS;
+ }
+ };
+ // Wait for long operation time to prevent a proliferation
+ // of dialogs
+ dialogJob.setSystem(true);
+ dialogJob.schedule(Services.getInstance().getProgressService()
+ .getLongOperationTime());
+ } else {
+ singleton.open();
+ }
+
+ return singleton;
+ }
+
+ /**
+ * monitor is done. Clear the receiver.
+ *
+ * @param monitor
+ * The monitor that is now cleared.
+ */
+ public static void clear(IProgressMonitor monitor) {
+ if (singleton == null) {
+ return;
+ }
+ singleton.close(monitor);
+
+ }
+
+ /**
+ * Creates a progress monitor dialog under the given shell. It also sets the
+ * dialog's\ message. <code>open</code> is non-blocking.
+ *
+ * @param parentShell
+ * The parent shell, or <code>null</code> to create a top-level
+ * shell.
+ * @param blocking
+ * The monitor that is blocking the job
+ * @param blockingStatus
+ * A status describing why the monitor is blocked
+ */
+ private BlockedJobsDialog(Shell parentShell, IProgressMonitor blocking,
+ IStatus blockingStatus, IProgressService progressService,
+ FinishedJobs finishedJobs, ProgressViewUpdater viewUpdater,
+ ProgressManager progressManager) {
+ super(parentShell == null ? ProgressManagerUtil.getDefaultParent()
+ : parentShell);
+ blockingMonitor = blocking;
+ this.progressService = progressService;
+ this.finishedJobs = finishedJobs;
+ this.progressViewUpdater = viewUpdater;
+ this.progressManager = progressManager;
+ setShellStyle(SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL
+ | SWT.RESIZE | SWT.MAX | getDefaultOrientation());
+ // no close button
+ setBlockOnOpen(false);
+ setMessage(blockingStatus.getMessage());
+ }
+
+ /**
+ * This method creates the dialog area under the parent composite.
+ *
+ * @param parent
+ * The parent Composite.
+ *
+ * @return parent The parent Composite.
+ */
+ protected Control createDialogArea(Composite parent) {
+ setMessage(message);
+ createMessageArea(parent);
+ showJobDetails(parent);
+ return parent;
+ }
+
+ /**
+ * This method creates a dialog area in the parent composite and displays a
+ * progress tree viewer of the running jobs.
+ *
+ * @param parent
+ * The parent Composite.
+ */
+ void showJobDetails(Composite parent) {
+ viewer = new DetailedProgressViewer(parent, SWT.MULTI | SWT.H_SCROLL
+ | SWT.V_SCROLL | SWT.BORDER, progressService, finishedJobs);
+ viewer.setComparator(new ViewerComparator() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public int compare(Viewer testViewer, Object e1, Object e2) {
+ return ((Comparable) e1).compareTo(e2);
+ }
+ });
+ ProgressViewerContentProvider provider = getContentProvider();
+ viewer.setContentProvider(provider);
+ viewer.setInput(provider);
+ viewer.setLabelProvider(new ProgressLabelProvider());
+ GridData data = new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
+ data.horizontalSpan = 2;
+ int heightHint = convertHeightInCharsToPixels(10);
+ data.heightHint = heightHint;
+ viewer.getControl().setLayoutData(data);
+ }
+
+ /**
+ * Return the content provider used for the receiver.
+ *
+ * @return ProgressTreeContentProvider
+ */
+ private ProgressViewerContentProvider getContentProvider() {
+ return new ProgressViewerContentProvider(viewer, finishedJobs,
+ progressViewUpdater, progressManager, true, false) {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressViewerContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ Object[] elements = super.getElements(inputElement);
+ Object[] result = new Object[elements.length + 1];
+ System.arraycopy(elements, 0, result, 1, elements.length);
+ result[0] = blockedElement;
+ return result;
+ }
+ };
+ }
+
+ /**
+ * Clear the cursors in the dialog.
+ */
+ private void clearCursors() {
+ clearCursor(cancelSelected);
+ clearCursor(getShell());
+ if (arrowCursor != null) {
+ arrowCursor.dispose();
+ }
+ if (waitCursor != null) {
+ waitCursor.dispose();
+ }
+ arrowCursor = null;
+ waitCursor = null;
+ }
+
+ /**
+ * Clear the cursor on the supplied control.
+ *
+ * @param control
+ */
+ private void clearCursor(Control control) {
+ if (control != null && !control.isDisposed()) {
+ control.setCursor(null);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(ProgressMessages.BlockedJobsDialog_BlockedTitle);
+ if (waitCursor == null) {
+ waitCursor = new Cursor(shell.getDisplay(), SWT.CURSOR_WAIT);
+ }
+ shell.setCursor(waitCursor);
+ }
+
+ /**
+ * This method sets the message in the message label.
+ *
+ * @param messageString -
+ * the String for the message area
+ */
+ private void setMessage(String messageString) {
+ // must not set null text in a label
+ message = messageString == null ? "" : messageString; //$NON-NLS-1$
+ if (messageLabel == null || messageLabel.isDisposed()) {
+ return;
+ }
+ messageLabel.setText(message);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IconAndMessageDialog#getImage()
+ */
+ protected Image getImage() {
+ return getInfoImage();
+ }
+
+ /**
+ * Returns the progress monitor being used for this dialog. This allows
+ * recursive blockages to also respond to cancelation.
+ *
+ * @return IProgressMonitor
+ */
+ public IProgressMonitor getProgressMonitor() {
+ return blockingMonitor;
+ }
+
+ /**
+ * Requests that the blocked jobs dialog be closed. The supplied monitor
+ * must be the same one that was passed to the createBlockedDialog method.
+ *
+ * @param monitor
+ * @return IProgressMonitor
+ */
+ public boolean close(IProgressMonitor monitor) {
+ // ignore requests to close the dialog from all but the first monitor
+ if (blockingMonitor != monitor) {
+ return false;
+ }
+ return close();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.Dialog#close()
+ */
+ public boolean close() {
+ // Clear the singleton first
+ singleton = null;
+ clearCursors();
+ return super.close();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IconAndMessageDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createButtonBar(Composite parent) {
+ // Do nothing here as we want no buttons
+ return parent;
+ }
+
+ /**
+ * @param taskName
+ * The blockedTaskName to set.
+ */
+ void setBlockedTaskName(String taskName) {
+ this.blockedTaskName = taskName;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ContentProviderFactory.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ContentProviderFactory.java
new file mode 100644
index 0000000..f859a0c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ContentProviderFactory.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.e4.core.di.annotations.Creatable;
+
+@Creatable
+@Singleton
+public class ContentProviderFactory {
+
+ @Inject
+ Services services;
+
+ @PostConstruct
+ void init() {
+ services.registerService(ContentProviderFactory.class, this);
+ }
+
+ public ProgressViewerContentProvider getProgressViewerContentProvider(
+ AbstractProgressViewer structured, boolean debug,
+ boolean showFinished) {
+
+ //TODO E4 workaround for @Creatable problem
+ return new ProgressViewerContentProvider(structured,
+ services.getService(FinishedJobs.class),
+ services.getService(ProgressViewUpdater.class),
+ services.getService(ProgressManager.class), debug, showFinished);
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/DetailedProgressViewer.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/DetailedProgressViewer.java
new file mode 100644
index 0000000..b01901c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/DetailedProgressViewer.java
@@ -0,0 +1,540 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * The DetailedProgressViewer is a viewer that shows the details of all in
+ * progress job or jobs that are finished awaiting user input.
+ *
+ * @since 3.2
+ *
+ */
+public class DetailedProgressViewer extends AbstractProgressViewer {
+
+ //Maximum number of entries to display so that the view does not flood the UI with events
+ private static final int MAX_DISPLAYED = 20;
+
+ Composite control;
+
+ private ScrolledComposite scrolled;
+
+ private Composite noEntryArea;
+
+ private IProgressService progressService;
+
+ private FinishedJobs finishedJobs;
+
+ /**
+ * Create a new instance of the receiver with a control that is a child of
+ * parent with style style.
+ *
+ * @param parent
+ * @param style
+ */
+ public DetailedProgressViewer(Composite parent, int style,
+ IProgressService progressService, FinishedJobs finishedJobs) {
+ this.progressService = progressService;
+ this.finishedJobs = finishedJobs;
+
+ scrolled = new ScrolledComposite(parent, SWT.V_SCROLL | style);
+ int height = JFaceResources.getDefaultFont().getFontData()[0]
+ .getHeight();
+ scrolled.getVerticalBar().setIncrement(height * 2);
+ scrolled.setExpandHorizontal(true);
+ scrolled.setExpandVertical(true);
+
+ control = new Composite(scrolled, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ control.setLayout(layout);
+ control.setBackground(parent.getDisplay().getSystemColor(
+ SWT.COLOR_LIST_BACKGROUND));
+
+ control.addFocusListener(new FocusAdapter() {
+
+ private boolean settingFocus = false;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.FocusAdapter#focusGained(org.eclipse.swt.events.FocusEvent)
+ */
+ public void focusGained(FocusEvent e) {
+ if (!settingFocus) {
+ // Prevent new focus events as a result this update
+ // occurring
+ settingFocus = true;
+ setFocus();
+ settingFocus = false;
+ }
+ }
+ });
+
+ control.addControlListener(new ControlListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
+ */
+ public void controlMoved(ControlEvent e) {
+ updateVisibleItems();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
+ */
+ public void controlResized(ControlEvent e) {
+ updateVisibleItems();
+ }
+ });
+
+ // TODO E4 - missing e4 replacement
+ // PlatformUI.getWorkbench().getHelpSystem().setHelp(control,
+ // IWorkbenchHelpContextIds.RESPONSIVE_UI);
+
+ scrolled.setContent(control);
+ hookControl(control);
+
+ noEntryArea = new Composite(scrolled, SWT.NONE);
+ noEntryArea.setLayout(new GridLayout());
+ noEntryArea.setBackground(noEntryArea.getDisplay()
+ .getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+
+ Text noEntryLabel = new Text(noEntryArea, SWT.SINGLE);
+ noEntryLabel.setText(ProgressMessages.ProgressView_NoOperations);
+ noEntryLabel.setBackground(noEntryArea.getDisplay().getSystemColor(
+ SWT.COLOR_LIST_BACKGROUND));
+ GridData textData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+ noEntryLabel.setLayoutData(textData);
+ noEntryLabel.setEditable(false);
+
+ // TODO E4 - missing e4 replacement
+ // PlatformUI.getWorkbench().getHelpSystem().setHelp(noEntryLabel,
+ // IWorkbenchHelpContextIds.RESPONSIVE_UI);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#add(java.lang.Object[])
+ */
+ public void add(Object[] elements) {
+ ViewerComparator sorter = getComparator();
+
+ // Use a Set in case we are getting something added that exists
+ Set newItems = new HashSet(elements.length);
+
+ Control[] existingChildren = control.getChildren();
+ for (int i = 0; i < existingChildren.length; i++) {
+ if (existingChildren[i].getData() != null)
+ newItems.add(existingChildren[i].getData());
+ }
+
+ for (int i = 0; i < elements.length; i++) {
+ if (elements[i] != null)
+ newItems.add(elements[i]);
+ }
+
+ JobTreeElement[] infos = new JobTreeElement[newItems.size()];
+ newItems.toArray(infos);
+
+ if (sorter != null) {
+ sorter.sort(this, infos);
+ }
+
+ // Update with the new elements to prevent flash
+ for (int i = 0; i < existingChildren.length; i++) {
+ ((ProgressInfoItem) existingChildren[i]).dispose();
+ }
+
+ int totalSize = Math.min(newItems.size(), MAX_DISPLAYED);
+
+ for (int i = 0; i < totalSize; i++) {
+ ProgressInfoItem item = createNewItem(infos[i]);
+ item.setColor(i);
+ }
+
+ control.layout(true);
+ updateForShowingProgress();
+ }
+
+ /**
+ * Update for the progress being displayed.
+ */
+ private void updateForShowingProgress() {
+ if (control.getChildren().length > 0) {
+ scrolled.setContent(control);
+ } else {
+ scrolled.setContent(noEntryArea);
+ }
+ }
+
+ /**
+ * Create a new item for info.
+ *
+ * @param info
+ * @return ProgressInfoItem
+ */
+ private ProgressInfoItem createNewItem(JobTreeElement info) {
+ final ProgressInfoItem item = new ProgressInfoItem(control, SWT.NONE,
+ info, progressService, finishedJobs);
+
+ item.setIndexListener(new ProgressInfoItem.IndexListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#selectNext()
+ */
+ public void selectNext() {
+ DetailedProgressViewer.this.selectNext(item);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#selectPrevious()
+ */
+ public void selectPrevious() {
+ DetailedProgressViewer.this.selectPrevious(item);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressInfoItem.IndexListener#select()
+ */
+ public void select() {
+
+ Control[] children = control.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ ProgressInfoItem child = (ProgressInfoItem) children[i];
+ if (!item.equals(child)) {
+ child.selectWidgets(false);
+ }
+ }
+ item.selectWidgets(true);
+
+ }
+ });
+
+ // Refresh to populate with the current tasks
+ item.refresh();
+ return item;
+ }
+
+ /**
+ * Select the previous item in the receiver.
+ *
+ * @param item
+ */
+ protected void selectPrevious(ProgressInfoItem item) {
+ Control[] children = control.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ ProgressInfoItem child = (ProgressInfoItem) children[i];
+ if (item.equals(child)) {
+ ProgressInfoItem previous;
+ if (i == 0) {
+ previous = (ProgressInfoItem) children[children.length - 1];
+ } else {
+ previous = (ProgressInfoItem) children[i - 1];
+ }
+
+ item.selectWidgets(false);
+ previous.selectWidgets(true);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Select the next item in the receiver.
+ *
+ * @param item
+ */
+ protected void selectNext(ProgressInfoItem item) {
+ Control[] children = control.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ ProgressInfoItem child = (ProgressInfoItem) children[i];
+ if (item.equals(child)) {
+ ProgressInfoItem next;
+ if (i == children.length - 1) {
+ next = (ProgressInfoItem) children[0];
+ } else {
+ next = (ProgressInfoItem) children[i + 1];
+ }
+ item.selectWidgets(false);
+ next.selectWidgets(true);
+
+ return;
+ }
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
+ */
+ protected Widget doFindInputItem(Object element) {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
+ */
+ protected Widget doFindItem(Object element) {
+ Control[] existingChildren = control.getChildren();
+ for (int i = 0; i < existingChildren.length; i++) {
+ if (existingChildren[i].isDisposed()
+ || existingChildren[i].getData() == null) {
+ continue;
+ }
+ if (existingChildren[i].getData().equals(element)) {
+ return existingChildren[i];
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
+ * java.lang.Object, boolean)
+ */
+ protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+ if (usingElementMap()) {
+ unmapElement(item);
+ }
+ item.dispose();
+ add(new Object[] { element });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.Viewer#getControl()
+ */
+ public Control getControl() {
+ return scrolled;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
+ */
+ protected List getSelectionFromWidget() {
+ return new ArrayList(0);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
+ * java.lang.Object)
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ super.inputChanged(input, oldInput);
+ refreshAll();
+ updateForShowingProgress();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
+ */
+ protected void internalRefresh(Object element) {
+ if (element == null) {
+ return;
+ }
+
+ if (element.equals(getRoot())) {
+ refreshAll();
+ return;
+ }
+ Widget widget = findItem(element);
+ if (widget == null) {
+ add(new Object[] { element });
+ return;
+ }
+ ((ProgressInfoItem) widget).refresh();
+
+ // Update the minimum size
+ Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ size.x += IDialogConstants.HORIZONTAL_SPACING;
+ size.y += IDialogConstants.VERTICAL_SPACING;
+
+ scrolled.setMinSize(size);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#remove(java.lang.Object[])
+ */
+ public void remove(Object[] elements) {
+
+ for (int i = 0; i < elements.length; i++) {
+ JobTreeElement treeElement = (JobTreeElement) elements[i];
+ // Make sure we are not keeping this one
+ if (finishedJobs.isKept(treeElement)) {
+ Widget item = doFindItem(elements[i]);
+ if (item != null) {
+ ((ProgressInfoItem) item).refresh();
+ }
+
+ } else {
+ Widget item = doFindItem(treeElement);
+ if (item == null) {
+ // Is the parent showing?
+ Object parent = treeElement.getParent();
+ if (parent != null)
+ item = doFindItem(parent);
+ }
+ if (item != null) {
+ unmapElement(elements[i]);
+ item.dispose();
+ }
+ }
+ }
+
+ Control[] existingChildren = control.getChildren();
+ for (int i = 0; i < existingChildren.length; i++) {
+ ProgressInfoItem item = (ProgressInfoItem) existingChildren[i];
+ item.setColor(i);
+ }
+ control.layout(true);
+ updateForShowingProgress();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
+ */
+ public void reveal(Object element) {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
+ * boolean)
+ */
+ protected void setSelectionToWidget(List l, boolean reveal) {
+
+ }
+
+ /**
+ * Cancel the current selection
+ *
+ */
+ public void cancelSelection() {
+
+ }
+
+ /**
+ * Set focus on the current selection.
+ *
+ */
+ public void setFocus() {
+ Control[] children = control.getChildren();
+ if (children.length > 0) {
+ ((ProgressInfoItem)children[0]).setButtonFocus();
+ } else {
+ noEntryArea.setFocus();
+ }
+ }
+
+ /**
+ * Refresh everything as the root is being refreshed.
+ */
+ private void refreshAll() {
+
+ Object[] infos = getSortedChildren(getRoot());
+ Control[] existingChildren = control.getChildren();
+
+ for (int i = 0; i < existingChildren.length; i++) {
+ existingChildren[i].dispose();
+
+ }
+
+ int maxLength = Math.min(infos.length,MAX_DISPLAYED);
+ // Create new ones if required
+ for (int i = 0; i < maxLength; i++) {
+ ProgressInfoItem item = createNewItem((JobTreeElement) infos[i]);
+ item.setColor(i);
+ }
+
+ control.layout(true);
+ updateForShowingProgress();
+
+ }
+
+ /**
+ * Set the virtual items to be visible or not depending on the displayed
+ * area.
+ */
+ private void updateVisibleItems() {
+ Control[] children = control.getChildren();
+ int top = scrolled.getOrigin().y;
+ int bottom = top + scrolled.getParent().getBounds().height;
+ for (int i = 0; i < children.length; i++) {
+ ProgressInfoItem item = (ProgressInfoItem) children[i];
+ item.setDisplayed(top, bottom);
+
+ }
+ }
+
+ public ProgressInfoItem[] getProgressInfoItems() {
+ Control[] children = control.getChildren();
+ ProgressInfoItem[] progressInfoItems = new ProgressInfoItem[children.length];
+ System.arraycopy(children, 0, progressInfoItems, 0, children.length);
+ return progressInfoItems;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ErrorInfo.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ErrorInfo.java
new file mode 100644
index 0000000..47445b7
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ErrorInfo.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import com.ibm.icu.text.DateFormat;
+import java.util.Date;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * ErrorInfo is the info that displays errors.
+ */
+public class ErrorInfo extends JobTreeElement {
+
+ private final IStatus errorStatus;
+
+ private final Job job;
+
+ private final long timestamp;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param status
+ * @param job
+ * The Job to create
+ */
+ public ErrorInfo(IStatus status, Job job) {
+ errorStatus = status;
+ this.job = job;
+ timestamp = System.currentTimeMillis();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren()
+ */
+ boolean hasChildren() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren()
+ */
+ Object[] getChildren() {
+ return ProgressManagerUtil.EMPTY_OBJECT_ARRAY;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString()
+ */
+ String getDisplayString() {
+ return NLS.bind(ProgressMessages.JobInfo_Error, (new Object[] {
+ job.getName(),
+ DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG).format(new Date(timestamp)) }));
+ }
+
+ /**
+ * Return the image for the receiver.
+ *
+ * @return Image
+ */
+ Image getImage() {
+ return JFaceResources.getImage(ProgressManager.ERROR_JOB_KEY);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ boolean isJobInfo() {
+ return false;
+ }
+
+ /**
+ * Return the current status of the receiver.
+ *
+ * @return IStatus
+ */
+ IStatus getErrorStatus() {
+ return errorStatus;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive()
+ */
+ boolean isActive() {
+ return true;
+ }
+
+ /**
+ * Return the job that generated the error.
+ *
+ * @return the job that generated the error
+ */
+ public Job getJob() {
+ return job;
+ }
+
+ /**
+ * Return the timestamp for the job.
+ *
+ * @return long
+ */
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object arg0) {
+ if (arg0 instanceof ErrorInfo) {
+ // Order ErrorInfo by time received
+ long otherTimestamp = ((ErrorInfo) arg0).timestamp;
+ if (timestamp < otherTimestamp) {
+ return -1;
+ } else if (timestamp > otherTimestamp) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ return super.compareTo(arg0);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/FinishedJobs.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/FinishedJobs.java
new file mode 100644
index 0000000..d148d4f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/FinishedJobs.java
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.core.commands.common.EventManager;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.progress.IDisposableAction;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+
+/**
+ * This singleton remembers all JobTreeElements that should be preserved (e.g.
+ * because their associated Jobs have the "keep" property set).
+ */
+@Creatable
+@Singleton
+public class FinishedJobs extends EventManager {
+
+ /*
+ * Interface for notify listeners.
+ */
+ static interface KeptJobsListener {
+
+ /**
+ * A job to be kept has finished
+ *
+ * @param jte
+ */
+ void finished(JobTreeElement jte);
+
+ /**
+ * A kept job has been removed.
+ *
+ * @param jte
+ */
+ void removed(JobTreeElement jte);
+ }
+
+ private IJobProgressManagerListener listener;
+
+ private HashSet keptjobinfos = new HashSet();
+
+ private HashMap finishedTime = new HashMap();
+
+ private static JobTreeElement[] EMPTY_INFOS;
+
+ @Inject
+ ProgressManager progressManager;
+
+ @PostConstruct
+ void init(MApplication application) {
+ progressManager.addListener(listener);
+ EMPTY_INFOS = new JobTreeElement[0];
+ // TODO E4 workaround for @creatable problem
+ application.getContext().set(FinishedJobs.class, this);
+ }
+
+ public FinishedJobs() {
+ listener = new IJobProgressManagerListener() {
+ public void addJob(JobInfo info) {
+ checkForDuplicates(info);
+ }
+
+ public void addGroup(GroupInfo info) {
+ checkForDuplicates(info);
+ }
+
+ public void refreshJobInfo(JobInfo info) {
+ checkTasks(info);
+ }
+
+ public void refreshGroup(GroupInfo info) {
+ }
+
+ public void refreshAll() {
+ }
+
+ public void removeJob(JobInfo info) {
+ if (keep(info)) {
+ checkForDuplicates(info);
+ add(info);
+ }
+ }
+
+ public void removeGroup(GroupInfo group) {
+ }
+
+ public boolean showsDebug() {
+ return false;
+ }
+ };
+ }
+
+ /**
+ * Returns true if JobInfo indicates that it must be kept.
+ */
+ static boolean keep(JobInfo info) {
+ Job job = info.getJob();
+ if (job != null) {
+ Object prop = job.getProperty(ProgressManagerUtil.KEEP_PROPERTY);
+ if (prop instanceof Boolean) {
+ if (((Boolean) prop).booleanValue()) {
+ return true;
+ }
+ }
+
+ prop = job.getProperty(ProgressManagerUtil.KEEPONE_PROPERTY);
+ if (prop instanceof Boolean) {
+ if (((Boolean) prop).booleanValue()) {
+ return true;
+ }
+ }
+
+ IStatus status = job.getResult();
+ if (status != null && status.getSeverity() == IStatus.ERROR) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Register for notification.
+ */
+ void addListener(KeptJobsListener l) {
+ addListenerObject(l);
+ }
+
+ /**
+ * Deregister for notification.
+ */
+ void removeListener(KeptJobsListener l) {
+ removeListenerObject(l);
+ }
+
+ private void checkForDuplicates(GroupInfo info) {
+ Object[] objects = info.getChildren();
+ for (int i = 0; i < objects.length; i++) {
+ if (objects[i] instanceof JobInfo) {
+ checkForDuplicates((JobInfo) objects[i]);
+ }
+ }
+ }
+
+ private void checkForDuplicates(JobTreeElement info) {
+ JobTreeElement[] toBeRemoved = findJobsToRemove(info);
+ if (toBeRemoved != null) {
+ for (int i = 0; i < toBeRemoved.length; i++) {
+ remove(toBeRemoved[i]);
+ }
+ }
+ }
+
+ /**
+ * Add given Job to list of kept jobs.
+ */
+ private void add(JobInfo info) {
+ boolean fire = false;
+
+ synchronized (keptjobinfos) {
+ if (!keptjobinfos.contains(info)) {
+ keptjobinfos.add(info);
+
+ long now = System.currentTimeMillis();
+ finishedTime.put(info, new Long(now));
+
+ Object parent = info.getParent();
+ if (!(parent == null || keptjobinfos.contains(parent))) {
+ keptjobinfos.add(parent);
+ finishedTime.put(parent, new Long(now));
+ }
+
+ fire = true;
+ }
+ }
+
+ if (fire) {
+ Object l[] = getListeners();
+ for (int i = 0; i < l.length; i++) {
+ KeptJobsListener jv = (KeptJobsListener) l[i];
+ jv.finished(info);
+ }
+ }
+ }
+
+ static void disposeAction(JobTreeElement jte) {
+ if (jte.isJobInfo()) {
+ JobInfo ji = (JobInfo) jte;
+ Job job = ji.getJob();
+ if (job != null) {
+ Object prop = job
+ .getProperty(IProgressConstants.ACTION_PROPERTY);
+ if (prop instanceof IDisposableAction) {
+ ((IDisposableAction) prop).dispose();
+ }
+ }
+ }
+ }
+
+ private JobTreeElement[] findJobsToRemove(JobTreeElement info) {
+
+ if (info.isJobInfo()) {
+ Job myJob = ((JobInfo) info).getJob();
+
+ if (myJob != null) {
+
+ Object prop = myJob
+ .getProperty(ProgressManagerUtil.KEEPONE_PROPERTY);
+ if (prop instanceof Boolean && ((Boolean) prop).booleanValue()) {
+ ArrayList found = null;
+ JobTreeElement[] all;
+ synchronized (keptjobinfos) {
+ all = (JobTreeElement[]) keptjobinfos
+ .toArray(new JobTreeElement[keptjobinfos.size()]);
+ }
+ for (int i = 0; i < all.length; i++) {
+ JobTreeElement jte = all[i];
+ if (jte != info && jte.isJobInfo()) {
+ Job job = ((JobInfo) jte).getJob();
+ if (job != null && job != myJob
+ && job.belongsTo(myJob)) {
+ if (found == null) {
+ found = new ArrayList();
+ }
+ found.add(jte);
+ }
+ }
+ }
+ if (found != null) {
+ return (JobTreeElement[]) found
+ .toArray(new JobTreeElement[found.size()]);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private void checkTasks(JobInfo info) {
+ if (keep(info)) {
+ TaskInfo tinfo = info.getTaskInfo();
+ if (tinfo != null) {
+ JobTreeElement[] toBeRemoved = null;
+ boolean fire = false;
+ JobTreeElement element = (JobTreeElement) tinfo.getParent();
+ synchronized (keptjobinfos) {
+ if (element == info && !keptjobinfos.contains(tinfo)) {
+ toBeRemoved = findJobsToRemove(element);
+ keptjobinfos.add(tinfo);
+ finishedTime.put(tinfo, new Long(System
+ .currentTimeMillis()));
+ }
+ }
+
+ if (toBeRemoved != null) {
+ for (int i = 0; i < toBeRemoved.length; i++) {
+ remove(toBeRemoved[i]);
+ }
+ }
+
+ if (fire) {
+ Object l[] = getListeners();
+ for (int i = 0; i < l.length; i++) {
+ KeptJobsListener jv = (KeptJobsListener) l[i];
+ jv.finished(info);
+ }
+ }
+ }
+ }
+ }
+
+ public void removeErrorJobs() {
+ JobTreeElement[] infos = getKeptElements();
+ for (int i = 0; i < infos.length; i++) {
+ if (infos[i].isJobInfo()) {
+ JobInfo info1 = (JobInfo) infos[i];
+ Job job = info1.getJob();
+ if (job != null) {
+ IStatus status = job.getResult();
+ if (status != null && status.getSeverity() == IStatus.ERROR) {
+ JobTreeElement topElement = (JobTreeElement) info1
+ .getParent();
+ if (topElement == null) {
+ topElement = info1;
+ }
+ remove(topElement);
+ }
+ }
+ }
+ }
+ }
+
+ boolean remove(JobTreeElement jte) {
+ boolean fire = false;
+ boolean removed = false;
+
+ synchronized (keptjobinfos) {
+ if (keptjobinfos.remove(jte)) {
+ removed = true;
+ finishedTime.remove(jte);
+ disposeAction(jte);
+
+ // delete all elements that have jte as their direct or indirect
+ // parent
+ JobTreeElement jtes[] = (JobTreeElement[]) keptjobinfos
+ .toArray(new JobTreeElement[keptjobinfos.size()]);
+ for (int i = 0; i < jtes.length; i++) {
+ JobTreeElement parent = (JobTreeElement) jtes[i]
+ .getParent();
+ if (parent != null) {
+ if (parent == jte || parent.getParent() == jte) {
+ if (keptjobinfos.remove(jtes[i])) {
+ disposeAction(jtes[i]);
+ }
+ finishedTime.remove(jtes[i]);
+ }
+ }
+ }
+ fire = true;
+ }
+ }
+
+ if (fire) {
+ // notify listeners
+ Object l[] = getListeners();
+ for (int i = 0; i < l.length; i++) {
+ KeptJobsListener jv = (KeptJobsListener) l[i];
+ jv.removed(jte);
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Returns all kept elements.
+ */
+ JobTreeElement[] getKeptElements() {
+ JobTreeElement[] all;
+ if (keptjobinfos.isEmpty()) {
+ return EMPTY_INFOS;
+ }
+
+ synchronized (keptjobinfos) {
+ all = (JobTreeElement[]) keptjobinfos
+ .toArray(new JobTreeElement[keptjobinfos.size()]);
+ }
+
+ return all;
+ }
+
+ /**
+ * Get the date that indicates the finish time.
+ *
+ * @param jte
+ * @return Date
+ */
+ public Date getFinishDate(JobTreeElement jte) {
+ Object o = finishedTime.get(jte);
+ if (o instanceof Long) {
+ return new Date(((Long) o).longValue());
+ }
+ return null;
+ }
+
+ /**
+ * Return whether or not the kept infos have the element.
+ *
+ * @param element
+ * @return boolean
+ */
+ public boolean isKept(JobTreeElement element) {
+ return keptjobinfos.contains(element);
+ }
+
+ /**
+ * Clear all kept jobs.
+ */
+ public void clearAll() {
+ synchronized (keptjobinfos) {
+ JobTreeElement[] all = (JobTreeElement[]) keptjobinfos
+ .toArray(new JobTreeElement[keptjobinfos.size()]);
+ for (int i = 0; i < all.length; i++) {
+ disposeAction(all[i]);
+ }
+ keptjobinfos.clear();
+ finishedTime.clear();
+ }
+
+ // notify listeners
+ Object l[] = getListeners();
+ for (int i = 0; i < l.length; i++) {
+ KeptJobsListener jv = (KeptJobsListener) l[i];
+ jv.removed(null);
+ }
+ }
+
+ /**
+ * Return the set of kept jobs.
+ * @return Set
+ */
+ Set getKeptAsSet() {
+ return keptjobinfos;
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/GroupInfo.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/GroupInfo.java
new file mode 100644
index 0000000..d94b658
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/GroupInfo.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Michael Fraenkel <fraenkel@us.ibm.com> - Fix for bug 60698 -
+ * [Progress] ConcurrentModificationException in NewProgressViewer.
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * The GroupInfo is the object used to display group properties.
+ */
+
+class GroupInfo extends JobTreeElement implements IProgressMonitor {
+
+ private List infos = new ArrayList();
+
+ private Object lock = new Object();
+
+ private String taskName = ProgressMessages.SubTaskInfo_UndefinedTaskName;
+
+ boolean isActive = false;
+
+ double total = -1;
+
+ double currentWork;
+
+ private ProgressManager progressManager;
+
+ private FinishedJobs finishedJobs;
+
+ public GroupInfo(ProgressManager progressManager, FinishedJobs finishedJobs) {
+ this.progressManager = progressManager;
+ this.finishedJobs = finishedJobs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren()
+ */
+ boolean hasChildren() {
+ synchronized (lock) {
+ return !infos.isEmpty();
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren()
+ */
+ Object[] getChildren() {
+ synchronized (lock) {
+ return infos.toArray();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString()
+ */
+ String getDisplayString() {
+ if (total < 0) {
+ return taskName;
+ }
+ String[] messageValues = new String[2];
+ messageValues[0] = taskName;
+ messageValues[1] = String.valueOf(getPercentDone());
+ return NLS.bind(ProgressMessages.JobInfo_NoTaskNameDoneMessage,
+ messageValues);
+
+ }
+
+ /**
+ * Return an integer representing the amount of work completed.
+ *
+ * @return int
+ */
+ int getPercentDone() {
+ return (int) (currentWork * 100 / total);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ boolean isJobInfo() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(String name, int totalWork) {
+ if (name == null)
+ name = ProgressMessages.SubTaskInfo_UndefinedTaskName;
+ else
+ taskName = name;
+ total = totalWork;
+ synchronized (lock) {
+ isActive = true;
+ }
+ progressManager.refreshGroup(this);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#done()
+ */
+ public void done() {
+ synchronized (lock) {
+ isActive = false;
+ }
+ updateInProgressManager();
+
+ }
+
+ /**
+ * Update the receiver in the progress manager. If all of the jobs are
+ * finished and the receiver is not being kept then remove it.
+ */
+ private void updateInProgressManager() {
+ Iterator infoIterator = infos.iterator();
+ while (infoIterator.hasNext()) {
+ JobInfo next = (JobInfo) infoIterator.next();
+ if (!(next.getJob().getState() == Job.NONE)) {
+ progressManager.refreshGroup(this);
+ return;
+ }
+ }
+
+ if (finishedJobs.isKept(this))
+ progressManager.refreshGroup(this);
+ else
+ progressManager.removeGroup(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(double work) {
+ synchronized (lock) {
+ currentWork += work;
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
+ */
+ public boolean isCanceled() {
+ // Just a group so no cancel state
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
+ */
+ public void setCanceled(boolean value) {
+ cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
+ */
+ public void setTaskName(String name) {
+ synchronized (this) {
+ isActive = true;
+ }
+ if (name == null)
+ taskName = ProgressMessages.SubTaskInfo_UndefinedTaskName;
+ else
+ taskName = name;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
+ */
+ public void subTask(String name) {
+ // Not interesting for this monitor
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ internalWorked(work);
+ }
+
+ /**
+ * Remove the job from the list of jobs.
+ *
+ * @param job
+ */
+ void removeJobInfo(final JobInfo job) {
+ synchronized (lock) {
+ infos.remove(job);
+ if (infos.isEmpty()) {
+ done();
+ }
+ }
+ }
+
+ /**
+ * Remove the job from the list of jobs.
+ *
+ * @param job
+ */
+ void addJobInfo(final JobInfo job) {
+ synchronized (lock) {
+ infos.add(job);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive()
+ */
+ boolean isActive() {
+ return isActive;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#cancel()
+ */
+ public void cancel() {
+ Object[] jobInfos = getChildren();
+ for (int i = 0; i < jobInfos.length; i++) {
+ ((JobInfo) jobInfos[i]).cancel();
+ }
+ // Call the refresh so that this is updated immediately
+ updateInProgressManager();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isCancellable()
+ */
+ public boolean isCancellable() {
+ return true;
+ }
+
+ /**
+ * Get the task name for the receiver.
+ *
+ * @return String
+ */
+ String getTaskName() {
+ return taskName;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IAnimationProcessor.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IAnimationProcessor.java
new file mode 100644
index 0000000..f526781
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IAnimationProcessor.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * The IAnimationProcessor is the class that handles the animation of
+ * the animation item.
+ */
+interface IAnimationProcessor {
+
+ /**
+ * Add an item to the list of the items we are updating.
+ * @param item
+ */
+ void addItem(AnimationItem item);
+
+ /**
+ * Remove an item from the list of the items we are updating.
+ * @param item
+ */
+ void removeItem(AnimationItem item);
+
+ /**
+ * Return whether or not the receiver has any items.
+ * @return
+ */
+ boolean hasItems();
+
+ /**
+ * Animation has begun. Inform any listeners. This is called
+ * from the UI Thread.
+ */
+ void animationStarted();
+
+ /**
+ * Animation has finished. Inform any listeners. This is called
+ * from the UI Thread.
+ */
+ void animationFinished();
+
+ /**
+ * Get the preferred width of the types of items this
+ * processor manages.
+ * @return
+ */
+ int getPreferredWidth();
+
+ /**
+ * Return whether or not this is a job used by the processor.
+ * @param job
+ * @return
+ */
+ boolean isProcessorJob(Job job);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobBusyListener.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobBusyListener.java
new file mode 100644
index 0000000..36f7c0b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobBusyListener.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * The IJobBusyListener is used to listen for running and
+ * terminating of jobs of a particular family.
+ */
+interface IJobBusyListener {
+
+ /**
+ * Increment the busy count for job.
+ * @param job
+ */
+ public void incrementBusy(Job job);
+
+ /**
+ * Decrement the busy count for job.
+ * @param job
+ */
+ public void decrementBusy(Job job);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobProgressManagerListener.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobProgressManagerListener.java
new file mode 100644
index 0000000..871640f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IJobProgressManagerListener.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+/**
+ * The IJobProgressManagerListener is a class that listeners to the JobProgressManager.
+ */
+interface IJobProgressManagerListener {
+
+ /**
+ * Refresh the viewer as a result of an addition of info.
+ * @param info
+ */
+ void addJob(final JobInfo info);
+
+ /**
+ * Refresh the viewer as a result of an addition of group.
+ * @param info
+ */
+ void addGroup(final GroupInfo info);
+
+ /**
+ * Refresh the IJobProgressManagerListeners as a result of a change in info.
+ * @param info
+ */
+ public void refreshJobInfo(JobInfo info);
+
+ /**
+ * Refresh the IJobProgressManagerListeners as a result of a change in groups.
+ * @param info
+ */
+ public void refreshGroup(GroupInfo info);
+
+ /**
+ * Refresh the viewer for all jobs.
+ * @param info
+ */
+ void refreshAll();
+
+ /**
+ * Refresh the viewer as a result of a removal of info.
+ * @param info
+ */
+ void removeJob(final JobInfo info);
+
+ /**
+ * Refresh the viewer as a result of a removal of group.
+ * @param info
+ */
+ void removeGroup(final GroupInfo group);
+
+ /**
+ * Return whether or not this listener shows debug information.
+ * @return boolean
+ */
+ boolean showsDebug();
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IProgressUpdateCollector.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IProgressUpdateCollector.java
new file mode 100644
index 0000000..3ebd422
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/IProgressUpdateCollector.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+/**
+ * The IProgressUpdateCollector is the interface that content providers
+ * conform to in order that the ProgressViewUpdater can talk to various
+ * types of content provider.
+ */
+public interface IProgressUpdateCollector {
+
+ /**
+ * Refresh the viewer.
+ */
+ void refresh();
+
+ /**
+ * Refresh the elements.
+ * @param elements
+ */
+ void refresh(Object[] elements);
+
+ /**
+ * Add the elements.
+ * @param elements Array of JobTreeElement
+ */
+ void add(Object[] elements);
+
+ /**
+ * Remove the elements.
+ * @param elements Array of JobTreeElement
+ */
+ void remove(Object[] elements);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ImageTools.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ImageTools.java
new file mode 100644
index 0000000..702d876
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ImageTools.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import java.net.URL;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+public class ImageTools {
+
+ private static final String ICONS_LOCATION = "/icons/full/";
+
+ protected static ImageTools instance;
+
+ private ImageRegistry imageRegistry = JFaceResources.getImageRegistry();
+
+ public static ImageTools getInstance() {
+ if (instance == null) {
+ instance = new ImageTools();
+ }
+ return instance;
+ }
+
+ public ImageDescriptor getImageDescriptor(
+ String relativePath) {
+ //TODO E4 - the only place that requires org.eclipse.core.runtime
+ URL url = FileLocator.find(Platform
+ .getBundle(IProgressConstants.PLUGIN_ID), new Path(
+ ICONS_LOCATION + relativePath), null);
+ return ImageDescriptor.createFromURL(url);
+ }
+
+ public Image getImage(String relativePath, Display display) {
+ return getImageDescriptor(
+ relativePath).createImage(display);
+ }
+
+ public void putIntoRegistry(String name, String relativePath) {
+ imageRegistry.put(name, getImageDescriptor(relativePath));
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfo.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfo.java
new file mode 100644
index 0000000..00845c3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfo.java
@@ -0,0 +1,478 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Brock Janiczak <brockj@tpg.com.au> - Fix for Bug 123169 [Progress] NPE from JobInfo
+ * Martin W. Kirst <martin.kirst@s1998.tu-chemnitz.de> - jUnit test for Bug 361121 [Progress] DetailedProgressViewer's comparator violates its general contract
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * JobInfo is the class that keeps track of the tree structure for objects that
+ * display job status in a tree.
+ */
+public class JobInfo extends JobTreeElement {
+
+ private IStatus blockedStatus;
+
+ private volatile boolean canceled = false;
+ private List children = Collections.synchronizedList(new ArrayList());
+
+ private Job job;
+
+ private GroupInfo parent;
+
+ private TaskInfo taskInfo;
+
+ private ProgressManager progressManager;
+
+ private FinishedJobs finishedJobs;
+
+ //Default to no progress
+ private int ticks = -1;
+
+ /**
+ * Create a top level JobInfo.
+ *
+ * @param enclosingJob
+ */
+ protected JobInfo(Job enclosingJob, ProgressManager progressManager,
+ FinishedJobs finishedJobs) {
+ this.job = enclosingJob;
+ this.progressManager = progressManager;
+ this.finishedJobs = finishedJobs;
+ }
+
+ /**
+ * Add the subtask to the receiver.
+ *
+ * @param subTaskName
+ */
+ void addSubTask(String subTaskName) {
+ children.add(new SubTaskInfo(this, subTaskName));
+ }
+
+ /**
+ * Add the amount of work to the job info.
+ *
+ * @param workIncrement
+ */
+ void addWork(double workIncrement) {
+ if (taskInfo == null) {
+ return;
+ }
+ if (parent == null || ticks < 1) {
+ taskInfo.addWork(workIncrement);
+ } else {
+ taskInfo.addWork(workIncrement, parent, ticks);
+ }
+ }
+
+ /**
+ * Begin the task called taskName with the supplied work.
+ *
+ * @param taskName
+ * @param work
+ */
+ void beginTask(String taskName, int work) {
+ taskInfo = new TaskInfo(this, taskName, work);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#cancel()
+ */
+ public void cancel() {
+ this.canceled = true;
+ this.job.cancel();
+ //Call the refresh so that this is updated immediately
+ progressManager.refreshJobInfo(this);
+ }
+
+ /**
+ * Clear the collection of subtasks an the task info.
+ */
+ void clearChildren() {
+ children.clear();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ void clearTaskInfo() {
+ finishedJobs.remove(taskInfo);
+ taskInfo = null;
+ }
+
+ /**
+ * Compare the the job of the receiver to job2.
+ *
+ * @param jobInfo
+ * The info we are comparing to
+ * @return @see Comparable#compareTo(java.lang.Object)
+ */
+ private int compareJobs(JobInfo jobInfo) {
+
+ Job job2 = jobInfo.getJob();
+
+ //User jobs have top priority
+ if (job.isUser()) {
+ if (!job2.isUser()) {
+ return -1;
+ }
+ } else {
+ if (job2.isUser()) {
+ return 1;
+ }
+ }
+
+ //Show the blocked ones last
+ if (isBlocked()) {
+ if (!jobInfo.isBlocked()) {
+ return 1;
+ }
+ } else {
+ if (jobInfo.isBlocked()) {
+ return -1;
+ }
+ }
+
+ int thisPriority = job.getPriority();
+ int otherPriority = job2.getPriority();
+ // If equal prio, order by names
+ if (thisPriority == otherPriority) {
+ return job.getName().compareTo(job2.getName());
+ }
+
+ // order by priority
+ if (thisPriority > otherPriority) {
+ return -1;
+ }
+ return 1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object arg0) {
+
+ if (!(arg0 instanceof JobInfo)) {
+ return super.compareTo(arg0);
+ }
+ JobInfo element = (JobInfo) arg0;
+
+ boolean thisCanceled = isCanceled();
+ boolean anotherCanceled = element.isCanceled();
+ if (thisCanceled && !anotherCanceled) {
+ // If the receiver is cancelled then it is lowest priority
+ return 1;
+ } else if (!thisCanceled && anotherCanceled) {
+ return -1;
+ }
+
+ int thisState = getJob().getState();
+ int anotherState = element.getJob().getState();
+
+ // if equal job state, compare other job attributes
+ if (thisState == anotherState) {
+ return compareJobs(element);
+ }
+
+ // ordering by job states, Job.RUNNING should be ordered first
+ return (thisState > anotherState ? -1 : (thisState == anotherState ? 0 : 1));
+ }
+
+ /**
+ * Dispose of the receiver.
+ */
+ void dispose() {
+ if (parent != null) {
+ parent.removeJobInfo(this);
+ }
+ }
+
+ /**
+ * Return the blocked status or <code>null</code> if there isn't one.
+ *
+ * @return Returns the blockedStatus.
+ */
+ public IStatus getBlockedStatus() {
+ return blockedStatus;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren()
+ */
+ Object[] getChildren() {
+ return children.toArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getCondensedDisplayString()
+ */
+ String getCondensedDisplayString() {
+ TaskInfo info = getTaskInfo();
+ if (info != null) {
+ return info.getDisplayStringWithoutTask(true);
+ }
+ return getJob().getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayImage()
+ */
+ public Image getDisplayImage() {
+ int done = getPercentDone();
+ if (done > 0) {
+ return super.getDisplayImage();
+ }
+ if (isBlocked()) {
+ return JFaceResources.getImage(ProgressManager.BLOCKED_JOB_KEY);
+ }
+ int state = getJob().getState();
+ if (state == Job.SLEEPING) {
+ return JFaceResources.getImage(ProgressManager.SLEEPING_JOB_KEY);
+ }
+ if (state == Job.WAITING) {
+ return JFaceResources.getImage(ProgressManager.WAITING_JOB_KEY);
+ }
+ //By default return the first progress image
+ return super.getDisplayImage();
+
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString()
+ */
+ String getDisplayString() {
+ return getDisplayString(true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString(boolean)
+ */
+ String getDisplayString(boolean showProgress) {
+ String name = getDisplayStringWithStatus(showProgress);
+ if (job.isSystem()) {
+ return NLS.bind(ProgressMessages.JobInfo_System, (new Object[] { name }));
+ }
+ return name;
+ }
+
+ /**
+ * Get the display string based on the current status and the name of the
+ * job.
+ * @param showProgress a boolean to indicate if we should
+ * show progress or not.
+ *
+ * @return String
+ */
+ private String getDisplayStringWithStatus(boolean showProgress) {
+ if (isCanceled()) {
+ return NLS.bind(ProgressMessages.JobInfo_Cancelled, (new Object[] { getJob().getName() }));
+ }
+ if (isBlocked()) {
+ return NLS.bind(ProgressMessages.JobInfo_Blocked, (new Object[] { getJob().getName(),
+ blockedStatus.getMessage() }));
+ }
+ if (getJob().getState() == Job.RUNNING) {
+ TaskInfo info = getTaskInfo();
+ if (info == null) {
+ return getJob().getName();
+ }
+ return info.getDisplayString(showProgress);
+ }
+ if (getJob().getState() == Job.SLEEPING) {
+ return NLS.bind(ProgressMessages.JobInfo_Sleeping, (new Object[] { getJob().getName() }));
+ }
+
+ return NLS.bind(ProgressMessages.JobInfo_Waiting, (new Object[] { getJob().getName() }));
+
+ }
+
+ /**
+ * Return the GroupInfo for the receiver if it' is active.
+ *
+ * @return GroupInfo or <code>null</code>.
+ */
+ GroupInfo getGroupInfo() {
+ if (parent != null) {
+ return parent;
+ }
+ return null;
+ }
+
+ /**
+ * Return the job that the receiver is collecting data on.
+ *
+ * @return Job
+ */
+ public Job getJob() {
+ return job;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getParent()
+ */
+ public Object getParent() {
+ return parent;
+ }
+
+ /**
+ * Return the amount of progress we have had as a percentage. If there is no
+ * progress or it is indeterminate return IProgressMonitor.UNKNOWN.
+ *
+ * @return int
+ */
+ int getPercentDone() {
+ TaskInfo info = getTaskInfo();
+ if (info != null){
+ if(info.totalWork == IProgressMonitor.UNKNOWN) {
+ return IProgressMonitor.UNKNOWN;
+ }
+ if(info.totalWork == 0) {
+ return 0;
+ }
+ return (int) info.preWork * 100 / info.totalWork;
+ }
+ return IProgressMonitor.UNKNOWN;
+ }
+
+ /**
+ * @return Returns the taskInfo.
+ */
+ TaskInfo getTaskInfo() {
+ return taskInfo;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren()
+ */
+ boolean hasChildren() {
+ return children.size() > 0;
+ }
+
+ /**
+ * Return whether or not there is a task.
+ *
+ * @return boolean
+ */
+ boolean hasTaskInfo() {
+ return taskInfo != null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive()
+ */
+ boolean isActive() {
+ return getJob().getState() != Job.NONE;
+ }
+
+ /**
+ * Return whether or not the receiver is blocked.
+ *
+ * @return boolean <code>true</code> if this is a currently
+ * blocked job.
+ */
+ public boolean isBlocked() {
+ return getBlockedStatus() != null;
+ }
+
+ /**
+ * Return whether or not the job was cancelled in the UI.
+ *
+ * @return boolean
+ */
+ public boolean isCanceled() {
+ return canceled;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isCancellable()
+ */
+ public boolean isCancellable() {
+ return super.isCancellable();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ boolean isJobInfo() {
+ return true;
+ }
+
+ /**
+ * Set the description of the blocking status.
+ *
+ * @param blockedStatus
+ * The IStatus that describes the blockage or <code>null</code>
+ */
+ public void setBlockedStatus(IStatus blockedStatus) {
+ this.blockedStatus = blockedStatus;
+ }
+
+ /**
+ * Set the GroupInfo to be the group.
+ *
+ * @param group
+ */
+ void setGroupInfo(GroupInfo group) {
+ parent = group;
+ }
+
+ /**
+ * Set the name of the taskInfo.
+ *
+ * @param name
+ */
+ void setTaskName(String name) {
+ taskInfo.setTaskName(name);
+ }
+
+ /**
+ * Set the number of ticks this job represents. Default is indeterminate
+ * (-1).
+ *
+ * @param ticks
+ * The ticks to set.
+ */
+ public void setTicks(int ticks) {
+ this.ticks = ticks;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfoFactory.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfoFactory.java
new file mode 100644
index 0000000..4fa41a9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobInfoFactory.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.Creatable;
+
+@Creatable
+@Singleton
+public class JobInfoFactory {
+
+ @Inject
+ Services services;
+
+ public JobInfo getJobInfo(Job enclosingJob) {
+ return new JobInfo(enclosingJob,
+ services.getService(ProgressManager.class),
+ services.getService(FinishedJobs.class));
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobTreeElement.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobTreeElement.java
new file mode 100644
index 0000000..155a00d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobTreeElement.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * The JobTreeElement is the abstract superclass of items displayed in the tree.
+ */
+public abstract class JobTreeElement implements Comparable {
+
+ /**
+ * Return the parent of this object.
+ *
+ * @return Object
+ */
+ public Object getParent() {
+ return null;
+ }
+
+ /**
+ * Return whether or not the receiver has children.
+ *
+ * @return boolean
+ */
+ abstract boolean hasChildren();
+
+ /**
+ * Return the children of the receiver.
+ *
+ * @return Object[]
+ */
+ abstract Object[] getChildren();
+
+ /**
+ * Return the displayString for the receiver.
+ *
+ * @return String
+ */
+ abstract String getDisplayString();
+
+ /**
+ * Return the displayString for the receiver.
+ *
+ * @param showProgress
+ * Whether or not progress is being shown (if relevant).
+ * @return String
+ */
+ String getDisplayString(boolean showProgress) {
+ return getDisplayString();
+ }
+
+ /**
+ * Get the image for the reciever.
+ *
+ * @return Image or <code>null</code>.
+ */
+ public Image getDisplayImage() {
+ return JFaceResources.getImage(ProgressInfoItem.DEFAULT_JOB_KEY);
+ }
+
+ /**
+ * Return the condensed version of the display string
+ *
+ * @return String
+ */
+ String getCondensedDisplayString() {
+ return getDisplayString();
+ }
+
+ /**
+ * Return whether or not the receiver is an info.
+ *
+ * @return boolean
+ */
+ abstract boolean isJobInfo();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object arg0) {
+ if (arg0 instanceof JobTreeElement)
+ return getDisplayString().compareTo(
+ ((JobTreeElement) arg0).getDisplayString());
+ return 0;
+ }
+
+ /**
+ * Return whether or not this is currently active.
+ *
+ * @return boolean
+ */
+ abstract boolean isActive();
+
+ /**
+ * Return whether or not the receiver can be cancelled.
+ *
+ * @return boolean
+ */
+ public boolean isCancellable() {
+ return false;
+ }
+
+ /**
+ * Cancel the receiver.
+ */
+ public void cancel() {
+ // By default do nothing.
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobsViewPreferenceDialog.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobsViewPreferenceDialog.java
new file mode 100644
index 0000000..7756118
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/JobsViewPreferenceDialog.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Sebastian Davids <sdavids@gmx.de> - Fix for Bug 132156 [Dialogs] Progress Preferences dialog problems
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The JobsViewPreferenceDialog is the dialog that
+ * allows the user to set the preferences.
+ */
+public class JobsViewPreferenceDialog extends ViewSettingsDialog {
+
+ private BooleanFieldEditor showSystemJob;
+ private BooleanFieldEditor runInBackground;
+ private IPreferenceStore preferenceStore;
+
+
+ /**
+ * Create a new instance of the receiver.
+ * @param parentShell
+ * @param preferenceStore
+ */
+ public JobsViewPreferenceDialog(Shell parentShell, IPreferenceStore preferenceStore) {
+ super(parentShell);
+ this.preferenceStore = preferenceStore;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(ProgressMessages.JobsViewPreferenceDialog_Title);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite top = (Composite) super.createDialogArea(parent);
+
+ Composite editArea = new Composite(top, SWT.NONE);
+ editArea.setLayout(new GridLayout());
+ editArea.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
+
+ runInBackground = new BooleanFieldEditor(IProgressConstants.RUN_IN_BACKGROUND, ProgressMessages.JobsViewPreferenceDialog_RunInBackground, editArea);//$NON-NLS-1$
+ runInBackground.setPreferenceName(IProgressConstants.RUN_IN_BACKGROUND);
+ runInBackground.setPreferenceStore(preferenceStore);
+ runInBackground.load();
+
+ showSystemJob = new BooleanFieldEditor(IProgressConstants.SHOW_SYSTEM_JOBS, ProgressMessages.JobsViewPreferenceDialog_ShowSystemJobs, editArea);//$NON-NLS-1$
+ showSystemJob.setPreferenceName(IProgressConstants.SHOW_SYSTEM_JOBS);
+ showSystemJob.setPreferenceStore(preferenceStore);
+ showSystemJob.load();
+
+ Dialog.applyDialogFont(top);
+
+ return top;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#okPressed()
+ */
+ protected void okPressed() {
+ runInBackground.store();
+ showSystemJob.store();
+ super.okPressed();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.preferences.ViewSettingsDialog#performDefaults()
+ */
+ protected void performDefaults() {
+ runInBackground.loadDefault();
+ showSystemJob.loadDefault();
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/PreferenceStore.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/PreferenceStore.java
new file mode 100644
index 0000000..84f8e1d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/PreferenceStore.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.inject.Inject;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+
+public class PreferenceStore implements IPreferenceStore {
+
+ @Inject
+ private Preferences preferences;
+
+ @Override
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ }
+
+ @Override
+ public boolean contains(String name) {
+ return false;
+ }
+
+ @Override
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ }
+
+ @Override
+ public boolean getBoolean(String name) {
+ return Preferences.getBoolean(name);
+ }
+
+ @Override
+ public boolean getDefaultBoolean(String name) {
+ return false;
+ }
+
+ @Override
+ public double getDefaultDouble(String name) {
+ return 0;
+ }
+
+ @Override
+ public float getDefaultFloat(String name) {
+ return 0;
+ }
+
+ @Override
+ public int getDefaultInt(String name) {
+ return 0;
+ }
+
+ @Override
+ public long getDefaultLong(String name) {
+ return 0;
+ }
+
+ @Override
+ public String getDefaultString(String name) {
+ return "";
+ }
+
+ @Override
+ public double getDouble(String name) {
+ return 0;
+ }
+
+ @Override
+ public float getFloat(String name) {
+ return 0;
+ }
+
+ @Override
+ public int getInt(String name) {
+ return 0;
+ }
+
+ @Override
+ public long getLong(String name) {
+ return 0;
+ }
+
+ @Override
+ public String getString(String name) {
+ return "";
+ }
+
+ @Override
+ public boolean isDefault(String name) {
+ return false;
+ }
+
+ @Override
+ public boolean needsSaving() {
+ return false;
+ }
+
+ @Override
+ public void putValue(String name, String value) {
+ Preferences.set(name, value);
+ }
+
+ @Override
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ }
+
+ @Override
+ public void setDefault(String name, double value) {
+ }
+
+ @Override
+ public void setDefault(String name, float value) {
+ }
+
+ @Override
+ public void setDefault(String name, int value) {
+ }
+
+ @Override
+ public void setDefault(String name, long value) {
+ }
+
+ @Override
+ public void setDefault(String name, String defaultObject) {
+ }
+
+ @Override
+ public void setDefault(String name, boolean value) {
+ }
+
+ @Override
+ public void setToDefault(String name) {
+ Preferences.set(name, false);
+ }
+
+ @Override
+ public void setValue(String name, double value) {
+ }
+
+ @Override
+ public void setValue(String name, float value) {
+ }
+
+ @Override
+ public void setValue(String name, int value) {
+ }
+
+ @Override
+ public void setValue(String name, long value) {
+ }
+
+ @Override
+ public void setValue(String name, String value) {
+ }
+
+ @Override
+ public void setValue(String name, boolean value) {
+ Preferences.set(name, value);
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Preferences.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Preferences.java
new file mode 100644
index 0000000..3709aba
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Preferences.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.ui.model.application.MApplication;
+
+@Creatable
+@Singleton
+public class Preferences {
+
+ private static Map<String, String> preferences;
+
+ @Inject
+ private static synchronized void updatePreferences(MApplication application) {
+ preferences = application.getPersistedState();
+ }
+
+ public static synchronized boolean getBoolean(String key) {
+ return Boolean.parseBoolean(preferences.get(key));
+ }
+
+ public static synchronized void set(String key, boolean value) {
+ preferences.put(key, Boolean.toString(value));
+ }
+
+ public static synchronized void set(String key, String value) {
+ preferences.put(key, value);
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationItem.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationItem.java
new file mode 100644
index 0000000..0107489
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationItem.java
@@ -0,0 +1,406 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.net.URL;
+
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.services.statusreporter.StatusReporter;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.e4.ui.progress.internal.legacy.StatusAdapter;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Util;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * The ProgressAnimationItem is the animation items that uses the progress bar.
+ */
+public class ProgressAnimationItem extends AnimationItem implements
+ FinishedJobs.KeptJobsListener {
+
+ ProgressBar bar;
+
+ MouseListener mouseListener;
+
+ Composite top;
+
+ ToolBar toolbar;
+
+ ToolItem toolButton;
+
+ ProgressRegion progressRegion;
+
+ Image noneImage, okImage, errorImage;
+
+ boolean animationRunning;
+
+ // ProgressBar flags
+ private int flags;
+
+ private FinishedJobs finishedJobs;
+
+ /**
+ * Create an instance of the receiver in the supplied region.
+ *
+ * @param region
+ * The ProgressRegion that contains the receiver.
+ * @param flags
+ * flags to use for creation of the progress bar
+ */
+ ProgressAnimationItem(ProgressRegion region, int flags,
+ AnimationManager animationManager, FinishedJobs finishedJobs) {
+ super(animationManager);
+ this.flags = flags;
+ this.finishedJobs = finishedJobs;
+ finishedJobs.addListener(this);
+
+ progressRegion = region;
+ mouseListener = new MouseAdapter() {
+ public void mouseDoubleClick(MouseEvent e) {
+ doAction();
+ }
+ };
+ }
+
+ void doAction() {
+
+ JobTreeElement[] jobTreeElements = finishedJobs.getKeptElements();
+ // search from end (youngest)
+ for (int i = jobTreeElements.length - 1; i >= 0; i--) {
+ if (jobTreeElements[i] instanceof JobInfo) {
+ JobInfo ji = (JobInfo) jobTreeElements[i];
+ Job job = ji.getJob();
+ if (job != null) {
+
+ IStatus status = job.getResult();
+ if (status != null && status.getSeverity() == IStatus.ERROR) {
+ //TODO E4
+// StatusAdapter statusAdapter = StatusAdapterHelper
+// .getInstance().getStatusAdapter(ji);
+
+// if (statusAdapter == null)
+// statusAdapter = new StatusAdapter(status);
+ getStatusReporter().report(status,
+ StatusReporter.SHOW, new Object[0]);
+ removeTopElement(ji);
+ }
+
+ execute(ji, job);
+ }
+ }
+ }
+
+ progressRegion.processDoubleClick();
+ refresh();
+ }
+
+ /**
+ * @param ji
+ * @param job
+ */
+ private void execute(JobInfo ji, Job job) {
+
+ Object prop = job.getProperty(IProgressConstants.ACTION_PROPERTY);
+ if (prop instanceof IAction && ((IAction) prop).isEnabled()) {
+ IAction action = (IAction) prop;
+ action.run();
+ removeTopElement(ji);
+ }
+
+ prop = job.getProperty(IProgressConstants.COMMAND_PROPERTY);
+ if (prop instanceof ParameterizedCommand) {
+ ParameterizedCommand command = (ParameterizedCommand) prop;
+ Exception exception = null;
+ getEHandlerService().executeHandler(command);
+ removeTopElement(ji);
+
+ if (exception != null) {
+ Status status = new Status(IStatus.ERROR, IProgressConstants.PLUGIN_ID,
+ exception.getMessage(), exception);
+ getStatusReporter().report(status,
+ StatusReporter.LOG | StatusReporter.SHOW, null);
+ }
+
+ }
+ }
+
+ /**
+ * @param ji
+ */
+ private void removeTopElement(JobInfo ji) {
+ JobTreeElement topElement = (JobTreeElement) ji.getParent();
+ if (topElement == null) {
+ topElement = ji;
+ }
+ finishedJobs.remove(topElement);
+ }
+
+ private IAction getAction(Job job) {
+ Object property = job.getProperty(IProgressConstants.ACTION_PROPERTY);
+ if (property instanceof IAction) {
+ return (IAction) property;
+ }
+ return null;
+ }
+
+ private void refresh() {
+
+ // Abort the refresh if we are in the process of shutting down
+ if (!PlatformUI.isWorkbenchRunning()) {
+ return;
+ }
+
+ if (toolbar == null || toolbar.isDisposed()) {
+ return;
+ }
+
+ JobTreeElement[] jobTreeElements = finishedJobs.getKeptElements();
+ // search from end (youngest)
+ for (int i = jobTreeElements.length - 1; i >= 0; i--) {
+ if (jobTreeElements[i] instanceof JobInfo) {
+ JobInfo ji = (JobInfo) jobTreeElements[i];
+ Job job = ji.getJob();
+ if (job != null) {
+ IStatus status = job.getResult();
+ if (status != null && status.getSeverity() == IStatus.ERROR) {
+ // green arrow with error overlay
+ initButton(errorImage, NLS.bind(
+ ProgressMessages.ProgressAnimationItem_error,
+ job.getName()));
+ return;
+ }
+ IAction action = getAction(job);
+ if (action != null && action.isEnabled()) {
+ // green arrow with exclamation mark
+ String tt = action.getToolTipText();
+ if (tt == null || tt.trim().length() == 0) {
+ tt = NLS.bind(
+ ProgressMessages.ProgressAnimationItem_ok,
+ job.getName());
+ }
+ initButton(okImage, tt);
+ return;
+ }
+ // just the green arrow
+ initButton(noneImage,
+ ProgressMessages.ProgressAnimationItem_tasks);
+ return;
+ }
+ }
+ }
+
+ if (animationRunning) {
+ initButton(noneImage, ProgressMessages.ProgressAnimationItem_tasks);
+ return;
+ }
+
+ // if nothing found hide tool item
+ toolbar.setVisible(false);
+ }
+
+ private void initButton(Image im, final String tt) {
+ toolButton.setImage(im);
+ toolButton.setToolTipText(tt);
+ toolbar.setVisible(true);
+ toolbar.getParent().layout(); // must layout
+
+ toolbar.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ public void getName(AccessibleEvent e) {
+ e.result = tt;
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AnimationItem#createAnimationItem(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createAnimationItem(Composite parent) {
+
+ if (okImage == null) {
+ Display display = parent.getDisplay();
+ ImageTools imageTools = ImageTools.getInstance();
+
+ noneImage = imageTools.getImage("progress/progress_none.png", display); //$NON-NLS-1$
+ okImage = imageTools.getImage("progress/progress_ok.png", display); //$NON-NLS-1$
+ errorImage = imageTools.getImage("progress/progress_error.png", display); //$NON-NLS-1$
+ }
+
+ top = new Composite(parent, SWT.NULL);
+ top.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ finishedJobs.removeListener(
+ ProgressAnimationItem.this);
+ noneImage.dispose();
+ okImage.dispose();
+ errorImage.dispose();
+ }
+ });
+
+ boolean isCarbon = Util.isMac();
+
+ GridLayout gl = new GridLayout();
+ if (isHorizontal())
+ gl.numColumns = isCarbon ? 3 : 2;
+ gl.marginHeight = 0;
+ gl.marginWidth = 0;
+ if (isHorizontal()) {
+ gl.horizontalSpacing = 2;
+ } else {
+ gl.verticalSpacing = 2;
+ }
+ top.setLayout(gl);
+
+ bar = new ProgressBar(top, flags | SWT.INDETERMINATE);
+ bar.setVisible(false);
+ bar.addMouseListener(mouseListener);
+
+ GridData gd;
+ int hh = 12;
+ if (isHorizontal()) {
+ gd = new GridData(SWT.BEGINNING, SWT.CENTER, true, false);
+ gd.heightHint = hh;
+ } else {
+ gd = new GridData(SWT.CENTER, SWT.BEGINNING, false, true);
+ gd.widthHint = hh;
+ }
+
+ bar.setLayoutData(gd);
+
+ toolbar = new ToolBar(top, SWT.FLAT);
+ toolbar.setVisible(false);
+
+ toolButton = new ToolItem(toolbar, SWT.NONE);
+ toolButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ doAction();
+ }
+ });
+
+ if (isCarbon) {
+ new Label(top, SWT.NONE).setLayoutData(new GridData(4, 4));
+ }
+
+ refresh();
+
+ return top;
+ }
+
+ /**
+ * @return <code>true</code> if the control is horizontally oriented
+ */
+ private boolean isHorizontal() {
+ return (flags & SWT.HORIZONTAL) != 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AnimationItem#getControl()
+ */
+ public Control getControl() {
+ return top;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AnimationItem#animationDone()
+ */
+ void animationDone() {
+ super.animationDone();
+ animationRunning = false;
+ if (bar.isDisposed()) {
+ return;
+ }
+ bar.setVisible(false);
+ refresh();
+ }
+
+ /**
+ * @return <code>true</code> when the animation is running
+ */
+ public boolean animationRunning() {
+ return animationRunning;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.AnimationItem#animationStart()
+ */
+ void animationStart() {
+ super.animationStart();
+ animationRunning = true;
+ if (bar.isDisposed()) {
+ return;
+ }
+ bar.setVisible(true);
+ refresh();
+ }
+
+ public void removed(JobTreeElement info) {
+ final Display display = Display.getDefault();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ refresh();
+ }
+ });
+ }
+
+ public void finished(final JobTreeElement jte) {
+ final Display display = Display.getDefault();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ refresh();
+ }
+ });
+ }
+
+ protected StatusReporter getStatusReporter() {
+ return Services.getInstance().getStatusReporter();
+ }
+
+ protected EHandlerService getEHandlerService() {
+ return Services.getInstance().getEHandlerService();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationProcessor.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationProcessor.java
new file mode 100644
index 0000000..1c2c1d8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressAnimationProcessor.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+
+/**
+ * The ProgressAnimationProcessor is the processor for the animation using the
+ * system progress.
+ */
+class ProgressAnimationProcessor implements IAnimationProcessor {
+
+ AnimationManager manager;
+
+ /**
+ * Create a new instance of the receiver and listen to the animation
+ * manager.
+ *
+ * @param animationManager
+ */
+ ProgressAnimationProcessor(AnimationManager animationManager) {
+ manager = animationManager;
+ }
+
+ List items = Collections.synchronizedList(new ArrayList());
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#startAnimation(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void startAnimationLoop(IProgressMonitor monitor) {
+
+ // Create an off-screen image to draw on, and a GC to draw with.
+ // Both are disposed after the animation.
+ if (items.size() == 0) {
+ return;
+ }
+ if (!PlatformUI.isWorkbenchRunning()) {
+ return;
+ }
+
+ while (manager.isAnimated() && !monitor.isCanceled()) {
+ //Do nothing while animation is happening
+ }
+
+ ProgressAnimationItem[] animationItems = getAnimationItems();
+ for (int i = 0; i < animationItems.length; i++) {
+ animationItems[i].animationDone();
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#addItem(org.eclipse.ui.internal.progress.AnimationItem)
+ */
+ public void addItem(AnimationItem item) {
+ Assert.isTrue(item instanceof ProgressAnimationItem);
+ items.add(item);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#removeItem(org.eclipse.ui.internal.progress.AnimationItem)
+ */
+ public void removeItem(AnimationItem item) {
+ Assert.isTrue(item instanceof ProgressAnimationItem);
+ items.remove(item);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#hasItems()
+ */
+ public boolean hasItems() {
+ return items.size() > 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#itemsInactiveRedraw()
+ */
+ public void itemsInactiveRedraw() {
+ //Nothing to do here as SWT handles redraw
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#animationStarted(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void animationStarted() {
+ AnimationItem[] animationItems = getAnimationItems();
+ for (int i = 0; i < animationItems.length; i++) {
+ animationItems[i].animationStart();
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#getPreferredWidth()
+ */
+ public int getPreferredWidth() {
+ return 30;
+ }
+
+ /**
+ * Get the animation items currently registered for the receiver.
+ *
+ * @return ProgressAnimationItem[]
+ */
+ private ProgressAnimationItem[] getAnimationItems() {
+ ProgressAnimationItem[] animationItems = new ProgressAnimationItem[items
+ .size()];
+ items.toArray(animationItems);
+ return animationItems;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#animationFinished()
+ */
+ public void animationFinished() {
+ AnimationItem[] animationItems = getAnimationItems();
+ for (int i = 0; i < animationItems.length; i++) {
+ animationItems[i].animationDone();
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IAnimationProcessor#isProcessorJob(org.eclipse.core.runtime.jobs.Job)
+ */
+ public boolean isProcessorJob(Job job) {
+ // We have no jobs
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressCanvasViewer.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressCanvasViewer.java
new file mode 100644
index 0000000..94a368a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressCanvasViewer.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.e4.ui.progress.internal.legacy.TrimUtil;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Transform;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * The ProgressCanvasViewer is the viewer used by progress windows. It displays text
+ * on the canvas.
+ */
+public class ProgressCanvasViewer extends AbstractProgressViewer {
+ Canvas canvas;
+
+ Object[] displayedItems = new Object[0];
+
+ private final static List EMPTY_LIST = new ArrayList();
+
+ /**
+ * Font metrics to use for determining pixel sizes.
+ */
+ private FontMetrics fontMetrics;
+
+ private int numShowItems = 1;
+
+ private int maxCharacterWidth;
+
+ private int orientation = SWT.HORIZONTAL;
+
+ /**
+ * Create a new instance of the receiver with the supplied
+ * parent and style bits.
+ * @param parent The composite the Canvas is created in
+ * @param style style bits for the canvas
+ * @param itemsToShow the number of items this will show
+ * @param numChars The number of characters for the width hint.
+ * @param side the side to display text, this helps determine horizontal vs vertical
+ */
+ ProgressCanvasViewer(Composite parent, int style, int itemsToShow, int numChars, int orientation) {
+ super();
+ this.orientation = orientation;
+ numShowItems = itemsToShow;
+ maxCharacterWidth = numChars;
+ canvas = new Canvas(parent, style);
+ hookControl(canvas);
+ // Compute and store a font metric
+ GC gc = new GC(canvas);
+ gc.setFont(JFaceResources.getDefaultFont());
+ fontMetrics = gc.getFontMetrics();
+ gc.dispose();
+ initializeListeners();
+ }
+
+ /**
+ * NE: Copied from ContentViewer. We don't want the OpenStrategy hooked
+ * in StructuredViewer.hookControl otherwise the canvas will take focus
+ * since it has a key listener. We don't want this included in the window's
+ * tab traversal order. Defeating it here is more self-contained then
+ * setting the tab list on the shell or other parent composite.
+ */
+ protected void hookControl(Control control) {
+ control.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent event) {
+ handleDispose(event);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
+ */
+ protected Widget doFindInputItem(Object element) {
+ return null; // No widgets associated with items
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
+ */
+ protected Widget doFindItem(Object element) {
+ return null; // No widgets associated with items
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
+ * java.lang.Object, boolean)
+ */
+ protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+ canvas.redraw();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
+ */
+ protected List getSelectionFromWidget() {
+ //No selection on a Canvas
+ return EMPTY_LIST;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
+ */
+ protected void internalRefresh(Object element) {
+ displayedItems = getSortedChildren(getRoot());
+ canvas.redraw();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
+ */
+ public void reveal(Object element) {
+ //Nothing to do here as we do not scroll
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
+ * boolean)
+ */
+ protected void setSelectionToWidget(List l, boolean reveal) {
+ //Do nothing as there is no selection
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.Viewer#getControl()
+ */
+ public Control getControl() {
+ return canvas;
+ }
+
+ private void initializeListeners() {
+ canvas.addPaintListener(new PaintListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
+ */
+ public void paintControl(PaintEvent event) {
+
+ GC gc = event.gc;
+ Transform transform = null;
+ if (orientation == SWT.VERTICAL) {
+ transform = new Transform(event.display);
+ transform.translate(TrimUtil.TRIM_DEFAULT_HEIGHT, 0);
+ transform.rotate(90);
+ }
+ ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
+
+ int itemCount = Math.min(displayedItems.length, numShowItems);
+
+ int yOffset = 0;
+ int xOffset = 0;
+ if (numShowItems == 1) {//If there is a single item try to center it
+ Rectangle clientArea = canvas.getParent().getClientArea();
+ if (orientation == SWT.HORIZONTAL) {
+ int size = clientArea.height;
+ yOffset = size - (fontMetrics.getHeight());
+ yOffset = yOffset / 2;
+ } else {
+ int size = clientArea.width;
+ xOffset = size - (fontMetrics.getHeight());
+ xOffset = xOffset / 2;
+ }
+ }
+
+ for (int i = 0; i < itemCount; i++) {
+ String string = labelProvider.getText(displayedItems[i]);
+ if(string == null) {
+ string = "";//$NON-NLS-1$
+ }
+ if (orientation == SWT.HORIZONTAL) {
+ gc.drawString(string, 2, yOffset + (i * fontMetrics.getHeight()), true);
+ } else {
+ gc.setTransform(transform);
+ gc.drawString(string, xOffset + (i * fontMetrics.getHeight()), 2, true);
+ }
+ }
+ if (transform != null)
+ transform.dispose();
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ContentViewer#setLabelProvider(org.eclipse.jface.viewers.IBaseLabelProvider)
+ */
+ public void setLabelProvider(IBaseLabelProvider labelProvider) {
+ Assert.isTrue(labelProvider instanceof ILabelProvider);
+ super.setLabelProvider(labelProvider);
+ }
+
+ /**
+ * Get the size hints for the receiver. These are used for
+ * layout data.
+ * @return Point - the preferred x and y coordinates
+ */
+ public Point getSizeHints() {
+
+ Display display = canvas.getDisplay();
+
+ GC gc = new GC(canvas);
+ FontMetrics fm = gc.getFontMetrics();
+ int charWidth = fm.getAverageCharWidth();
+ int charHeight = fm.getHeight();
+ int maxWidth = display.getBounds().width / 2;
+ int maxHeight = display.getBounds().height / 6;
+ int fontWidth = charWidth * maxCharacterWidth;
+ int fontHeight = charHeight * numShowItems;
+ if (maxWidth < fontWidth) {
+ fontWidth = maxWidth;
+ }
+ if (maxHeight < fontHeight) {
+ fontHeight = maxHeight;
+ }
+ gc.dispose();
+ return new Point(fontWidth, fontHeight);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#add(java.lang.Object[])
+ */
+ public void add(Object[] elements) {
+ refresh(true);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AbstractProgressViewer#remove(java.lang.Object[])
+ */
+ public void remove(Object[] elements) {
+ refresh(true);
+
+ }
+
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressContentProvider.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressContentProvider.java
new file mode 100644
index 0000000..d228edb
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressContentProvider.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * The ProgressContentProvider is the content provider used for classes that
+ * listen to the progress changes.
+ */
+public abstract class ProgressContentProvider implements
+ IProgressUpdateCollector, IStructuredContentProvider {
+
+ /**
+ * Return whether or not we check the preferences or overide.
+ */
+ private boolean canShowDebug = false;
+
+ protected ProgressViewUpdater progressViewUpdater;
+
+ private ProgressManager progressManager;
+
+ /**
+ * Create a new instance of the receiver with all of the
+ * default values.
+ */
+ public ProgressContentProvider(ProgressViewUpdater progressViewUpdater,
+ ProgressManager progressManager) {
+ this.progressViewUpdater = progressViewUpdater;
+ this.progressManager= progressManager;
+ progressViewUpdater.addCollector(this);
+ }
+
+ /**
+ * Create a new instance of the receiver with a flag to
+ * indicate if there will be debug info shown or not.
+ * @param debug If true debug information will be shown
+ * if the debug flag in the ProgressManager is true.
+ */
+ public ProgressContentProvider(ProgressViewUpdater progressViewUpdater,
+ ProgressManager progressManager, boolean debug) {
+ this(progressViewUpdater, progressManager);
+ canShowDebug = debug;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+
+ return progressManager.getRootElements(debug());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ progressViewUpdater.removeCollector(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ //No change when input changes
+ }
+
+ /**
+ * Return whether or not we are debugging. Check the
+ * system settings unless we are overiding them.
+ * @return boolean <code>true</code> if debug
+ * (system) jobs are being shown.
+ */
+ public boolean debug(){
+ if(!canShowDebug) {
+ return false;
+ }
+ return progressViewUpdater.showsDebug();
+
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressInfoItem.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressInfoItem.java
new file mode 100644
index 0000000..5eb083d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressInfoItem.java
@@ -0,0 +1,1035 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import com.ibm.icu.text.DateFormat;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.util.Util;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.osgi.framework.FrameworkUtil;
+
+
+/**
+ * ProgressInfoItem is the item used to show jobs.
+ *
+ * @since 3.1
+ *
+ */
+public class ProgressInfoItem extends Composite {
+
+ static String STOP_IMAGE_KEY = "org.eclipse.ui.internal.progress.PROGRESS_STOP"; //$NON-NLS-1$
+
+ static String DISABLED_STOP_IMAGE_KEY = "org.eclipse.ui.internal.progress.DISABLED_PROGRESS_STOP"; //$NON-NLS-1$
+
+ static String CLEAR_FINISHED_JOB_KEY = "org.eclipse.ui.internal.progress.CLEAR_FINISHED_JOB"; //$NON-NLS-1$
+
+ static String DISABLED_CLEAR_FINISHED_JOB_KEY = "org.eclipse.ui.internal.progress.DISABLED_CLEAR_FINISHED_JOB"; //$NON-NLS-1$
+
+ static String DEFAULT_JOB_KEY = "org.eclipse.ui.internal.progress.PROGRESS_DEFAULT"; //$NON-NLS-1$
+
+ static String DARK_COLOR_KEY = "org.eclipse.ui.internal.progress.PROGRESS_DARK_COLOR"; //$NON-NLS-1$
+
+ JobTreeElement info;
+
+ Label progressLabel;
+
+ ToolBar actionBar;
+
+ ToolItem actionButton;
+
+ List taskEntries = new ArrayList(0);
+
+ private ProgressBar progressBar;
+
+ private Label jobImageLabel;
+
+ private IProgressService progressService;
+
+ private FinishedJobs finishedJobs;
+
+ static final int MAX_PROGRESS_HEIGHT = 12;
+
+ static final int MIN_ICON_SIZE = 16;
+
+ private static final String TEXT_KEY = "Text"; //$NON-NLS-1$
+
+ private static final String TRIGGER_KEY = "Trigger";//$NON-NLS-1$
+
+ interface IndexListener {
+ /**
+ * Select the item previous to the receiver.
+ */
+ public void selectPrevious();
+
+ /**
+ * Select the next previous to the receiver.
+ */
+ public void selectNext();
+
+ /**
+ * Select the receiver.
+ */
+ public void select();
+ }
+
+ IndexListener indexListener;
+
+ private int currentIndex;
+
+ private boolean selected;
+
+ private MouseAdapter mouseListener;
+
+ private boolean isShowing = true;
+
+ private ResourceManager resourceManager;
+
+ private Link link;
+
+ static {
+ ImageTools.getInstance().putIntoRegistry(STOP_IMAGE_KEY,
+ "elcl16/progress_stop.png");//$NON-NLS-1$
+ ImageTools.getInstance().putIntoRegistry(DISABLED_STOP_IMAGE_KEY,
+ "dlcl16/progress_stop.png");//$NON-NLS-1$
+ ImageTools.getInstance().putIntoRegistry(DEFAULT_JOB_KEY,
+ "progress/progress_task.png"); //$NON-NLS-1$
+ ImageTools.getInstance().putIntoRegistry(CLEAR_FINISHED_JOB_KEY,
+ "elcl16/progress_rem.png"); //$NON-NLS-1$
+ ImageTools.getInstance().putIntoRegistry(
+ DISABLED_CLEAR_FINISHED_JOB_KEY, "dlcl16/progress_rem.png"); //$NON-NLS-1$
+
+ // Mac has different Gamma value
+ int shift = Util.isMac() ? -25 : -10;
+
+ Color lightColor = Services.getInstance().getDisplay()
+ .getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+
+ // Determine a dark color by shifting the list color
+ RGB darkRGB = new RGB(Math.max(0, lightColor.getRed() + shift),
+ Math.max(0, lightColor.getGreen() + shift), Math.max(0,
+ lightColor.getBlue() + shift));
+ JFaceResources.getColorRegistry().put(DARK_COLOR_KEY, darkRGB);
+ }
+
+ /**
+ * Create a new instance of the receiver with the specified parent, style
+ * and info object/
+ *
+ * @param parent
+ * @param style
+ * @param progressInfo
+ */
+ public ProgressInfoItem(Composite parent, int style,
+ JobTreeElement progressInfo, IProgressService progressService,
+ FinishedJobs finishedJobs) {
+ super(parent, style);
+ info = progressInfo;
+ this.progressService = progressService;
+ this.finishedJobs = finishedJobs;
+ setData(info);
+ setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+ createChildren();
+ if (info.isJobInfo()) {
+ setToolTipText(decorateText(getMainTitle(),
+ ((JobInfo) info).getJob()));
+ }
+ }
+
+ /**
+ * Create the child widgets of the receiver.
+ */
+ protected void createChildren() {
+
+ FormLayout layout = new FormLayout();
+ setLayout(layout);
+
+ jobImageLabel = new Label(this, SWT.NONE);
+ Image infoImage = getInfoImage();
+ jobImageLabel.setImage(infoImage);
+ FormData imageData = new FormData();
+ if (infoImage != null) {
+ // position it in the center
+ imageData.top = new FormAttachment(50,
+ -infoImage.getBounds().height / 2);
+ } else {
+ imageData.top = new FormAttachment(0,
+ IDialogConstants.VERTICAL_SPACING);
+ }
+ imageData.left = new FormAttachment(0,
+ IDialogConstants.HORIZONTAL_SPACING / 2);
+ jobImageLabel.setLayoutData(imageData);
+
+ progressLabel = new Label(this, SWT.NONE);
+ setMainText();
+
+ actionBar = new ToolBar(this, SWT.FLAT);
+ actionBar.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+
+ // set cursor to overwrite any busy cursor we might have
+
+ actionButton = new ToolItem(actionBar, SWT.NONE);
+ actionButton
+ .setToolTipText(ProgressMessages.NewProgressView_CancelJobToolTip);
+ actionButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ actionButton.setEnabled(false);
+ cancelOrRemove();
+ }
+ });
+ actionBar.addListener(SWT.Traverse, new Listener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+ */
+ public void handleEvent(Event event) {
+ if (indexListener == null) {
+ return;
+ }
+ int detail = event.detail;
+ if (detail == SWT.TRAVERSE_ARROW_NEXT) {
+ indexListener.selectNext();
+ }
+ if (detail == SWT.TRAVERSE_ARROW_PREVIOUS) {
+ indexListener.selectPrevious();
+ }
+
+ }
+ });
+ updateToolBarValues();
+
+ FormData progressData = new FormData();
+ progressData.top = new FormAttachment(0,
+ IDialogConstants.VERTICAL_SPACING);
+ progressData.left = new FormAttachment(jobImageLabel,
+ IDialogConstants.HORIZONTAL_SPACING / 2);
+ progressData.right = new FormAttachment(actionBar,
+ IDialogConstants.HORIZONTAL_SPACING * -1);
+ progressLabel.setLayoutData(progressData);
+
+ mouseListener = new MouseAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDown(MouseEvent e) {
+ if (indexListener != null) {
+ indexListener.select();
+ }
+ }
+ };
+ addMouseListener(mouseListener);
+ jobImageLabel.addMouseListener(mouseListener);
+ progressLabel.addMouseListener(mouseListener);
+
+ setLayoutsForNoProgress();
+
+ refresh();
+ }
+
+ /**
+ * Set the main text of the receiver. Truncate to fit the available space.
+ */
+ private void setMainText() {
+ progressLabel
+ .setText(Dialog.shortenText(getMainTitle(), progressLabel));
+ }
+
+ /**
+ * Set the layout of the widgets for the no progress case.
+ *
+ */
+ private void setLayoutsForNoProgress() {
+
+ FormData buttonData = new FormData();
+ buttonData.top = new FormAttachment(progressLabel, 0, SWT.TOP);
+ buttonData.right = new FormAttachment(100,
+ IDialogConstants.HORIZONTAL_SPACING * -1);
+
+ actionBar.setLayoutData(buttonData);
+ if (taskEntries.size() > 0) {
+ FormData linkData = new FormData();
+ linkData.top = new FormAttachment(progressLabel,
+ IDialogConstants.VERTICAL_SPACING);
+ linkData.left = new FormAttachment(progressLabel, 0, SWT.LEFT);
+ linkData.right = new FormAttachment(actionBar, 0, SWT.LEFT);
+ ((Link) taskEntries.get(0)).setLayoutData(linkData);
+
+ }
+ }
+
+ /**
+ * Cancel or remove the reciever.
+ *
+ */
+ protected void cancelOrRemove() {
+
+ if (finishedJobs.isKept(info) && isCompleted()) {
+ finishedJobs.remove(info);
+ } else {
+ info.cancel();
+ }
+
+ }
+
+ /**
+ * Get the image for the info.
+ *
+ * @return Image
+ */
+ private Image getInfoImage() {
+
+ if (!info.isJobInfo()) {
+ return JFaceResources.getImage(DEFAULT_JOB_KEY);
+ }
+
+ JobInfo jobInfo = (JobInfo) info;
+
+ ImageDescriptor descriptor = null;
+ Object property = jobInfo.getJob().getProperty(
+ IProgressConstants.ICON_PROPERTY);
+
+ if (property instanceof ImageDescriptor) {
+ descriptor = (ImageDescriptor) property;
+ } else if (property instanceof URL) {
+ descriptor = ImageDescriptor.createFromURL((URL) property);
+ }
+
+ Image image = null;
+ if (descriptor == null) {
+ image = progressService.getIconFor(jobInfo.getJob());
+ } else {
+ image = getResourceManager().createImageWithDefault(descriptor);
+ }
+
+ if (image == null)
+ image = jobInfo.getDisplayImage();
+
+ return image;
+ }
+
+ /**
+ * Return a resource manager for the receiver.
+ *
+ * @return {@link ResourceManager}
+ */
+ private ResourceManager getResourceManager() {
+ if (resourceManager == null)
+ resourceManager = new LocalResourceManager(JFaceResources
+ .getResources());
+ return resourceManager;
+ }
+
+ /**
+ * Get the main title for the receiver.
+ *
+ * @return String
+ */
+ private String getMainTitle() {
+ if (info.isJobInfo()) {
+ return getJobNameAndStatus((JobInfo) info);
+ }
+ if (info.hasChildren()) {
+ return ((GroupInfo) info).getTaskName();
+ }
+ return info.getDisplayString();
+
+ }
+
+ /**
+ * Get the name and status for a jobInfo
+ *
+ * @param jobInfo
+ *
+ * @return String
+ */
+ public String getJobNameAndStatus(JobInfo jobInfo) {
+
+ Job job = jobInfo.getJob();
+
+ String name = job.getName();
+
+ if (job.isSystem()) {
+ name = NLS.bind(ProgressMessages.JobInfo_System, name);
+ }
+
+ if (jobInfo.isCanceled()) {
+ if (job.getState() == Job.RUNNING)
+ return NLS
+ .bind(ProgressMessages.JobInfo_Cancel_Requested, name);
+ return NLS.bind(ProgressMessages.JobInfo_Cancelled, name);
+ }
+
+ if (jobInfo.isBlocked()) {
+ IStatus blockedStatus = jobInfo.getBlockedStatus();
+ return NLS.bind(ProgressMessages.JobInfo_Blocked, name,
+ blockedStatus.getMessage());
+ }
+
+ switch (job.getState()) {
+ case Job.RUNNING:
+ return name;
+ case Job.SLEEPING: {
+ return NLS.bind(ProgressMessages.JobInfo_Sleeping, name);
+
+ }
+ case Job.NONE: // Only happens for kept jobs
+ return getJobInfoFinishedString(job, true);
+ default:
+ return NLS.bind(ProgressMessages.JobInfo_Waiting, name);
+ }
+ }
+
+ /**
+ * Return the finished String for a job.
+ *
+ * @param job
+ * the completed Job
+ * @param withTime
+ * @return String
+ */
+ String getJobInfoFinishedString(Job job, boolean withTime) {
+ String time = null;
+ if (withTime) {
+ time = getTimeString();
+ }
+ if (time != null) {
+ return NLS.bind(ProgressMessages.JobInfo_FinishedAt, job.getName(),
+ time);
+ }
+ return NLS.bind(ProgressMessages.JobInfo_Finished, job.getName());
+ }
+
+ /**
+ * Get the time string the finished job
+ *
+ * @return String or <code>null</code> if this is not one of the finished
+ * jobs.
+ */
+ private String getTimeString() {
+ Date date = finishedJobs.getFinishDate(info);
+ if (date != null) {
+ return DateFormat.getTimeInstance(DateFormat.SHORT).format(date);
+ }
+ return null;
+ }
+
+ /**
+ * Refresh the contents of the receiver.
+ *
+ */
+ void refresh() {
+
+ // Don't refresh if not visible
+ if (isDisposed() || !isShowing)
+ return;
+
+ jobImageLabel.setImage(getInfoImage());
+ int percentDone = getPercentDone();
+ ProgressBar currentProgressBar = progressBar;
+
+ JobInfo[] infos = getJobInfos();
+ if (isRunning()) {
+ if (progressBar == null) {
+ if (percentDone == IProgressMonitor.UNKNOWN) {
+ // Only do it if there is an indeterminate task
+ // There may be no task so we don't want to create it
+ // until we know for sure
+ for (int i = 0; i < infos.length; i++) {
+ if (infos[i].hasTaskInfo()
+ && infos[i].getTaskInfo().totalWork == IProgressMonitor.UNKNOWN) {
+ createProgressBar(SWT.INDETERMINATE);
+ break;
+ }
+ }
+ } else {
+ createProgressBar(SWT.NONE);
+ progressBar.setMinimum(0);
+ progressBar.setMaximum(100);
+ }
+ }
+
+ // Protect against bad counters
+ if (percentDone >= 0 && percentDone <= 100
+ && percentDone != progressBar.getSelection()) {
+ progressBar.setSelection(percentDone);
+ }
+ }
+
+ else if (isCompleted()) {
+
+ if (progressBar != null) {
+ progressBar.dispose();
+ progressBar = null;
+ }
+ setLayoutsForNoProgress();
+
+ }
+
+ for (int i = 0; i < infos.length; i++) {
+ JobInfo jobInfo = infos[i];
+ TaskInfo taskInfo = jobInfo.getTaskInfo();
+
+ if (taskInfo != null) {
+
+ String taskString = taskInfo.getTaskName();
+ String subTaskString = null;
+ Object[] jobChildren = jobInfo.getChildren();
+ if (jobChildren.length > 0) {
+ subTaskString = ((JobTreeElement) jobChildren[0])
+ .getDisplayString();
+ }
+
+ if (subTaskString != null) {
+ if (taskString == null || taskString.length() == 0) {
+ taskString = subTaskString;
+ } else {
+ taskString = NLS.bind(
+ ProgressMessages.JobInfo_DoneNoProgressMessage,
+ taskString, subTaskString);
+ }
+ }
+ if (taskString != null) {
+ setLinkText(infos[i].getJob(), taskString, i);
+ }
+ } else {// Check for the finished job state
+ Job job = jobInfo.getJob();
+ IStatus result = job.getResult();
+
+ if (result == null || result.getMessage().length() == 0
+ && !info.isJobInfo()) {
+ setLinkText(job, getJobNameAndStatus(jobInfo), i);
+ } else {
+ setLinkText(job, result.getMessage(), i);
+
+ }
+
+ }
+ setColor(currentIndex);
+ }
+
+ // Remove completed tasks
+ if (infos.length < taskEntries.size()) {
+ for (int i = infos.length; i < taskEntries.size(); i++) {
+ ((Link) taskEntries.get(i)).dispose();
+
+ }
+ if (infos.length > 1)
+ taskEntries = taskEntries.subList(0, infos.length - 1);
+ else
+ taskEntries.clear();
+ }
+
+ updateToolBarValues();
+ setMainText();
+
+ if (currentProgressBar != progressBar) {
+ getParent().layout(new Control[] { this });
+ }
+ }
+
+ /**
+ * Return whether or not the receiver is a completed job.
+ *
+ * @return boolean <code>true</code> if the state is Job#NONE.
+ */
+ private boolean isCompleted() {
+
+ JobInfo[] infos = getJobInfos();
+ for (int i = 0; i < infos.length; i++) {
+ if (infos[i].getJob().getState() != Job.NONE) {
+ return false;
+ }
+ }
+ // Only completed if there are any jobs
+ return infos.length > 0;
+ }
+
+ /**
+ * Return the job infos in the receiver.
+ *
+ * @return JobInfo[]
+ */
+ public JobInfo[] getJobInfos() {
+ if (info.isJobInfo()) {
+ return new JobInfo[] { (JobInfo) info };
+ }
+ Object[] children = info.getChildren();
+ JobInfo[] infos = new JobInfo[children.length];
+ System.arraycopy(children, 0, infos, 0, children.length);
+ return infos;
+ }
+
+ /**
+ * Return whether or not the receiver is being displayed as running.
+ *
+ * @return boolean
+ */
+ private boolean isRunning() {
+
+ JobInfo[] infos = getJobInfos();
+ for (int i = 0; i < infos.length; i++) {
+ int state = infos[i].getJob().getState();
+ if (state == Job.WAITING || state == Job.RUNNING)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the current percent done.
+ *
+ * @return int
+ */
+ private int getPercentDone() {
+ if (info.isJobInfo()) {
+ return ((JobInfo) info).getPercentDone();
+ }
+
+ if (info.hasChildren()) {
+ Object[] roots = ((GroupInfo) info).getChildren();
+ if (roots.length == 1 && roots[0] instanceof JobTreeElement) {
+ TaskInfo ti = ((JobInfo) roots[0]).getTaskInfo();
+ if (ti != null) {
+ return ti.getPercentDone();
+ }
+ }
+ return ((GroupInfo) info).getPercentDone();
+ }
+ return 0;
+ }
+
+ /**
+ * Set the images in the toolbar based on whether the receiver is finished
+ * or not. Also update tooltips if required.
+ *
+ */
+ private void updateToolBarValues() {
+ if (isCompleted()) {
+ actionButton.setImage(JFaceResources
+ .getImage(CLEAR_FINISHED_JOB_KEY));
+ actionButton.setDisabledImage(JFaceResources
+ .getImage(DISABLED_CLEAR_FINISHED_JOB_KEY));
+ actionButton
+ .setToolTipText(ProgressMessages.NewProgressView_ClearJobToolTip);
+ } else {
+ actionButton.setImage(JFaceResources.getImage(STOP_IMAGE_KEY));
+ actionButton.setDisabledImage(JFaceResources
+ .getImage(DISABLED_STOP_IMAGE_KEY));
+
+ }
+ JobInfo[] infos = getJobInfos();
+
+ for (int i = 0; i < infos.length; i++) {
+ // Only disable if there is an unresponsive operation
+ if (infos[i].isCanceled() && !isCompleted()) {
+ actionButton.setEnabled(false);
+ return;
+ }
+ }
+ actionButton.setEnabled(true);
+ }
+
+ /**
+ * Create the progress bar and apply any style bits from style.
+ *
+ * @param style
+ */
+ void createProgressBar(int style) {
+
+ FormData buttonData = new FormData();
+ buttonData.top = new FormAttachment(progressLabel, 0);
+ buttonData.right = new FormAttachment(100,
+ IDialogConstants.HORIZONTAL_SPACING * -1);
+
+ actionBar.setLayoutData(buttonData);
+
+ progressBar = new ProgressBar(this, SWT.HORIZONTAL | style);
+ FormData barData = new FormData();
+ barData.top = new FormAttachment(actionBar,
+ IDialogConstants.VERTICAL_SPACING, SWT.TOP);
+ barData.left = new FormAttachment(progressLabel, 0, SWT.LEFT);
+ barData.right = new FormAttachment(actionBar,
+ IDialogConstants.HORIZONTAL_SPACING * -1);
+ barData.height = MAX_PROGRESS_HEIGHT;
+ barData.width = 0;// default is too large
+ progressBar.setLayoutData(barData);
+
+ if (taskEntries.size() > 0) {
+ // Reattach the link label if there is one
+ FormData linkData = new FormData();
+ linkData.top = new FormAttachment(progressBar,
+ IDialogConstants.VERTICAL_SPACING);
+ linkData.left = new FormAttachment(progressBar, 0, SWT.LEFT);
+ linkData.right = new FormAttachment(progressBar, 0, SWT.RIGHT);
+ // Give an initial value so as to constrain the link shortening
+ linkData.width = 20;
+
+ ((Link) taskEntries.get(0)).setLayoutData(linkData);
+ }
+ }
+
+ /**
+ * Set the text of the link to the taskString.
+ *
+ * @param taskString
+ */
+ void setLinkText(Job linkJob, String taskString, int index) {
+
+ if (index >= taskEntries.size()) {// Is it new?
+ link = new Link(this, SWT.NONE);
+
+ FormData linkData = new FormData();
+ if (index == 0 || taskEntries.size() == 0) {
+ Control top = progressBar;
+ if (top == null) {
+ top = progressLabel;
+ }
+ linkData.top = new FormAttachment(top,
+ IDialogConstants.VERTICAL_SPACING);
+ linkData.left = new FormAttachment(top, 0, SWT.LEFT);
+ linkData.right = new FormAttachment(top, 0, SWT.RIGHT);
+ // Give an initial value so as to constrain the link shortening
+ linkData.width = 20;
+ } else {
+ Link previous = (Link) taskEntries.get(index - 1);
+ linkData.top = new FormAttachment(previous,
+ IDialogConstants.VERTICAL_SPACING);
+ linkData.left = new FormAttachment(previous, 0, SWT.LEFT);
+ linkData.right = new FormAttachment(previous, 0, SWT.RIGHT);
+ // Give an initial value so as to constrain the link shortening
+ linkData.width = 20;
+ }
+
+ link.setLayoutData(linkData);
+
+ link.addSelectionListener(new SelectionAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ executeTrigger();
+ }
+ });
+
+ link.addListener(SWT.Resize, new Listener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+ */
+ public void handleEvent(Event event) {
+
+ Object text = link.getData(TEXT_KEY);
+ if (text == null)
+ return;
+
+ updateText((String) text, link);
+
+ }
+ });
+ taskEntries.add(link);
+ } else {
+ link = (Link) taskEntries.get(index);
+ }
+
+ // check for action property
+ Object actionProperty = linkJob
+ .getProperty(IProgressConstants.ACTION_PROPERTY);
+ Object commandProperty = linkJob
+ .getProperty(IProgressConstants.COMMAND_PROPERTY);
+
+ if (actionProperty != null && commandProperty != null) {
+ // if both are specified, then use neither
+ updateTrigger(null, link);
+ } else {
+ Object property = actionProperty != null ? actionProperty
+ : commandProperty;
+ updateTrigger(property, link);
+ }
+
+ if (link.getData(TRIGGER_KEY) == null
+ && (taskString == null || taskString.equals(getMainTitle()))) {
+ // workaround for https://bugs.eclipse.org/383570
+ taskString = ""; //$NON-NLS-1$
+ }
+ link.setToolTipText(taskString);
+ link.setData(TEXT_KEY, taskString);
+
+ updateText(taskString, link);
+
+ }
+
+ public void executeTrigger() {
+
+ Object data = link.getData(TRIGGER_KEY);
+ if (data instanceof IAction) {
+ IAction action = (IAction) data;
+ if (action.isEnabled())
+ action.run();
+ updateTrigger(action, link);
+ } else if (data instanceof ParameterizedCommand) {
+ getEHandlerService().executeHandler((ParameterizedCommand) data);
+ }
+
+ if (link.isDisposed()) {
+ return;
+ }
+
+ Object text = link.getData(TEXT_KEY);
+ if (text == null)
+ return;
+
+ // Refresh the text as enablement might have changed
+ updateText((String) text, link);
+ }
+
+ /**
+ * Update the trigger key if either action is available and enabled or
+ * command is available
+ *
+ * @param trigger
+ * {@link Object} or <code>null</code>
+ * @param link
+ */
+ private void updateTrigger(Object trigger, Link link) {
+ if (link.isDisposed()) {
+ return;
+ }
+
+ if (trigger instanceof IAction && ((IAction) trigger).isEnabled()) {
+ link.setData(TRIGGER_KEY, trigger);
+ } else if (trigger instanceof ParameterizedCommand) {
+ link.setData(TRIGGER_KEY, trigger);
+ } else {
+ link.setData(TRIGGER_KEY, null);
+ }
+
+ }
+
+ /**
+ * Update the text in the link
+ *
+ * @param taskString
+ * @param link
+ */
+ private void updateText(String taskString, Link link) {
+ taskString = Dialog.shortenText(taskString, link);
+
+ // Put in a hyperlink if there is an action
+ link.setText(link.getData(TRIGGER_KEY) == null ? taskString : NLS.bind(
+ "<a>{0}</a>", taskString));//$NON-NLS-1$
+ }
+
+ /**
+ * Set the color base on the index
+ *
+ * @param i
+ */
+ public void setColor(int i) {
+ currentIndex = i;
+
+ if (selected) {
+ setAllBackgrounds(getDisplay().getSystemColor(
+ SWT.COLOR_LIST_SELECTION));
+ setAllForegrounds(getDisplay().getSystemColor(
+ SWT.COLOR_LIST_SELECTION_TEXT));
+ return;
+ }
+
+ if (i % 2 == 0) {
+ setAllBackgrounds(JFaceResources.getColorRegistry().get(
+ DARK_COLOR_KEY));
+ } else {
+ setAllBackgrounds(getDisplay().getSystemColor(
+ SWT.COLOR_LIST_BACKGROUND));
+ }
+ setAllForegrounds(getDisplay()
+ .getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+ }
+
+ /**
+ * Set the foreground of all widgets to the supplied color.
+ *
+ * @param color
+ */
+ private void setAllForegrounds(Color color) {
+ setForeground(color);
+ progressLabel.setForeground(color);
+
+ Iterator taskEntryIterator = taskEntries.iterator();
+ while (taskEntryIterator.hasNext()) {
+ ((Link) taskEntryIterator.next()).setForeground(color);
+ }
+
+ }
+
+ /**
+ * Set the background of all widgets to the supplied color.
+ *
+ * @param color
+ */
+ private void setAllBackgrounds(Color color) {
+ setBackground(color);
+ progressLabel.setBackground(color);
+ actionBar.setBackground(color);
+ jobImageLabel.setBackground(color);
+
+ Iterator taskEntryIterator = taskEntries.iterator();
+ while (taskEntryIterator.hasNext()) {
+ ((Link) taskEntryIterator.next()).setBackground(color);
+ }
+
+ }
+
+ /**
+ * Set the focus to the button.
+ *
+ */
+ void setButtonFocus() {
+ actionBar.setFocus();
+ }
+
+ /**
+ * Set the selection colors.
+ *
+ * @param select
+ * boolean that indicates whether or not to show selection.
+ */
+ void selectWidgets(boolean select) {
+ if (select) {
+ setButtonFocus();
+ }
+ selected = select;
+ setColor(currentIndex);
+ }
+
+ /**
+ * Set the listener for index changes.
+ *
+ * @param indexListener
+ */
+ void setIndexListener(IndexListener indexListener) {
+ this.indexListener = indexListener;
+ }
+
+ /**
+ * Return whether or not the receiver is selected.
+ *
+ * @return boolean
+ */
+ boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * Set whether or not the receiver is being displayed based on the top and
+ * bottom of the currently visible area.
+ *
+ * @param top
+ * @param bottom
+ */
+ void setDisplayed(int top, int bottom) {
+ int itemTop = getLocation().y;
+ int itemBottom = itemTop + getBounds().height;
+ setDisplayed(itemTop <= bottom && itemBottom > top);
+
+ }
+
+ /**
+ * Set whether or not the receiver is being displayed
+ *
+ * @param displayed
+ */
+ private void setDisplayed(boolean displayed) {
+ // See if this element has been turned off
+ boolean refresh = !isShowing && displayed;
+ isShowing = displayed;
+ if (refresh)
+ refresh();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Widget#dispose()
+ */
+ public void dispose() {
+ super.dispose();
+ if(resourceManager != null)
+ resourceManager.dispose();
+ }
+
+ /**
+ * @return Returns the info.
+ */
+ public JobTreeElement getInfo() {
+ return info;
+ }
+
+ private static String decorateText(String text, Object element) {
+ String bundleId = FrameworkUtil.getBundle(element.getClass())
+ .getSymbolicName();
+ return element == null ? text : text + " (" + bundleId + ")"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ protected EHandlerService getEHandlerService() {
+ return Services.getInstance().getEHandlerService();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressLabelProvider.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressLabelProvider.java
new file mode 100644
index 0000000..aec1cda
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressLabelProvider.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * The ProgressLabelProvider is a label provider used for viewers
+ * that need anILabelprovider to show JobInfos.
+ */
+public class ProgressLabelProvider extends LabelProvider {
+
+ Image image;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ return ((JobTreeElement) element).getDisplayImage();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return ((JobTreeElement) element).getDisplayString();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManager.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManager.java
new file mode 100644
index 0000000..b9f24bc
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManager.java
@@ -0,0 +1,1028 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Teddy Walker <teddy.walker@googlemail.com>
+ * - Fix for Bug 151204 [Progress] Blocked status of jobs are not applied/reported
+ * Lars Vogel <Lars.Vogel@gmail.com> - Bug 422040
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.core.runtime.jobs.ProgressProvider;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.e4.ui.progress.internal.legacy.EventLoopProgressMonitor;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.e4.ui.progress.internal.legacy.Policy;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * JobProgressManager provides the progress monitor to the job manager and
+ * informs any ProgressContentProviders of changes.
+ */
+public class ProgressManager extends ProgressProvider {
+ /**
+ * A property to determine if the job was run in the dialog. Kept for
+ * backwards compatability.
+ *
+ * @deprecated
+ * @see IProgressConstants#PROPERTY_IN_DIALOG
+ */
+ public static final QualifiedName PROPERTY_IN_DIALOG = IProgressConstants.PROPERTY_IN_DIALOG;
+
+ private static final String ERROR_JOB = "errorstate.png"; //$NON-NLS-1$
+
+ static final String ERROR_JOB_KEY = "ERROR_JOB"; //$NON-NLS-1$
+
+ private static ProgressManager singleton;
+
+ final private Map jobs = Collections.synchronizedMap(new HashMap());
+
+ final Map runnableMonitors = Collections.synchronizedMap(new HashMap());
+
+ final private Map familyListeners = Collections
+ .synchronizedMap(new HashMap());
+
+ // list of IJobProgressManagerListener
+ private ListenerList listeners = new ListenerList();
+
+ IJobChangeListener changeListener;
+
+ static final String PROGRESS_VIEW_NAME = "org.eclipse.e4.ui.progress.ProgressView"; //$NON-NLS-1$
+
+ static final String PROGRESS_FOLDER = "progress/"; //$NON-NLS-1$
+
+ private static final String SLEEPING_JOB = "sleeping.png"; //$NON-NLS-1$
+
+ private static final String WAITING_JOB = "waiting.png"; //$NON-NLS-1$
+
+ private static final String BLOCKED_JOB = "lockedstate.png"; //$NON-NLS-1$
+
+ /**
+ * The key for the sleeping job icon.
+ */
+ public static final String SLEEPING_JOB_KEY = "SLEEPING_JOB"; //$NON-NLS-1$
+
+ /**
+ * The key for the waiting job icon.
+ */
+ public static final String WAITING_JOB_KEY = "WAITING_JOB"; //$NON-NLS-1$
+
+ /**
+ * The key for the locked job icon.
+ */
+ public static final String BLOCKED_JOB_KEY = "LOCKED_JOB"; //$NON-NLS-1$
+
+
+
+ private static final String IMAGE_KEY = "org.eclipse.ui.progress.images"; //$NON-NLS-1$
+
+ @Inject
+ @Optional
+ IProgressService progressService;
+
+ @Inject
+ JobInfoFactory jobInfoFactory;
+
+ @Optional
+ @Inject
+ FinishedJobs finishedJobs;
+
+ /**
+ * Shutdown the singleton if there is one.
+ */
+ public static void shutdownProgressManager() {
+ if (singleton == null) {
+ return;
+ }
+ singleton.shutdown();
+ }
+
+// /**
+// * Create a new instance of the receiver.
+// */
+// protected ProgressManager() {
+// }
+
+ @PostConstruct
+ protected void init(WorkbenchDialogBlockedHandler dialogBlockedHandler) {
+ Dialog.setBlockedHandler(dialogBlockedHandler);
+
+ setUpImages();
+
+ changeListener = createChangeListener();
+
+ Job.getJobManager().setProgressProvider(this);
+ Job.getJobManager().addJobChangeListener(this.changeListener);
+ }
+
+ private void setUpImages() {
+ ImageTools imageTools = ImageTools.getInstance();
+
+ imageTools.putIntoRegistry(SLEEPING_JOB_KEY, PROGRESS_FOLDER
+ + SLEEPING_JOB);
+ imageTools.putIntoRegistry(WAITING_JOB_KEY, PROGRESS_FOLDER
+ + WAITING_JOB);
+ imageTools.putIntoRegistry(BLOCKED_JOB_KEY, PROGRESS_FOLDER
+ + BLOCKED_JOB);
+ imageTools.putIntoRegistry(ERROR_JOB_KEY, PROGRESS_FOLDER + ERROR_JOB);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job)
+ */
+ public IProgressMonitor createMonitor(Job job) {
+ return progressFor(job);
+ }
+
+ /**
+ * Return a monitor for the job. Check if we cached a monitor for this job
+ * previously for a long operation timeout check.
+ *
+ * @param job
+ * @return IProgressMonitor
+ */
+ public JobMonitor progressFor(Job job) {
+
+ synchronized (runnableMonitors) {
+ JobMonitor monitor = (JobMonitor) runnableMonitors.get(job);
+ if (monitor == null) {
+ monitor = new JobMonitor(job);
+ runnableMonitors.put(job, monitor);
+ }
+
+ return monitor;
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.ProgressProvider#createProgressGroup()
+ */
+
+ public IProgressMonitor createProgressGroup() {
+ //TODO E4 circular dependency
+ return new GroupInfo(this, finishedJobs);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job,
+ * org.eclipse.core.runtime.IProgressMonitor, int)
+ */
+ public IProgressMonitor createMonitor(Job job, IProgressMonitor group,
+ int ticks) {
+ JobMonitor monitor = progressFor(job);
+ if (group instanceof GroupInfo) {
+ GroupInfo groupInfo = (GroupInfo) group;
+ JobInfo jobInfo = getJobInfo(job);
+ jobInfo.setGroupInfo(groupInfo);
+ jobInfo.setTicks(ticks);
+ groupInfo.addJobInfo(jobInfo);
+ }
+ return monitor;
+ }
+
+ /**
+ * Get the JobInfo for the job. If it does not exist create it.
+ *
+ * @param job
+ * @return JobInfo
+ */
+ JobInfo getJobInfo(Job job) {
+ JobInfo info = internalGetJobInfo(job);
+ if (info == null) {
+ info = jobInfoFactory.getJobInfo(job);
+ jobs.put(job, info);
+ }
+ return info;
+ }
+
+ /**
+ * Return an existing job info for the given Job or <code>null</code> if
+ * there isn't one.
+ *
+ * @param job
+ * @return JobInfo
+ */
+ JobInfo internalGetJobInfo(Job job) {
+ return (JobInfo) jobs.get(job);
+ }
+
+
+ /**
+ * The JobMonitor is the inner class that handles the IProgressMonitor
+ * integration with the ProgressMonitor.
+ */
+ class JobMonitor implements IProgressMonitorWithBlocking {
+ Job job;
+
+ String currentTaskName;
+
+ IProgressMonitorWithBlocking listener;
+
+ /**
+ * Create a monitor on the supplied job.
+ *
+ * @param newJob
+ */
+ JobMonitor(Job newJob) {
+ job = newJob;
+ }
+
+ /**
+ * Add monitor as another monitor that
+ *
+ * @param monitor
+ */
+ void addProgressListener(IProgressMonitorWithBlocking monitor) {
+ listener = monitor;
+ JobInfo info = getJobInfo(job);
+ TaskInfo currentTask = info.getTaskInfo();
+ if (currentTask != null) {
+ listener.beginTask(currentTaskName, currentTask.totalWork);
+ listener.internalWorked(currentTask.preWork);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(String taskName, int totalWork) {
+ JobInfo info = getJobInfo(job);
+ info.beginTask(taskName, totalWork);
+ refreshJobInfo(info);
+ currentTaskName = taskName;
+ if (listener != null) {
+ listener.beginTask(taskName, totalWork);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#done()
+ */
+ public void done() {
+ JobInfo info = getJobInfo(job);
+ info.clearTaskInfo();
+ info.clearChildren();
+ runnableMonitors.remove(job);
+ if (listener != null) {
+ listener.done();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(double work) {
+ JobInfo info = getJobInfo(job);
+ if (info.hasTaskInfo()) {
+ info.addWork(work);
+ refreshJobInfo(info);
+ }
+ if (listener != null) {
+ listener.internalWorked(work);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
+ */
+ public boolean isCanceled() {
+ // Use the internal get so we don't create a Job Info for
+ // a job that is not running (see bug 149857)
+ JobInfo info = internalGetJobInfo(job);
+ if (info == null)
+ return false;
+ return info.isCanceled();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
+ */
+ public void setCanceled(boolean value) {
+ JobInfo info = getJobInfo(job);
+ // Don't bother cancelling twice
+ if (value && !info.isCanceled()) {
+ info.cancel();
+ // Only inform the first time
+ if (listener != null) {
+ listener.setCanceled(value);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
+ */
+ public void setTaskName(String taskName) {
+ JobInfo info = getJobInfo(job);
+ if (info.hasTaskInfo()) {
+ info.setTaskName(taskName);
+ } else {
+ beginTask(taskName, 100);
+ return;
+ }
+ info.clearChildren();
+ refreshJobInfo(info);
+ currentTaskName = taskName;
+ if (listener != null) {
+ listener.setTaskName(taskName);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
+ */
+ public void subTask(String name) {
+ if (name == null) {
+ return;
+ }
+ JobInfo info = getJobInfo(job);
+ info.clearChildren();
+ info.addSubTask(name);
+ refreshJobInfo(info);
+ if (listener != null) {
+ listener.subTask(name);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ internalWorked(work);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
+ */
+ public void clearBlocked() {
+ JobInfo info = getJobInfo(job);
+ info.setBlockedStatus(null);
+ refreshJobInfo(info);
+ if (listener != null) {
+ listener.clearBlocked();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ JobInfo info = getJobInfo(job);
+ info.setBlockedStatus(reason);
+ refreshJobInfo(info);
+ if (listener != null) {
+ listener.setBlocked(reason);
+ }
+ }
+ }
+
+
+
+ /**
+ * Create and return the IJobChangeListener registered with the Job manager.
+ *
+ * @return the created IJobChangeListener
+ */
+ private IJobChangeListener createChangeListener() {
+ return new JobChangeAdapter() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void aboutToRun(IJobChangeEvent event) {
+ JobInfo info = getJobInfo(event.getJob());
+ refreshJobInfo(info);
+ Iterator startListeners = busyListenersForJob(event.getJob())
+ .iterator();
+ while (startListeners.hasNext()) {
+ IJobBusyListener next = (IJobBusyListener) startListeners
+ .next();
+ next.incrementBusy(event.getJob());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void done(IJobChangeEvent event) {
+ if (!PlatformUI.isWorkbenchRunning()) {
+ return;
+ }
+ Iterator startListeners = busyListenersForJob(event.getJob())
+ .iterator();
+ while (startListeners.hasNext()) {
+ IJobBusyListener next = (IJobBusyListener) startListeners
+ .next();
+ next.decrementBusy(event.getJob());
+ }
+
+ final JobInfo info = getJobInfo(event.getJob());
+ removeJobInfo(info);
+ //TODO E4
+// if (event.getResult() != null
+// && event.getResult().getSeverity() == IStatus.ERROR
+// && event
+// .getJob()
+// .getProperty(
+// IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) != Boolean.TRUE) {
+//
+// ExternalServices.getStatusReporter().report(event.getResult(), StatusReporter.SHOW, new Object[0]);
+// }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void scheduled(IJobChangeEvent event) {
+ updateFor(event);
+ if (event.getJob().isUser()) {
+ boolean noDialog = shouldRunInBackground();
+ if (!noDialog) {
+ final IJobChangeEvent finalEvent = event;
+ Job showJob = new UIJob(
+ ProgressMessages.ProgressManager_showInDialogName) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(
+ IProgressMonitor monitor) {
+ progressService.showInDialog(null, finalEvent.getJob());
+ return Status.OK_STATUS;
+ }
+ };
+ showJob.setSystem(true);
+ showJob.schedule();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Update the listeners for the receiver for the event.
+ *
+ * @param event
+ */
+ private void updateFor(IJobChangeEvent event) {
+ if (isInfrastructureJob(event.getJob())) {
+ return;
+ }
+ if (jobs.containsKey(event.getJob())) {
+ refreshJobInfo(getJobInfo(event.getJob()));
+ } else {
+ addJobInfo(jobInfoFactory.getJobInfo(event.getJob()));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#awake(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void awake(IJobChangeEvent event) {
+ updateFor(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#sleeping(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void sleeping(IJobChangeEvent event) {
+
+ if (jobs.containsKey(event.getJob()))// Are we showing this?
+ sleepJobInfo(getJobInfo(event.getJob()));
+ }
+ };
+ }
+
+ /**
+ * The job in JobInfo is now sleeping. Refresh it if we are showing it,
+ * remove it if not.
+ *
+ * @param info
+ */
+ protected void sleepJobInfo(JobInfo info) {
+ if (isInfrastructureJob(info.getJob()))
+ return;
+
+ GroupInfo group = info.getGroupInfo();
+ if (group != null) {
+ sleepGroup(group,info);
+ }
+
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ IJobProgressManagerListener listener = (IJobProgressManagerListener) listenersArray[i];
+ // Is this one the user never sees?
+ if (isNeverDisplaying(info.getJob(), listener.showsDebug()))
+ continue;
+ if (listener.showsDebug())
+ listener.refreshJobInfo(info);
+ else
+ listener.removeJob(info);
+
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.ProgressProvider#getDefaultMonitor()
+ */
+ public IProgressMonitor getDefaultMonitor() {
+ // only need a default monitor for operations the UI thread
+ // and only if there is a display
+ Display display;
+ if (PlatformUI.isWorkbenchRunning() && !PlatformUI.isWorkbenchStarting()) {
+ display = getDisplay();
+ if (!display.isDisposed() && (display.getThread() == Thread.currentThread())) {
+ return new EventLoopProgressMonitor(new NullProgressMonitor());
+ }
+ }
+ return super.getDefaultMonitor();
+ }
+
+ /**
+ * Refresh the group when info is sleeping.
+ * @param group
+ */
+ private void sleepGroup(GroupInfo group, JobInfo info) {
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+
+ IJobProgressManagerListener listener = (IJobProgressManagerListener) listenersArray[i];
+ if (isNeverDisplaying(info.getJob(), listener.showsDebug()))
+ continue;
+
+ if (listener.showsDebug() || group.isActive())
+ listener.refreshGroup(group);
+ else
+ listener.removeGroup(group);
+ }
+ }
+
+
+
+ /**
+ * Add an IJobProgressManagerListener to listen to the changes.
+ *
+ * @param listener
+ */
+ void addListener(IJobProgressManagerListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Remove the supplied IJobProgressManagerListener from the list of
+ * listeners.
+ *
+ * @param listener
+ */
+ void removeListener(IJobProgressManagerListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Refresh the IJobProgressManagerListeners as a result of a change in info.
+ *
+ * @param info
+ */
+ public void refreshJobInfo(JobInfo info) {
+ GroupInfo group = info.getGroupInfo();
+ if (group != null) {
+ refreshGroup(group);
+ }
+
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ IJobProgressManagerListener listener = (IJobProgressManagerListener) listenersArray[i];
+ if (!isCurrentDisplaying(info.getJob(), listener.showsDebug())) {
+ listener.refreshJobInfo(info);
+ }
+ }
+ }
+
+ /**
+ * Refresh the IJobProgressManagerListeners as a result of a change in info.
+ *
+ * @param info
+ */
+ public void refreshGroup(GroupInfo info) {
+
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ ((IJobProgressManagerListener)listenersArray[i]).refreshGroup(info);
+ }
+ }
+
+ /**
+ * Refresh all the IJobProgressManagerListener as a result of a change in
+ * the whole model.
+ */
+ public void refreshAll() {
+
+ pruneStaleJobs();
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ ((IJobProgressManagerListener)listenersArray[i]).refreshAll();
+ }
+
+ }
+
+ /**
+ * Refresh the content providers as a result of a deletion of info.
+ *
+ * @param info
+ * JobInfo
+ */
+ public void removeJobInfo(JobInfo info) {
+
+ Job job = info.getJob();
+ jobs.remove(job);
+ runnableMonitors.remove(job);
+
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ IJobProgressManagerListener listener = (IJobProgressManagerListener) listenersArray[i];
+ if (!isCurrentDisplaying(info.getJob(), listener.showsDebug())) {
+ listener.removeJob(info);
+ }
+ }
+ }
+
+ /**
+ * Remove the group from the roots and inform the listeners.
+ *
+ * @param group
+ * GroupInfo
+ */
+ public void removeGroup(GroupInfo group) {
+
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ ((IJobProgressManagerListener)listenersArray[i]).removeGroup(group);
+ }
+ }
+
+ /**
+ * Refresh the content providers as a result of an addition of info.
+ *
+ * @param info
+ */
+ public void addJobInfo(JobInfo info) {
+ GroupInfo group = info.getGroupInfo();
+ if (group != null) {
+ refreshGroup(group);
+ }
+
+ jobs.put(info.getJob(), info);
+ Object[] listenersArray = listeners.getListeners();
+ for (int i = 0; i < listenersArray.length; i++) {
+ IJobProgressManagerListener listener = (IJobProgressManagerListener) listenersArray[i];
+ if (!isCurrentDisplaying(info.getJob(), listener.showsDebug())) {
+ listener.addJob(info);
+ }
+ }
+ }
+
+ /**
+ * Return whether or not this job is currently displayable.
+ *
+ * @param job
+ * @param debug
+ * If the listener is in debug mode.
+ * @return boolean <code>true</code> if the job is not displayed.
+ */
+ boolean isCurrentDisplaying(Job job, boolean debug) {
+ return isNeverDisplaying(job, debug) || job.getState() == Job.SLEEPING;
+ }
+
+ /**
+ * Return whether or not we even display this job with debug mode set to
+ * debug.
+ *
+ * @param job
+ * @param debug
+ * @return boolean
+ */
+ boolean isNeverDisplaying(Job job, boolean debug) {
+ if (isInfrastructureJob(job)) {
+ return true;
+ }
+ if (debug)
+ return false;
+
+ return job.isSystem();
+ }
+
+ /**
+ * Return whether or not this job is an infrastructure job.
+ *
+ * @param job
+ * @return boolean <code>true</code> if it is never displayed.
+ */
+ private boolean isInfrastructureJob(Job job) {
+ if (Policy.DEBUG_SHOW_ALL_JOBS)
+ return false;
+ return job.getProperty(ProgressManagerUtil.INFRASTRUCTURE_PROPERTY) != null;
+ }
+
+ /**
+ * Return the current job infos filtered on debug mode.
+ *
+ * @param debug
+ * @return JobInfo[]
+ */
+ public JobInfo[] getJobInfos(boolean debug) {
+ synchronized (jobs) {
+ Iterator iterator = jobs.keySet().iterator();
+ Collection result = new ArrayList();
+ while (iterator.hasNext()) {
+ Job next = (Job) iterator.next();
+ if (!isCurrentDisplaying(next, debug)) {
+ result.add(jobs.get(next));
+ }
+ }
+ JobInfo[] infos = new JobInfo[result.size()];
+ result.toArray(infos);
+ return infos;
+ }
+ }
+
+ /**
+ * Return the current root elements filtered on the debug mode.
+ *
+ * @param debug
+ * @return JobTreeElement[]
+ */
+ public JobTreeElement[] getRootElements(boolean debug) {
+ synchronized (jobs) {
+ Iterator iterator = jobs.keySet().iterator();
+ Collection result = new HashSet();
+ while (iterator.hasNext()) {
+ Job next = (Job) iterator.next();
+ if (!isCurrentDisplaying(next, debug)) {
+ JobInfo jobInfo = (JobInfo) jobs.get(next);
+ GroupInfo group = jobInfo.getGroupInfo();
+ if (group == null) {
+ result.add(jobInfo);
+ } else {
+ result.add(group);
+ }
+ }
+ }
+ JobTreeElement[] infos = new JobTreeElement[result.size()];
+ result.toArray(infos);
+ return infos;
+ }
+ }
+
+ /**
+ * Return whether or not there are any jobs being displayed.
+ *
+ * @return boolean
+ */
+ public boolean hasJobInfos() {
+ synchronized (jobs) {
+ Iterator iterator = jobs.keySet().iterator();
+ while (iterator.hasNext()) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns the image descriptor with the given relative path.
+ *
+ * @param source
+ * @return Image
+ */
+ Image getImage(ImageData source) {
+ ImageData mask = source.getTransparencyMask();
+ return new Image(null, source, mask);
+ }
+
+ /**
+ * Returns the image descriptor with the given relative path.
+ *
+ * @param fileSystemPath
+ * The URL for the file system to the image.
+ * @param loader -
+ * the loader used to get this data
+ * @return ImageData[]
+ */
+ ImageData[] getImageData(URL fileSystemPath, ImageLoader loader) {
+ try {
+ InputStream stream = fileSystemPath.openStream();
+ ImageData[] result = loader.load(stream);
+ stream.close();
+ return result;
+ } catch (FileNotFoundException exception) {
+ ProgressManagerUtil.logException(exception);
+ return null;
+ } catch (IOException exception) {
+ ProgressManagerUtil.logException(exception);
+ return null;
+ }
+ }
+
+ /**
+ * Shutdown the receiver.
+ */
+ private void shutdown() {
+ listeners.clear();
+ Job.getJobManager().setProgressProvider(null);
+ Job.getJobManager().removeJobChangeListener(this.changeListener);
+ }
+
+ /**
+ * Add the listener to the family.
+ *
+ * @param family
+ * @param listener
+ */
+ void addListenerToFamily(Object family, IJobBusyListener listener) {
+ synchronized (familyListeners) {
+ Collection currentListeners = (Collection) familyListeners.get(family);
+ if (currentListeners == null) {
+ currentListeners = new HashSet();
+ familyListeners.put(family, currentListeners);
+ }
+ currentListeners.add(listener);
+ }
+ }
+
+ /**
+ * Remove the listener from all families.
+ *
+ * @param listener
+ */
+ void removeListener(IJobBusyListener listener) {
+ synchronized (familyListeners) {
+ Iterator families = familyListeners.keySet().iterator();
+ while (families.hasNext()) {
+ Object next = families.next();
+ Collection currentListeners = (Collection) familyListeners
+ .get(next);
+ currentListeners.remove(listener);
+
+ // Remove any empty listeners
+ if (currentListeners.isEmpty()) {
+ families.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the listeners for the job.
+ *
+ * @param job
+ * @return Collection of IJobBusyListener
+ */
+ private Collection busyListenersForJob(Job job) {
+ if (job.isSystem()) {
+ return Collections.EMPTY_LIST;
+ }
+ synchronized (familyListeners) {
+
+ if (familyListeners.isEmpty()) {
+ return Collections.EMPTY_LIST;
+ }
+
+ Iterator families = familyListeners.keySet().iterator();
+ Collection returnValue = new HashSet();
+ while (families.hasNext()) {
+ Object next = families.next();
+ if (job.belongsTo(next)) {
+ Collection currentListeners = (Collection) familyListeners
+ .get(next);
+ returnValue.addAll(currentListeners);
+ }
+ }
+ return returnValue;
+ }
+ }
+
+ /**
+ * Check to see if there are any stale jobs we have not cleared out.
+ *
+ * @return <code>true</code> if anything was pruned
+ */
+ private boolean pruneStaleJobs() {
+ Object[] jobsToCheck = jobs.keySet().toArray();
+ boolean pruned = false;
+ for (int i = 0; i < jobsToCheck.length; i++) {
+ Job job = (Job) jobsToCheck[i];
+ if (checkForStaleness(job)) {
+ pruned = true;
+ }
+ }
+
+ return pruned;
+ }
+
+ /**
+ * Check the if the job should be removed from the list as it may be stale.
+ *
+ * @param job
+ * @return boolean
+ */
+ boolean checkForStaleness(Job job) {
+ if (job.getState() == Job.NONE) {
+ removeJobInfo(getJobInfo(job));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return whether or not dialogs should be run in the background
+ *
+ * @return <code>true</code> if the dialog should not be shown.
+ */
+ protected boolean shouldRunInBackground() {
+ return Preferences.getBoolean(IProgressConstants.RUN_IN_BACKGROUND);
+ }
+
+ protected Display getDisplay() {
+ return Services.getInstance().getDisplay();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManagerUtil.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManagerUtil.java
new file mode 100644
index 0000000..8ac0406
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressManagerUtil.java
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Lars Vogel <Lars.Vogel@gmail.com> - Bug 422040
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.internal.legacy.StatusUtil;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.service.log.LogService;
+
+/**
+ * The ProgressUtil is a class that contains static utility methods used for the
+ * progress API.
+ */
+
+public class ProgressManagerUtil {
+
+ @SuppressWarnings("unchecked")
+ static class ProgressViewerComparator extends ViewerComparator {
+ @SuppressWarnings("rawtypes")
+ public int compare(Viewer testViewer, Object e1, Object e2) {
+ return ((Comparable) e1).compareTo(e2);
+ }
+
+ @Override
+ public void sort(final Viewer viewer, Object[] elements) {
+ /*
+ * https://bugs.eclipse.org/371354
+ *
+ * This ordering is inherently unstable, since it relies on
+ * modifiable properties of the elements: E.g. the default
+ * implementation in JobTreeElement compares getDisplayString(),
+ * many of whose implementations use getPercentDone().
+ *
+ * JavaSE 7+'s TimSort introduced a breaking change: It now throws a
+ * new IllegalArgumentException for bad comparators. Workaround is
+ * to retry a few times.
+ */
+ for (int retries = 3; retries > 0; retries--) {
+ try {
+ Arrays.sort(elements, new Comparator<Object>() {
+ public int compare(Object a, Object b) {
+ return ProgressViewerComparator.this.compare(viewer, a, b);
+ }
+ });
+ return; // success
+ } catch (IllegalArgumentException e) {
+ // retry
+ }
+ }
+
+ // One last try that will log and throw TimSort's IAE if it happens:
+ super.sort(viewer, elements);
+ }
+ }
+
+ /**
+ * A constant used by the progress support to determine if an operation is
+ * too short to show progress.
+ */
+ public static long SHORT_OPERATION_TIME = 250;
+
+ static final QualifiedName KEEP_PROPERTY = IProgressConstants.KEEP_PROPERTY;
+
+ static final QualifiedName KEEPONE_PROPERTY = IProgressConstants.KEEPONE_PROPERTY;
+
+ static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
+ static final QualifiedName INFRASTRUCTURE_PROPERTY = new QualifiedName(
+ IProgressConstants.PLUGIN_ID, "INFRASTRUCTURE_PROPERTY");//$NON-NLS-1$
+
+ private static String ellipsis = ProgressMessages.ProgressFloatingWindow_EllipsisValue;
+
+ /**
+ * Return a status for the exception.
+ *
+ * @param exception
+ * @return IStatus
+ */
+ static IStatus exceptionStatus(Throwable exception) {
+ return StatusUtil.newStatus(IStatus.ERROR,
+ exception.getMessage() == null ? "" : exception.getMessage(), //$NON-NLS-1$
+ exception);
+ }
+
+ /**
+ * Log the exception for debugging.
+ *
+ * @param exception
+ */
+ static void logException(Throwable exception) {
+ Services.getInstance().getLogService().log(LogService.LOG_ERROR,
+ exception.getMessage() == null ? "" : exception.getMessage(),
+ exception);
+ }
+
+ // /**
+ // * Sets the label provider for the viewer.
+ // *
+ // * @param viewer
+ // */
+ // static void initLabelProvider(ProgressTreeViewer viewer) {
+ // viewer.setLabelProvider(new ProgressLabelProvider());
+ // }
+ /**
+ * Return a viewer comparator for looking at the jobs.
+ *
+ * @return ViewerComparator
+ */
+ public static ViewerComparator getProgressViewerComparator() {
+ return new ProgressViewerComparator();
+ }
+
+ /**
+ * Open the progress view in the supplied window.
+ *
+ * @param window
+ */
+ // TODO E4
+ public static void openProgressView() {
+ Services services = Services.getInstance();
+ MPart progressView = (MPart) services.getModelService().find(
+ ProgressManager.PROGRESS_VIEW_NAME, services.getMWindow());
+ if (progressView == null) {
+ return;
+ }
+ services.getPartService().activate(progressView);
+ }
+
+ /**
+ * Shorten the given text <code>t</code> so that its length doesn't exceed
+ * the given width. The default implementation replaces characters in the
+ * center of the original string with an ellipsis ("..."). Override if you
+ * need a different strategy.
+ *
+ * @param textValue
+ * @param control
+ * @return String
+ */
+
+ static String shortenText(String textValue, Control control) {
+ if (textValue == null) {
+ return null;
+ }
+ GC gc = new GC(control);
+ int maxWidth = control.getBounds().width - 5;
+ int maxExtent = gc.textExtent(textValue).x;
+ if (maxExtent < maxWidth) {
+ gc.dispose();
+ return textValue;
+ }
+ int length = textValue.length();
+ int charsToClip = Math.round(0.95f * length
+ * (1 - ((float) maxWidth / maxExtent)));
+ int secondWord = findSecondWhitespace(textValue, gc, maxWidth);
+ int pivot = ((length - secondWord) / 2) + secondWord;
+ int start = pivot - (charsToClip / 2);
+ int end = pivot + (charsToClip / 2) + 1;
+ while (start >= 0 && end < length) {
+ String s1 = textValue.substring(0, start);
+ String s2 = textValue.substring(end, length);
+ String s = s1 + ellipsis + s2;
+ int l = gc.textExtent(s).x;
+ if (l < maxWidth) {
+ gc.dispose();
+ return s;
+ }
+ start--;
+ end++;
+ }
+ gc.dispose();
+ return textValue;
+ }
+
+ /**
+ * Find the second index of a whitespace. Return the first index if there
+ * isn't one or 0 if there is no space at all.
+ *
+ * @param textValue
+ * @param gc
+ * The GC to test max length
+ * @param maxWidth
+ * The maximim extent
+ * @return int
+ */
+ private static int findSecondWhitespace(String textValue, GC gc,
+ int maxWidth) {
+ int firstCharacter = 0;
+ char[] chars = textValue.toCharArray();
+ // Find the first whitespace
+ for (int i = 0; i < chars.length; i++) {
+ if (Character.isWhitespace(chars[i])) {
+ firstCharacter = i;
+ break;
+ }
+ }
+ // If we didn't find it once don't continue
+ if (firstCharacter == 0) {
+ return 0;
+ }
+ // Initialize to firstCharacter in case there is no more whitespace
+ int secondCharacter = firstCharacter;
+ // Find the second whitespace
+ for (int i = firstCharacter; i < chars.length; i++) {
+ if (Character.isWhitespace(chars[i])) {
+ secondCharacter = i;
+ break;
+ }
+ }
+ // Check that we haven't gone over max width. Throw
+ // out an index that is too high
+ if (gc.textExtent(textValue.substring(0, secondCharacter)).x > maxWidth) {
+ if (gc.textExtent(textValue.substring(0, firstCharacter)).x > maxWidth) {
+ return 0;
+ }
+ return firstCharacter;
+ }
+ return secondCharacter;
+ }
+
+ /**
+ * If there are any modal shells open reschedule openJob to wait until they
+ * are closed. Return true if it rescheduled, false if there is nothing
+ * blocking it.
+ *
+ * @param openJob
+ * @return boolean. true if the job was rescheduled due to modal dialogs.
+ */
+ public static boolean rescheduleIfModalShellOpen(Job openJob,
+ IProgressService progressService) {
+ Shell modal = getModalShellExcluding(null);
+ if (modal == null) {
+ return false;
+ }
+
+ // try again in a few seconds
+ openJob.schedule(progressService.getLongOperationTime());
+ return true;
+ }
+
+ /**
+ * Return whether or not it is safe to open this dialog. If so then return
+ * <code>true</code>. If not then set it to open itself when it has had
+ * ProgressManager#longOperationTime worth of ticks.
+ *
+ * @param dialog
+ * ProgressMonitorJobsDialog that will be opening
+ * @param excludedShell
+ * The shell
+ * @return boolean. <code>true</code> if it can open. Otherwise return
+ * false and set the dialog to tick.
+ */
+ public static boolean safeToOpen(ProgressMonitorJobsDialog dialog,
+ Shell excludedShell) {
+ Shell modal = getModalShellExcluding(excludedShell);
+ if (modal == null) {
+ return true;
+ }
+
+ dialog.watchTicks();
+ return false;
+ }
+
+ /**
+ * Return the modal shell that is currently open. If there isn't one then
+ * return null. If there are stacked modal shells, return the top one.
+ *
+ * @param shell
+ * A shell to exclude from the search. May be <code>null</code>.
+ *
+ * @return Shell or <code>null</code>.
+ */
+
+ public static Shell getModalShellExcluding(Shell shell) {
+
+ // If shell is null or disposed, then look through all shells
+ if (shell == null || shell.isDisposed()) {
+ return getModalChildExcluding(Services.getInstance().getShell()
+ .getShells(), shell);
+ }
+
+ // Start with the shell to exclude and check it's shells
+ return getModalChildExcluding(shell.getShells(), shell);
+ }
+
+ /**
+ * Return the modal shell that is currently open. If there isn't one then
+ * return null.
+ *
+ * @param toSearch shells to search for modal children
+ * @param toExclude shell to ignore
+ * @return the most specific modal child, or null if none
+ */
+ private static Shell getModalChildExcluding(Shell[] toSearch, Shell toExclude) {
+ int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL
+ | SWT.PRIMARY_MODAL;
+
+ // Make sure we don't pick a parent that has a modal child (this can
+ // lock the app)
+ // If we picked a parent with a modal child, use the modal child instead
+
+ for (int i = toSearch.length - 1; i >= 0; i--) {
+ Shell shell = toSearch[i];
+ if(shell.equals(toExclude)) {
+ continue;
+ }
+
+ // Check if this shell has a modal child
+ Shell[] children = shell.getShells();
+ Shell modalChild = getModalChildExcluding(children, toExclude);
+ if (modalChild != null) {
+ return modalChild;
+ }
+
+ // If not, check if this shell is modal itself
+ if (shell.isVisible() && (shell.getStyle() & modal) != 0) {
+ return shell;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Utility method to get the best parenting possible for a dialog. If there
+ * is a modal shell create it so as to avoid two modal dialogs. If not then
+ * return the shell of the active workbench window. If neither can be found
+ * return null.
+ *
+ * @return Shell or <code>null</code>
+ */
+ public static Shell getDefaultParent() {
+ Shell modal = getModalShellExcluding(null);
+ if (modal != null) {
+ return modal;
+ }
+
+ return getNonModalShell();
+ }
+
+ /**
+ * Get the active non modal shell. If there isn't one return null.
+ *
+ * @return Shell
+ */
+ public static Shell getNonModalShell() {
+ MApplication application = Services.getInstance().getMApplication();
+ if (application == null) {
+ // better safe than sorry
+ return null;
+ }
+ MWindow window = application.getSelectedElement();
+ if (window != null) {
+ Object widget = window.getWidget();
+ if (widget instanceof Shell) {
+ return (Shell) widget;
+ }
+ }
+ for (MWindow child : application.getChildren()) {
+ Object widget = child.getWidget();
+ if (widget instanceof Shell) {
+ return (Shell) widget;
+ }
+ }
+ return null;
+ }
+
+
+//TODO E4
+// /**
+// * Animate the closing of a window given the start position down to the
+// * progress region.
+// *
+// * @param startPosition
+// * Rectangle. The position to start drawing from.
+// */
+// public static void animateDown(Rectangle startPosition) {
+// IWorkbenchWindow currentWindow = PlatformUI.getWorkbench()
+// .getActiveWorkbenchWindow();
+// if (currentWindow == null) {
+// return;
+// }
+// WorkbenchWindow internalWindow = (WorkbenchWindow) currentWindow;
+//
+// ProgressRegion progressRegion = internalWindow.getProgressRegion();
+// if (progressRegion == null) {
+// return;
+// }
+// Rectangle endPosition = progressRegion.getControl().getBounds();
+//
+// Point windowLocation = internalWindow.getShell().getLocation();
+// endPosition.x += windowLocation.x;
+// endPosition.y += windowLocation.y;
+//
+// // animate the progress dialog's removal
+// AnimationEngine.createTweakedAnimation(internalWindow.getShell(), 400, startPosition, endPosition);
+// }
+
+// TODO E4
+// /**
+// * Animate the opening of a window given the start position down to the
+// * progress region.
+// *
+// * @param endPosition
+// * Rectangle. The position to end drawing at.
+// */
+// public static void animateUp(Rectangle endPosition) {
+// IWorkbenchWindow currentWindow = PlatformUI.getWorkbench()
+// .getActiveWorkbenchWindow();
+// if (currentWindow == null) {
+// return;
+// }
+// WorkbenchWindow internalWindow = (WorkbenchWindow) currentWindow;
+// Point windowLocation = internalWindow.getShell().getLocation();
+//
+// ProgressRegion progressRegion = internalWindow.getProgressRegion();
+// if (progressRegion == null) {
+// return;
+// }
+// Rectangle startPosition = progressRegion.getControl().getBounds();
+// startPosition.x += windowLocation.x;
+// startPosition.y += windowLocation.y;
+//
+// // animate the progress dialog's arrival
+// AnimationEngine.createTweakedAnimation(internalWindow.getShell(), 400, startPosition, endPosition);
+// }
+
+// /**
+// * Get the shell provider to use in the progress support dialogs. This
+// * provider will try to always parent off of an existing modal shell. If
+// * there isn't one it will use the current workbench window.
+// *
+// * @return IShellProvider
+// */
+// static IShellProvider getShellProvider() {
+// return new IShellProvider() {
+//
+// /*
+// * (non-Javadoc)
+// *
+// * @see org.eclipse.jface.window.IShellProvider#getShell()
+// */
+// @Override
+// public Shell getShell() {
+// return getDefaultParent();
+// }
+// };
+// }
+//
+
+// /**
+// * Return the location of the progress spinner.
+// *
+// * @return URL or <code>null</code> if it cannot be found
+// */
+// public static URL getProgressSpinnerLocation() {
+// try {
+// return new URL(getIconsRoot(), "progress_spinner.png");//$NON-NLS-1$
+// } catch (MalformedURLException e) {
+// return null;
+// }
+// }
+
+
+}
+ \ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMessages.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMessages.java
new file mode 100644
index 0000000..cd109e5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMessages.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ProgressMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.e4.ui.progress.internal.messages";//$NON-NLS-1$
+
+ public static String PendingUpdateAdapter_PendingLabel;
+ public static String JobInfo_DoneMessage;
+ public static String JobInfo_DoneNoProgressMessage;
+ public static String JobInfo_NoTaskNameDoneMessage;
+ public static String JobsViewPreferenceDialog_ShowSystemJobs;
+ public static String JobsViewPreferenceDialog_RunInBackground;
+ public static String JobErrorDialog_CustomJobText;
+ public static String JobInfo_UnknownProgress;
+ public static String JobInfo_Waiting;
+ public static String JobInfo_Sleeping;
+ public static String JobInfo_System;
+ public static String JobInfo_Cancelled;
+ public static String JobInfo_Cancel_Requested;
+ public static String JobInfo_Error;
+ public static String JobInfo_Blocked;
+ public static String JobInfo_Finished;
+ public static String JobInfo_FinishedAt;
+ public static String JobErrorDialog_CloseDialogMessage;
+ public static String InternalError;
+ public static String DeferredTreeContentManager_NotDeferred;
+ public static String DeferredTreeContentManager_AddingChildren;
+ public static String DeferredTreeContentManager_FetchingName;
+ public static String ProgressView_CancelAction;
+ public static String ProgressView_ClearAllAction;
+ public static String ProgressView_NoOperations;
+
+ public static String NewProgressView_RemoveAllJobsToolTip;
+ public static String NewProgressView_CancelJobToolTip;
+ public static String NewProgressView_ClearJobToolTip;
+ public static String NewProgressView_errorDialogTitle;
+ public static String NewProgressView_errorDialogMessage;
+ public static String ProgressAnimationItem_tasks;
+ public static String ProgressAnimationItem_ok;
+ public static String ProgressAnimationItem_error;
+ public static String SubTaskInfo_UndefinedTaskName;
+ public static String DeferredTreeContentManager_ClearJob;
+ public static String ProgressContentProvider_UpdateProgressJob;
+ public static String JobErrorDialog_MultipleErrorsTitle;
+ public static String ProgressManager_openJobName;
+ public static String ProgressManager_showInDialogName;
+ public static String ProgressMonitorJobsDialog_DetailsTitle;
+ public static String ProgressMonitorJobsDialog_HideTitle;
+ public static String ErrorNotificationManager_OpenErrorDialogJob;
+ public static String AnimationManager_AnimationStart;
+ public static String ProgressFloatingWindow_EllipsisValue;
+ public static String BlockedJobsDialog_UserInterfaceTreeElement;
+ public static String BlockedJobsDialog_BlockedTitle;
+ public static String WorkbenchSiteProgressService_CursorJob;
+ public static String ProgressMonitorFocusJobDialog_UserDialogJob;
+ public static String ProgressMonitorFocusJobDialog_CLoseDialogJob;
+ public static String ProgressMonitorFocusJobDialog_RunInBackgroundButton;
+
+ public static String JobErrorDialog_MultipleErrorsMessage;
+ public static String JobErrorDialog_CloseDialogTitle;
+ public static String JobsViewPreferenceDialog_Title;
+ public static String JobErrorDialog_DoNotShowAgainMessage;
+
+ public static String EventLoopProgressMonitor_OpenDialogJobName;
+
+ public static String WorkbenchPreference_RunInBackgroundButton;
+ public static String WorkbenchPreference_RunInBackgroundToolTip;
+
+ public static String TrimCommon_Progress_TrimName;
+
+// public static String ProgressView_ClearAll; //TODO E4
+
+ static {
+ // load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, ProgressMessages.class);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorFocusJobDialog.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorFocusJobDialog.java
new file mode 100644
index 0000000..6a9845c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorFocusJobDialog.java
@@ -0,0 +1,541 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The ProgressMonitorFocusJobDialog is a dialog that shows progress for a
+ * particular job in a modal dialog so as to give a user accustomed to a modal
+ * UI a more familiar feel.
+ */
+class ProgressMonitorFocusJobDialog extends ProgressMonitorJobsDialog {
+ Job job;
+ private boolean showDialog;
+ private ProgressManager progressManager;
+
+ /**
+ * Create a new instance of the receiver with progress reported on the job.
+ *
+ * @param parentShell
+ * The shell this is parented from.
+ */
+ public ProgressMonitorFocusJobDialog(Shell parentShell,
+ IProgressService progressService, ProgressManager progressManager,
+ ContentProviderFactory contentProviderFactory, FinishedJobs finishedJobs) {
+ super(parentShell == null ? ProgressManagerUtil.getNonModalShell()
+ : parentShell, progressService, progressManager,
+ contentProviderFactory, finishedJobs);
+ this.progressManager = progressManager;
+ setShellStyle(getDefaultOrientation() | SWT.BORDER | SWT.TITLE
+ | SWT.RESIZE | SWT.MAX | SWT.MODELESS);
+ setCancelable(true);
+ enableDetailsButton = true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#cancelPressed()
+ */
+ protected void cancelPressed() {
+ job.cancel();
+ super.cancelPressed();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(job.getName());
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ Button runInWorkspace = createButton(
+ parent,
+ IDialogConstants.CLOSE_ID,
+ ProgressMessages.ProgressMonitorFocusJobDialog_RunInBackgroundButton,
+ true);
+ runInWorkspace.addSelectionListener(new SelectionAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ Rectangle shellPosition = getShell().getBounds();
+ job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG,
+ Boolean.FALSE);
+ finishedRun();
+ //TODO E4
+ //ProgressManagerUtil.animateDown(shellPosition);
+ }
+ });
+ runInWorkspace.setCursor(arrowCursor);
+
+ cancel = createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+ cancel.setCursor(arrowCursor);
+
+ createDetailsButton(parent);
+ }
+
+ /**
+ * Returns a listener that will close the dialog when the job completes.
+ *
+ * @return IJobChangeListener
+ */
+ private IJobChangeListener createCloseListener() {
+ return new JobChangeAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.IJobChangeListener#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
+ */
+ public void done(IJobChangeEvent event) {
+ // first of all, make sure this listener is removed
+ event.getJob().removeJobChangeListener(this);
+ if (!PlatformUI.isWorkbenchRunning()) {
+ return;
+ }
+ // nothing to do if the dialog is already closed
+ if (getShell() == null) {
+ return;
+ }
+ Job closeJob = new UIJob(
+ ProgressMessages.ProgressMonitorFocusJobDialog_CLoseDialogJob) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ Shell currentShell = getShell();
+ if (currentShell == null || currentShell.isDisposed()) {
+ return Status.CANCEL_STATUS;
+ }
+ finishedRun();
+ return Status.OK_STATUS;
+ }
+ };
+ closeJob.setSystem(true);
+ closeJob.schedule();
+ }
+ };
+ }
+
+ /**
+ * Return the ProgressMonitorWithBlocking for the receiver.
+ *
+ * @return IProgressMonitorWithBlocking
+ */
+ private IProgressMonitorWithBlocking getBlockingProgressMonitor() {
+ return new IProgressMonitorWithBlocking() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(String name, int totalWork) {
+ final String finalName = name;
+ final int finalWork = totalWork;
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ getProgressMonitor().beginTask(finalName, finalWork);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
+ */
+ public void clearBlocked() {
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ ((IProgressMonitorWithBlocking) getProgressMonitor())
+ .clearBlocked();
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#done()
+ */
+ public void done() {
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ getProgressMonitor().done();
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(double work) {
+ final double finalWork = work;
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ getProgressMonitor().internalWorked(finalWork);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
+ */
+ public boolean isCanceled() {
+ return getProgressMonitor().isCanceled();
+ }
+
+ /**
+ * Run the runnable as an asyncExec if we are already open.
+ *
+ * @param runnable
+ */
+ private void runAsync(final Runnable runnable) {
+
+ if (alreadyClosed) {
+ return;
+ }
+ Shell currentShell = getShell();
+
+ Display display;
+ if (currentShell == null) {
+ display = Display.getDefault();
+ } else {
+ if (currentShell.isDisposed())// Don't bother if it has
+ // been closed
+ return;
+ display = currentShell.getDisplay();
+ }
+
+ display.asyncExec(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ if (alreadyClosed) {
+ return;// Check again as the async may come too
+ // late
+ }
+ Shell shell = getShell();
+ if (shell != null && shell.isDisposed())
+ return;
+
+ runnable.run();
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ final IStatus finalReason = reason;
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ ((IProgressMonitorWithBlocking) getProgressMonitor())
+ .setBlocked(finalReason);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
+ */
+ public void setCanceled(boolean value) {
+ // Just a listener - doesn't matter.
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
+ */
+ public void setTaskName(String name) {
+ final String finalName = name;
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ getProgressMonitor().setTaskName(finalName);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
+ */
+ public void subTask(String name) {
+ final String finalName = name;
+ runAsync(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ getProgressMonitor().subTask(finalName);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ internalWorked(work);
+ }
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.window.Window#open()
+ */
+ public int open() {
+ int result = super.open();
+
+ // add a listener that will close the dialog when the job completes.
+ IJobChangeListener listener = createCloseListener();
+ job.addJobChangeListener(listener);
+ if (job.getState() == Job.NONE) {
+ // if the job completed before we had a chance to add
+ // the listener, just remove the listener and return
+ job.removeJobChangeListener(listener);
+ finishedRun();
+ cleanUpFinishedJob();
+ }
+
+ return result;
+ }
+
+ /**
+ * Opens this dialog for the duration that the given job is running.
+ *
+ * @param jobToWatch
+ * @param originatingShell
+ * The shell this request was created from. Do not block on this
+ * shell.
+ */
+ public void show(Job jobToWatch, final Shell originatingShell) {
+ job = jobToWatch;
+ // after the dialog is opened we can get access to its monitor
+ job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG, Boolean.TRUE);
+
+ progressManager.progressFor(job).addProgressListener(
+ getBlockingProgressMonitor());
+
+ setOpenOnRun(false);
+ aboutToRun();
+ // start with a quick busy indicator. Lock the UI as we
+ // want to preserve modality
+ BusyIndicator.showWhile(getDisplay(),
+ new Runnable() {
+ public void run() {
+ try {
+ Thread
+ .sleep(ProgressManagerUtil.SHORT_OPERATION_TIME);
+ } catch (InterruptedException e) {
+ // Do not log as this is a common operation from the
+ // lock listener
+ }
+ }
+ });
+
+ Job openJob = new UIJob(
+ ProgressMessages.ProgressMonitorFocusJobDialog_UserDialogJob) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+
+ // if the job is done at this point, we don't need the dialog
+ if (job.getState() == Job.NONE) {
+ finishedRun();
+ cleanUpFinishedJob();
+ return Status.CANCEL_STATUS;
+ }
+
+ // now open the progress dialog if nothing else is
+ if (!ProgressManagerUtil.safeToOpen(
+ ProgressMonitorFocusJobDialog.this, originatingShell)) {
+ return Status.CANCEL_STATUS;
+ }
+
+ // Do not bother if the parent is disposed
+ if (getParentShell() != null && getParentShell().isDisposed()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ open();
+
+ return Status.OK_STATUS;
+ }
+ };
+ openJob.setSystem(true);
+ openJob.schedule();
+
+ }
+
+ /**
+ * The job finished before we did anything so clean up the finished
+ * reference.
+ */
+ private void cleanUpFinishedJob() {
+ progressManager.checkForStaleness(job);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Control area = super.createDialogArea(parent);
+ // Give the job info as the initial details
+ getProgressMonitor().setTaskName(
+ progressManager.getJobInfo(this.job)
+ .getDisplayString());
+ return area;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createExtendedDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected void createExtendedDialogArea(Composite parent) {
+ showDialog = (Preferences.getBoolean(IProgressConstants.RUN_IN_BACKGROUND));
+ final Button showUserDialogButton = new Button(parent, SWT.CHECK);
+ showUserDialogButton
+ .setText(ProgressMessages.WorkbenchPreference_RunInBackgroundButton);
+ showUserDialogButton
+ .setToolTipText(ProgressMessages.WorkbenchPreference_RunInBackgroundToolTip);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ gd.horizontalAlignment = GridData.FILL;
+ showUserDialogButton.setLayoutData(gd);
+
+ showUserDialogButton.addSelectionListener(new SelectionAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ showDialog = showUserDialogButton.getSelection();
+ }
+ });
+
+ super.createExtendedDialogArea(parent);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#close()
+ */
+ public boolean close() {
+ if (getReturnCode() != CANCEL) {
+ Preferences.set(IProgressConstants.RUN_IN_BACKGROUND, showDialog);
+ }
+
+ return super.close();
+ }
+
+ protected Display getDisplay() {
+ return Services.getInstance().getDisplay();
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorJobsDialog.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorJobsDialog.java
new file mode 100644
index 0000000..7bd511e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressMonitorJobsDialog.java
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.e4.ui.progress.internal.legacy.Policy;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The ProgressMonitorJobsDialog is the progress monitor dialog used by the
+ * progress service to allow locks to show the current jobs.
+ */
+public class ProgressMonitorJobsDialog extends ProgressMonitorDialog {
+ private DetailedProgressViewer viewer;
+
+ /**
+ * The height of the viewer. Set when the details button is selected.
+ */
+ private int viewerHeight = -1;
+
+ Composite viewerComposite;
+
+ private Button detailsButton;
+
+ private long watchTime = -1;
+
+ protected boolean alreadyClosed = false;
+
+ private IProgressMonitor wrapperedMonitor;
+
+ private IProgressService progressService;
+
+ private ProgressManager progressManager;
+
+ private ContentProviderFactory contentProviderFactory;
+
+ private FinishedJobs finishedJobs;
+
+ //Cache initial enablement in case the enablement state is set
+ //before the button is created
+ protected boolean enableDetailsButton = false;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param parent
+ */
+ public ProgressMonitorJobsDialog(Shell parent,
+ IProgressService progressService, ProgressManager progressManager,
+ ContentProviderFactory contentProviderFactory, FinishedJobs finishedJobs) {
+ super(parent);
+ this.progressService = progressService;
+ this.progressManager = progressManager;
+ this.contentProviderFactory = contentProviderFactory;
+ this.finishedJobs = finishedJobs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite top = (Composite) super.createDialogArea(parent);
+ createExtendedDialogArea(parent);
+ return top;
+ }
+
+ /**
+ * Create the extensions to the dialog area.
+ * @param parent
+ */
+ protected void createExtendedDialogArea(Composite parent) {
+ viewerComposite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ viewerComposite.setLayout(layout);
+ GridData viewerData = new GridData(GridData.FILL_BOTH);
+ viewerData.horizontalSpan = 2;
+ viewerData.heightHint = 0;
+ viewerComposite.setLayoutData(viewerData);
+ }
+
+ /**
+ * The details button has been selected. Open or close the progress viewer
+ * as appropriate.
+ *
+ */
+ void handleDetailsButtonSelect() {
+ Shell shell = getShell();
+ Point shellSize = shell.getSize();
+ Composite composite = (Composite) getDialogArea();
+ if (viewer != null) {
+ viewer.getControl().dispose();
+ viewer = null;
+ composite.layout();
+ shell.setSize(shellSize.x, shellSize.y - viewerHeight);
+ detailsButton.setText(ProgressMessages.ProgressMonitorJobsDialog_DetailsTitle);
+ } else {
+ //Abort if there are no jobs visible
+ if (progressManager.getRootElements(Policy.DEBUG_SHOW_ALL_JOBS).length == 0) {
+ detailsButton.setEnabled(false);
+ return;
+ }
+
+ viewer = new DetailedProgressViewer(viewerComposite, SWT.MULTI
+ | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, progressService, finishedJobs);
+ viewer.setComparator(new ViewerComparator() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public int compare(Viewer testViewer, Object e1, Object e2) {
+ return ((Comparable) e1).compareTo(e2);
+ }
+ });
+
+ viewer.setContentProvider(contentProviderFactory
+ .getProgressViewerContentProvider(viewer, true, false));
+ viewer.setLabelProvider(new ProgressLabelProvider());
+ viewer.setInput(this);
+ GridData viewerData = new GridData(GridData.FILL_BOTH);
+ viewer.getControl().setLayoutData(viewerData);
+ GridData viewerCompositeData = (GridData) viewerComposite.getLayoutData();
+ viewerCompositeData.heightHint = convertHeightInCharsToPixels(10);
+ viewerComposite.layout(true);
+ viewer.getControl().setVisible(true);
+ viewerHeight = viewerComposite.computeTrim(0, 0, 0, viewerCompositeData.heightHint).height;
+ detailsButton.setText(ProgressMessages.ProgressMonitorJobsDialog_HideTitle);
+ shell.setSize(shellSize.x, shellSize.y + viewerHeight);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ super.createButtonsForButtonBar(parent);
+ createDetailsButton(parent);
+ }
+
+ /**
+ * Create a spacer label to get the layout to not bunch the widgets.
+ *
+ * @param parent
+ * The parent of the new button.
+ */
+ protected void createSpacer(Composite parent) {
+ //Make a label to force the spacing
+ Label spacer = new Label(parent, SWT.NONE);
+ spacer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL));
+ }
+
+ /**
+ * Create the details button for the receiver.
+ *
+ * @param parent
+ * The parent of the new button.
+ */
+ protected void createDetailsButton(Composite parent) {
+ detailsButton = createButton(parent, IDialogConstants.DETAILS_ID,
+ ProgressMessages.ProgressMonitorJobsDialog_DetailsTitle,
+ false);
+ detailsButton.addSelectionListener(new SelectionAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ handleDetailsButtonSelect();
+ }
+ });
+ detailsButton.setCursor(arrowCursor);
+ detailsButton.setEnabled(enableDetailsButton);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IconAndMessageDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createButtonBar(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ // create a layout with spacing and margins appropriate for the font
+ // size.
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1; // this is incremented by createButton
+ layout.makeColumnsEqualWidth = false;
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ composite.setLayout(layout);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 2;
+ data.horizontalAlignment = GridData.END;
+ data.grabExcessHorizontalSpace = true;
+ composite.setLayoutData(data);
+ composite.setFont(parent.getFont());
+ // Add the buttons to the button bar.
+ if (arrowCursor == null) {
+ arrowCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_ARROW);
+ }
+ createButtonsForButtonBar(composite);
+ return composite;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#clearCursors()
+ */
+ protected void clearCursors() {
+ if (detailsButton != null && !detailsButton.isDisposed()) {
+ detailsButton.setCursor(null);
+ }
+ super.clearCursors();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#updateForSetBlocked(org.eclipse.core.runtime.IStatus)
+ */
+ protected void updateForSetBlocked(IStatus reason) {
+ if(alreadyClosed)
+ return;
+
+ super.updateForSetBlocked(reason);
+ enableDetails(true);
+ if (viewer == null) {
+ handleDetailsButtonSelect();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#run(boolean,
+ * boolean, org.eclipse.jface.operation.IRunnableWithProgress)
+ */
+ public void run(boolean fork, boolean cancelable,
+ IRunnableWithProgress runnable) throws InvocationTargetException,
+ InterruptedException {
+ //if it is run in the UI Thread don't do anything.
+ if (!fork) {
+ enableDetails(false);
+ }
+ super.run(fork, cancelable, runnable);
+ }
+
+ /**
+ * Set the enable state of the details button now or when it will be
+ * created.
+ *
+ * @param enableState
+ * a boolean to indicate the preferred' state
+ */
+ protected void enableDetails(boolean enableState) {
+ if (detailsButton == null) {
+ enableDetailsButton = enableState;
+ } else {
+ detailsButton.setEnabled(enableState);
+ }
+ }
+
+ /**
+ * Start watching the ticks. When the long operation time has
+ * passed open the dialog.
+ */
+ public void watchTicks() {
+ watchTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Create a monitor for the receiver that wrappers the superclasses monitor.
+ *
+ */
+ public void createWrapperedMonitor() {
+ wrapperedMonitor = new IProgressMonitorWithBlocking() {
+
+ IProgressMonitor superMonitor = ProgressMonitorJobsDialog.super
+ .getProgressMonitor();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(String name, int totalWork) {
+ superMonitor.beginTask(name, totalWork);
+ checkTicking();
+ }
+
+ /**
+ * Check if we have ticked in the last 800ms.
+ */
+ private void checkTicking() {
+ if (watchTime < 0) {
+ return;
+ }
+ if ((System.currentTimeMillis() - watchTime) > progressService.getLongOperationTime()) {
+ watchTime = -1;
+ openDialog();
+ }
+ }
+
+ /**
+ * Open the dialog in the ui Thread
+ */
+ private void openDialog() {
+ if (!PlatformUI.isWorkbenchRunning()) {
+ return;
+ }
+ getUISynchronize().syncExec(new Runnable() {
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ //Reset the watch if it is not safe to open
+ if (!ProgressManagerUtil.safeToOpen(ProgressMonitorJobsDialog.this,null)){
+ watchTicks();
+ return;
+ }
+
+ if (!alreadyClosed) {
+ open();
+ }
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#done()
+ */
+ public void done() {
+ superMonitor.done();
+ checkTicking();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(double work) {
+ superMonitor.internalWorked(work);
+ checkTicking();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
+ */
+ public boolean isCanceled() {
+ return superMonitor.isCanceled();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
+ */
+ public void setCanceled(boolean value) {
+ superMonitor.setCanceled(value);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
+ */
+ public void setTaskName(String name) {
+ superMonitor.setTaskName(name);
+ checkTicking();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
+ */
+ public void subTask(String name) {
+ superMonitor.subTask(name);
+ checkTicking();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ superMonitor.worked(work);
+ checkTicking();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
+ */
+ public void clearBlocked() {
+ //We want to open on blocking too
+ if (superMonitor instanceof IProgressMonitorWithBlocking) {
+ ((IProgressMonitorWithBlocking) superMonitor)
+ .clearBlocked();
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ openDialog();
+ if (superMonitor instanceof IProgressMonitorWithBlocking) {
+ ((IProgressMonitorWithBlocking) superMonitor)
+ .setBlocked(reason);
+ }
+
+ }
+
+ };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#getProgressMonitor()
+ */
+ public IProgressMonitor getProgressMonitor() {
+ if (wrapperedMonitor == null) {
+ createWrapperedMonitor();
+ }
+ return wrapperedMonitor;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.ProgressMonitorDialog#close()
+ */
+ public boolean close() {
+ alreadyClosed = true;//As this sometimes delayed cache if it was already closed
+ boolean result = super.close();
+ if (!result) {//If it fails reset the flag
+ alreadyClosed = false;
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#isResizable()
+ */
+ protected boolean isResizable() {
+ return true;
+ }
+
+ protected Display getUISynchronize() {
+ return Services.getInstance().getDisplay();
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressRegion.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressRegion.java
new file mode 100644
index 0000000..3c42fc2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressRegion.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.progress.internal.legacy.TrimUtil;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The ProgressRegion is class for the region of the workbench where the
+ * progress line and the animation item are shown.
+ */
+public class ProgressRegion {
+ ProgressCanvasViewer viewer;
+
+ ProgressAnimationItem animationItem;
+
+ Composite region;
+
+ private int fWidthHint = SWT.DEFAULT;
+
+ private int fHeightHint = SWT.DEFAULT;
+
+ /**
+ * the side the receiver is placed on
+ */
+ private int side = SWT.BOTTOM;
+
+ private boolean forceHorizontal;
+
+ /**
+ * Create a new instance of the receiver.
+ */
+ public ProgressRegion() {
+ //No default behavior.
+ }
+
+ @Inject
+ AnimationManager animationManager;
+
+ @Inject
+ ContentProviderFactory contentProviderfactory;
+
+ @Inject
+ FinishedJobs finishedJobs;
+
+ /**
+ * Create the contents of the receiver in the parent. Use the window for the
+ * animation item.
+ *
+ * @param parent
+ * The parent widget of the composite.
+ * @param window
+ * The WorkbenchWindow this is in.
+ * @return Control
+ */
+ @PostConstruct
+ public Control createContents(Composite parent) {
+ // Test whether or not 'advanced' graphics are available
+ // If not then we'll 'force' the ProgressBar to always be
+ // HORIZONTAL...
+ //TODO: This should likely be at some 'global' level state
+ GC gc = new GC(parent);
+ gc.setAdvanced(true);
+ forceHorizontal = !gc.getAdvanced();
+ gc.dispose();
+
+ region = new Composite(parent, SWT.NONE) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.widgets.Composite#computeSize(int, int,
+ * boolean)
+ */
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ Point size = super.computeSize(wHint, hHint, changed);
+ if (isHorizontal(side))
+ size.y = TrimUtil.TRIM_DEFAULT_HEIGHT;
+ else {
+ size.x = TrimUtil.TRIM_DEFAULT_HEIGHT;
+ }
+ return size;
+ }
+ };
+
+ GridLayout gl = new GridLayout();
+ gl.marginHeight = 0;
+ gl.marginWidth = 0;
+ if (isHorizontal(side))
+ gl.numColumns = 3;
+ region.setLayout(gl);
+
+ viewer = new ProgressCanvasViewer(region, SWT.NO_FOCUS, 1, 36, isHorizontal(side) ? SWT.HORIZONTAL : SWT.VERTICAL);
+ viewer.setUseHashlookup(true);
+ Control viewerControl = viewer.getControl();
+ GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+ Point viewerSizeHints = viewer.getSizeHints();
+ if (isHorizontal(side)) {
+ gd.widthHint = viewerSizeHints.x;
+ gd.heightHint = viewerSizeHints.y;
+ } else {
+ gd.widthHint = viewerSizeHints.y;
+ gd.heightHint = viewerSizeHints.x;
+ }
+ viewerControl.setLayoutData(gd);
+
+ int widthPreference = animationManager.getPreferredWidth() + 25;
+ animationItem = new ProgressAnimationItem(this,
+ isHorizontal(side) ? SWT.HORIZONTAL : SWT.VERTICAL,
+ animationManager, finishedJobs);
+ animationItem.createControl(region);
+
+ animationItem.setAnimationContainer(new AnimationItem.IAnimationContainer() {
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AnimationItem.IAnimationContainer#animationDone()
+ */
+ public void animationDone() {
+ //Add an extra refresh to the viewer in case
+ //of stale input if the controls are not disposed
+ if (viewer.getControl().isDisposed()) {
+ return;
+ }
+ viewer.refresh();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.AnimationItem.IAnimationContainer#animationStart()
+ */
+ public void animationStart() {
+ // Nothing by default here.
+
+ }
+ });
+ if (isHorizontal(side)) {
+ gd = new GridData(GridData.FILL_VERTICAL);
+ gd.widthHint = widthPreference;
+ } else {
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.heightHint = widthPreference;
+ }
+
+ animationItem.getControl().setLayoutData(gd);
+
+ viewerControl.addMouseListener(new MouseAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent e) {
+ processDoubleClick();
+ }
+ });
+
+ //Never show debug info
+ IContentProvider provider = contentProviderfactory.getProgressViewerContentProvider(viewer,
+ false,false);
+ viewer.setContentProvider(provider);
+ viewer.setInput(provider);
+ viewer.setLabelProvider(new ProgressViewerLabelProvider(viewerControl));
+ viewer.setComparator(ProgressManagerUtil.getProgressViewerComparator());
+ viewer.addFilter(new ViewerFilter() {
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if (element instanceof JobInfo) {
+ JobInfo info= (JobInfo)element;
+ if (info.isBlocked() || info.getJob().getState() == Job.WAITING) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ });
+ return region;
+ }
+
+ /**
+ * Return the animationItem for the receiver.
+ *
+ * @return AnimationItem
+ */
+ public AnimationItem getAnimationItem() {
+ return animationItem;
+ }
+
+ /**
+ * Return the control for the receiver.
+ *
+ * @return Control
+ */
+ public Control getControl() {
+ return region;
+ }
+
+ /**
+ * Process the double click event.
+ */
+ public void processDoubleClick() {
+ ProgressManagerUtil.openProgressView();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.IWindowTrim#dock(int)
+ */
+ public void dock(int dropSide) {
+ int oldSide = side;
+ side = dropSide;
+ if (oldSide == dropSide || (isVertical(oldSide) && isVertical(dropSide)) || (isHorizontal(oldSide) && isHorizontal(dropSide)))
+ return;
+ recreate();
+
+ }
+
+ /**
+ * Answer true if the side is a horizonal one
+ *
+ * @param dropSide
+ * @return <code>true</code> if the side is horizontal
+ */
+ private boolean isHorizontal(int dropSide) {
+ if (forceHorizontal)
+ return true;
+ return dropSide == SWT.TOP || dropSide == SWT.BOTTOM;
+ }
+
+
+ /**
+ * Answer true if the side is a horizonal one
+ *
+ * @param dropSide
+ * @return <code>true</code> if the side is horizontal
+ */
+ private boolean isVertical(int dropSide) {
+ if (forceHorizontal)
+ return false;
+ return dropSide == SWT.LEFT || dropSide == SWT.RIGHT;
+ }
+
+ /**
+ * Recreate the receiver given the new side
+ */
+ private void recreate() {
+ if (region != null && !region.isDisposed()) {
+ Composite parent = region.getParent();
+ boolean animating = animationItem.animationRunning();
+ animationManager.removeItem(animationItem);
+ region.dispose();
+ createContents(parent);
+ if (animating)
+ animationItem.animationStart();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.IWindowTrim#getId()
+ */
+ public String getId() {
+ return "org.eclipse.ui.internal.progress.ProgressRegion"; //$NON-NLS-1$
+ }
+
+ public String getDisplayName() {
+ return ProgressMessages.TrimCommon_Progress_TrimName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.IWindowTrim#getValidSides()
+ */
+ public int getValidSides() {
+ return SWT.BOTTOM | SWT.TOP | SWT.LEFT | SWT.RIGHT ;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.IWindowTrim#isCloseable()
+ */
+ public boolean isCloseable() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.IWindowTrim#handleClose()
+ */
+ public void handleClose() {
+ // nothing to do...
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IWindowTrim#getWidthHint()
+ */
+ public int getWidthHint() {
+ return fWidthHint;
+ }
+
+ /**
+ * Update the width hint for this control.
+ * @param w pixels, or SWT.DEFAULT
+ */
+ public void setWidthHint(int w) {
+ fWidthHint = w;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IWindowTrim#getHeightHint()
+ */
+ public int getHeightHint() {
+ return fHeightHint;
+ }
+
+ /**
+ * Update the height hint for this control.
+ * @param h pixels, or SWT.DEFAULT
+ */
+ public void setHeightHint(int h) {
+ fHeightHint = h;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowTrim#isResizeable()
+ */
+ public boolean isResizeable() {
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceCreationFunction.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceCreationFunction.java
new file mode 100644
index 0000000..1c4d727
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceCreationFunction.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+public class ProgressServiceCreationFunction extends ContextFunction {
+
+ @Override
+ public Object compute(IEclipseContext context, String contextKey) {
+ return ContextInjectionFactory.make(ProgressServiceImpl.class, context);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceImpl.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceImpl.java
new file mode 100644
index 0000000..4894280
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressServiceImpl.java
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.e4.ui.progress.internal.legacy.EventLoopProgressMonitor;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class ProgressServiceImpl implements IProgressService {
+
+ private static final String IMAGE_KEY = "org.eclipse.ui.progress.images"; //$NON-NLS-1$
+
+ private Hashtable imageKeyTable = new Hashtable();
+
+ @Inject
+ @Optional
+ ProgressManager progressManager;
+
+ @Inject
+ @Optional
+ FinishedJobs finishedJobs;
+
+ @Inject
+ @Optional
+ ContentProviderFactory contentProviderFactory;
+
+ @Inject
+ @Optional
+ UISynchronize uiSynchronize;
+
+ @Override
+ public int getLongOperationTime() {
+ return 800;
+ }
+
+ @Override
+ public void registerIconForFamily(ImageDescriptor icon, Object family) {
+ String key = IMAGE_KEY + String.valueOf(imageKeyTable.size());
+ imageKeyTable.put(family, key);
+ ImageRegistry registry = JFaceResources.getImageRegistry();
+
+ // Avoid registering twice
+ if (registry.getDescriptor(key) == null) {
+ registry.put(key, icon);
+ }
+ }
+
+ @Override
+ public void runInUI(IRunnableContext context,
+ IRunnableWithProgress runnable, ISchedulingRule rule)
+ throws InvocationTargetException, InterruptedException {
+ final RunnableWithStatus runnableWithStatus = new RunnableWithStatus(
+ context,
+ runnable, rule);
+ uiSynchronize.syncExec(new Runnable() {
+ public void run() {
+ BusyIndicator.showWhile(getDisplay(), runnableWithStatus);
+ }
+
+ });
+
+ IStatus status = runnableWithStatus.getStatus();
+ if (!status.isOK()) {
+ Throwable exception = status.getException();
+ if (exception instanceof InvocationTargetException)
+ throw (InvocationTargetException) exception;
+ else if (exception instanceof InterruptedException)
+ throw (InterruptedException) exception;
+ else // should be OperationCanceledException
+ throw new InterruptedException(exception.getMessage());
+ }
+ }
+
+ @Override
+ public Image getIconFor(Job job) {
+ Enumeration families = imageKeyTable.keys();
+ while (families.hasMoreElements()) {
+ Object next = families.nextElement();
+ if (job.belongsTo(next)) {
+ return JFaceResources.getImageRegistry().get(
+ (String) imageKeyTable.get(next));
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.IProgressService#busyCursorWhile(org.eclipse.jface.operation.IRunnableWithProgress)
+ */
+ @Override
+ public void busyCursorWhile(final IRunnableWithProgress runnable)
+ throws InvocationTargetException, InterruptedException {
+ final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
+ ProgressManagerUtil.getDefaultParent(), this, progressManager,
+ contentProviderFactory, finishedJobs);
+ dialog.setOpenOnRun(false);
+ final InvocationTargetException[] invokes = new InvocationTargetException[1];
+ final InterruptedException[] interrupt = new InterruptedException[1];
+ // show a busy cursor until the dialog opens
+ Runnable dialogWaitRunnable = new Runnable() {
+ public void run() {
+ try {
+ dialog.setOpenOnRun(false);
+ setUserInterfaceActive(false);
+ dialog.run(true, true, runnable);
+ } catch (InvocationTargetException e) {
+ invokes[0] = e;
+ } catch (InterruptedException e) {
+ interrupt[0] = e;
+ } finally {
+ setUserInterfaceActive(true);
+ }
+ }
+ };
+ busyCursorWhile(dialogWaitRunnable, dialog);
+ if (invokes[0] != null) {
+ throw invokes[0];
+ }
+ if (interrupt[0] != null) {
+ throw interrupt[0];
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.operation.IRunnableContext#run(boolean, boolean,
+ * org.eclipse.jface.operation.IRunnableWithProgress)
+ */
+ public void run(boolean fork, boolean cancelable,
+ IRunnableWithProgress runnable) throws InvocationTargetException,
+ InterruptedException {
+ if (fork == false || cancelable == false) {
+ // backward compatible code
+ final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
+ null, this, progressManager, contentProviderFactory,
+ finishedJobs);
+ dialog.run(fork, cancelable, runnable);
+ return;
+ }
+
+ busyCursorWhile(runnable);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.IProgressService#showInDialog(org.eclipse.swt.widgets.Shell,
+ * org.eclipse.core.runtime.jobs.Job)
+ */
+ @Override
+ public void showInDialog(Shell shell, Job job) {
+ if (shouldRunInBackground()) {
+ return;
+ }
+
+ final ProgressMonitorFocusJobDialog dialog = new ProgressMonitorFocusJobDialog(
+ shell, this, progressManager, contentProviderFactory,
+ finishedJobs);
+ dialog.show(job, shell);
+ }
+
+ /**
+ * Return whether or not dialogs should be run in the background
+ *
+ * @return <code>true</code> if the dialog should not be shown.
+ */
+ protected boolean shouldRunInBackground() {
+ return Preferences.getBoolean(IProgressConstants.RUN_IN_BACKGROUND);
+ }
+
+ private class RunnableWithStatus implements Runnable {
+
+ IStatus status = Status.OK_STATUS;
+ private final IRunnableContext context;
+ private final IRunnableWithProgress runnable;
+ private final ISchedulingRule rule;
+
+ public RunnableWithStatus(IRunnableContext context,
+ IRunnableWithProgress runnable, ISchedulingRule rule) {
+ this.context = context;
+ this.runnable = runnable;
+ this.rule = rule;
+ }
+
+ public void run() {
+ IJobManager manager = Job.getJobManager();
+ try {
+ manager.beginRule(rule, getEventLoopMonitor());
+ context.run(false, false, runnable);
+ } catch (InvocationTargetException e) {
+ status = new Status(IStatus.ERROR, IProgressConstants.PLUGIN_ID, e
+ .getMessage(), e);
+ } catch (InterruptedException e) {
+ status = new Status(IStatus.ERROR, IProgressConstants.PLUGIN_ID, e
+ .getMessage(), e);
+ } catch (OperationCanceledException e) {
+ status = new Status(IStatus.ERROR, IProgressConstants.PLUGIN_ID, e
+ .getMessage(), e);
+ } finally {
+ manager.endRule(rule);
+ }
+ }
+
+ /**
+ * Get a progress monitor that forwards to an event loop monitor.
+ * Override #setBlocked() so that we always open the blocked dialog.
+ *
+ * @return the monitor on the event loop
+ */
+ private IProgressMonitor getEventLoopMonitor() {
+
+ if (PlatformUI.isWorkbenchStarting())
+ return new NullProgressMonitor();
+
+ return new EventLoopProgressMonitor(new NullProgressMonitor()) {
+
+ public void setBlocked(IStatus reason) {
+
+ // Set a shell to open with as we want to create
+ // this
+ // even if there is a modal shell.
+ Dialog.getBlockedHandler().showBlocked(
+ ProgressManagerUtil.getDefaultParent(), this,
+ reason, getTaskName());
+ }
+ };
+ }
+
+ public IStatus getStatus() {
+ return status;
+ }
+
+ }
+
+ /**
+ * Show the busy cursor while the runnable is running. Schedule a job to
+ * replace it with a progress dialog.
+ *
+ * @param dialogWaitRunnable
+ * @param dialog
+ */
+ private void busyCursorWhile(Runnable dialogWaitRunnable,
+ ProgressMonitorJobsDialog dialog) {
+ // create the job that will open the dialog after a delay
+ scheduleProgressMonitorJob(dialog);
+ final Display display = getDisplay();
+ if (display == null) {
+ return;
+ }
+ // show a busy cursor until the dialog opens
+ BusyIndicator.showWhile(display, dialogWaitRunnable);
+ }
+
+ /**
+ * Schedule the job that will open the progress monitor dialog
+ *
+ * @param dialog
+ * the dialog to open
+ */
+ private void scheduleProgressMonitorJob(
+ final ProgressMonitorJobsDialog dialog) {
+
+ final Job updateJob = new UIJob(
+ ProgressMessages.ProgressManager_openJobName) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ setUserInterfaceActive(true);
+ if (ProgressManagerUtil.safeToOpen(dialog, null)) {
+ dialog.open();
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ updateJob.setSystem(true);
+ updateJob.schedule(getLongOperationTime());
+
+ }
+
+ /**
+ * Iterate through all of the windows and set them to be disabled or enabled
+ * as appropriate.'
+ *
+ * @param active
+ * The set the windows will be set to.
+ */
+ private void setUserInterfaceActive(boolean active) {
+ Shell[] shells = getDisplay().getShells();
+ if (active) {
+ for (int i = 0; i < shells.length; i++) {
+ if (!shells[i].isDisposed()) {
+ shells[i].setEnabled(active);
+ }
+ }
+ } else {
+ // Deactive shells in reverse order
+ for (int i = shells.length - 1; i >= 0; i--) {
+ if (!shells[i].isDisposed()) {
+ shells[i].setEnabled(active);
+ }
+ }
+ }
+ }
+
+ protected Display getDisplay() {
+ return Services.getInstance().getDisplay();
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewUpdater.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewUpdater.java
new file mode 100644
index 0000000..f06d377
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewUpdater.java
@@ -0,0 +1,469 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.e4.ui.progress.internal.legacy.PlatformUI;
+
+/**
+ * The ProgressViewUpdater is the singleton that updates viewers.
+ */
+@Creatable
+@Singleton
+public class ProgressViewUpdater implements IJobProgressManagerListener {
+
+ private IProgressUpdateCollector[] collectors;
+
+ Job updateJob;
+
+ UpdatesInfo currentInfo = new UpdatesInfo();
+
+ Object updateLock = new Object();
+
+ @Inject
+ ProgressManager progressManager;
+
+ class MutableBoolean {
+ boolean value;
+ }
+
+ /*
+ * True when update job is scheduled or running. This is used to limit the
+ * update job to no more than once every 100 ms. See bug 258352 and 395645.
+ */
+ MutableBoolean updateScheduled = new MutableBoolean();
+
+
+ /**
+ * The UpdatesInfo is a private class for keeping track of the updates
+ * required.
+ */
+ class UpdatesInfo {
+
+ Collection additions = new HashSet();
+
+ Collection deletions = new HashSet();
+
+ Collection refreshes = new HashSet();
+
+ boolean updateAll = false;
+
+ private UpdatesInfo() {
+ //Create a new instance of the info
+ }
+
+ /**
+ * Add an add update
+ *
+ * @param addition
+ */
+ void add(JobTreeElement addition) {
+ additions.add(addition);
+ }
+
+ /**
+ * Add a remove update
+ *
+ * @param removal
+ */
+ void remove(JobTreeElement removal) {
+ deletions.add(removal);
+ }
+
+ /**
+ * Add a refresh update
+ *
+ * @param refresh
+ */
+ void refresh(JobTreeElement refresh) {
+ refreshes.add(refresh);
+ }
+
+ /**
+ * Reset the caches after completion of an update.
+ */
+ void reset() {
+ additions.clear();
+ deletions.clear();
+ refreshes.clear();
+ updateAll = false;
+ }
+
+ void processForUpdate() {
+ HashSet staleAdditions = new HashSet();
+
+ Iterator additionsIterator = additions.iterator();
+ while (additionsIterator.hasNext()) {
+ JobTreeElement treeElement = (JobTreeElement) additionsIterator
+ .next();
+ if (!treeElement.isActive()) {
+ if (deletions.contains(treeElement)) {
+ staleAdditions.add(treeElement);
+ }
+ }
+ }
+
+ additions.removeAll(staleAdditions);
+
+ HashSet obsoleteRefresh = new HashSet();
+ Iterator refreshIterator = refreshes.iterator();
+ while (refreshIterator.hasNext()) {
+ JobTreeElement treeElement = (JobTreeElement) refreshIterator
+ .next();
+ if (deletions.contains(treeElement)
+ || additions.contains(treeElement)) {
+ obsoleteRefresh.add(treeElement);
+ }
+
+ //Also check for groups that are being added
+ Object parent = treeElement.getParent();
+ if(parent != null && (deletions.contains(parent)
+ || additions.contains(parent))){
+ obsoleteRefresh.add(treeElement);
+ }
+
+ if (!treeElement.isActive()) {
+ //If it is done then delete it
+ obsoleteRefresh.add(treeElement);
+ deletions.add(treeElement);
+ }
+ }
+
+ refreshes.removeAll(obsoleteRefresh);
+
+ }
+ }
+
+ /**
+ * Create a new instance of the receiver.
+ */
+ ProgressViewUpdater() {
+ createUpdateJob();
+ collectors = new IProgressUpdateCollector[0];
+ }
+
+ @PostConstruct
+ void init(MApplication application) {
+ progressManager.addListener(this);
+ application.getContext().set(ProgressViewUpdater.class, this);
+ }
+
+ /**
+ * Add the new collector to the list of collectors.
+ *
+ * @param newCollector
+ */
+ void addCollector(IProgressUpdateCollector newCollector) {
+ IProgressUpdateCollector[] newCollectors = new IProgressUpdateCollector[collectors.length + 1];
+ System.arraycopy(collectors, 0, newCollectors, 0, collectors.length);
+ newCollectors[collectors.length] = newCollector;
+ collectors = newCollectors;
+ }
+
+ /**
+ * Remove the collector from the list of collectors.
+ *
+ * @param provider
+ */
+ void removeCollector(IProgressUpdateCollector provider) {
+ HashSet newCollectors = new HashSet();
+ for (int i = 0; i < collectors.length; i++) {
+ if (!collectors[i].equals(provider)) {
+ newCollectors.add(collectors[i]);
+ }
+ }
+ IProgressUpdateCollector[] newArray = new IProgressUpdateCollector[newCollectors
+ .size()];
+ newCollectors.toArray(newArray);
+ collectors = newArray;
+ //Remove ourselves if there is nothing to update
+ if (collectors.length == 0) {
+ progressManager.removeListener(this);
+ }
+ }
+
+ /**
+ * Schedule an update.
+ */
+ void scheduleUpdate() {
+ if (PlatformUI.isWorkbenchRunning()) {
+ // make sure we don't schedule too often
+ boolean scheduleUpdate = false;
+ synchronized (updateScheduled) {
+ if (!updateScheduled.value || updateJob.getState() == Job.NONE) {
+ updateScheduled.value = scheduleUpdate = true;
+ }
+ }
+ if (scheduleUpdate)
+ updateJob.schedule(100);
+ }
+ }
+
+ /**
+ * Create the update job that handles the updatesInfo.
+ */
+ private void createUpdateJob() {
+ updateJob = new UIJob(ProgressMessages.ProgressContentProvider_UpdateProgressJob) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ synchronized (updateScheduled) {
+ // updates requested while we are running should cause it to
+ // be rescheduled
+ updateScheduled.value = false;
+ }
+ // Abort the job if there isn't anything
+ if (collectors.length == 0) {
+ return Status.CANCEL_STATUS;
+ }
+
+ if (currentInfo.updateAll) {
+ synchronized (updateLock) {
+ currentInfo.reset();
+ }
+ for (int i = 0; i < collectors.length; i++) {
+ collectors[i].refresh();
+ }
+
+ } else {
+ // Lock while getting local copies of the caches.
+ Object[] updateItems;
+ Object[] additionItems;
+ Object[] deletionItems;
+ synchronized (updateLock) {
+ currentInfo.processForUpdate();
+
+ updateItems = currentInfo.refreshes.toArray();
+ additionItems = currentInfo.additions.toArray();
+ deletionItems = currentInfo.deletions.toArray();
+
+ currentInfo.reset();
+ }
+
+ for (int v = 0; v < collectors.length; v++) {
+ IProgressUpdateCollector collector = collectors[v];
+
+ if (updateItems.length > 0) {
+ collector.refresh(updateItems);
+ }
+ if (additionItems.length > 0) {
+ collector.add(additionItems);
+ }
+ if (deletionItems.length > 0) {
+ collector.remove(deletionItems);
+ }
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.Job#canceling()
+ */
+ protected void canceling() {
+ synchronized (updateScheduled) {
+ updateScheduled.value = false;
+ }
+ }
+ };
+ updateJob.setSystem(true);
+ updateJob.setPriority(Job.DECORATE);
+ updateJob.setProperty(ProgressManagerUtil.INFRASTRUCTURE_PROPERTY, new Object());
+
+ }
+
+ /**
+ * Get the updates info that we are using in the receiver.
+ *
+ * @return Returns the currentInfo.
+ */
+ UpdatesInfo getCurrentInfo() {
+ return currentInfo;
+ }
+
+ /**
+ * Refresh the supplied JobInfo.
+ * @param info
+ */
+ public void refresh(JobInfo info) {
+
+ if (isUpdateJob(info.getJob())) {
+ return;
+ }
+
+ synchronized (updateLock) {
+ currentInfo.refresh(info);
+ GroupInfo group = info.getGroupInfo();
+ if (group != null) {
+ currentInfo.refresh(group);
+ }
+ }
+ //Add in a 100ms delay so as to keep priority low
+ scheduleUpdate();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshJobInfo(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void refreshJobInfo(JobInfo info) {
+
+ if (isUpdateJob(info.getJob())) {
+ return;
+ }
+
+ synchronized (updateLock) {
+ currentInfo.refresh(info);
+ }
+ //Add in a 100ms delay so as to keep priority low
+ scheduleUpdate();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void refreshGroup(GroupInfo info) {
+ synchronized (updateLock) {
+ currentInfo.refresh(info);
+ }
+ //Add in a 100ms delay so as to keep priority low
+ scheduleUpdate();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#addGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void addGroup(GroupInfo info) {
+
+ synchronized (updateLock) {
+ currentInfo.add(info);
+ }
+ scheduleUpdate();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#refreshAll()
+ */
+ public void refreshAll() {
+
+ synchronized (updateLock) {
+ currentInfo.updateAll = true;
+ }
+
+ //Add in a 100ms delay so as to keep priority low
+ scheduleUpdate();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#add(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void addJob(JobInfo info) {
+
+ if (isUpdateJob(info.getJob())) {
+ return;
+ }
+
+ synchronized (updateLock) {
+ GroupInfo group = info.getGroupInfo();
+
+ if (group == null) {
+ currentInfo.add(info);
+ } else {
+ currentInfo.refresh(group);
+ }
+ }
+ scheduleUpdate();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#removeJob(org.eclipse.ui.internal.progress.JobInfo)
+ */
+ public void removeJob(JobInfo info) {
+
+ if (isUpdateJob(info.getJob())) {
+ return;
+ }
+
+ synchronized (updateLock) {
+ GroupInfo group = info.getGroupInfo();
+ if (group == null) {
+ currentInfo.remove(info);
+ } else {
+ currentInfo.refresh(group);
+ }
+ }
+ scheduleUpdate();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#removeGroup(org.eclipse.ui.internal.progress.GroupInfo)
+ */
+ public void removeGroup(GroupInfo group) {
+ synchronized (updateLock) {
+ currentInfo.remove(group);
+ }
+ scheduleUpdate();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IJobProgressManagerListener#showsDebug()
+ */
+ public boolean showsDebug() {
+ return Preferences.getBoolean(IProgressConstants.SHOW_SYSTEM_JOBS);
+ }
+
+ /**
+ * Return whether or not this is the update job. This is used to determine
+ * if a final refresh is required.
+ *
+ * @param job
+ * @return boolean <code>true</true> if this is the
+ * update job
+ */
+ boolean isUpdateJob(Job job) {
+ return job.equals(updateJob);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerContentProvider.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerContentProvider.java
new file mode 100644
index 0000000..0062934
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerContentProvider.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.progress.UIJob;
+import org.eclipse.e4.ui.progress.internal.FinishedJobs.KeptJobsListener;
+
+/**
+ * The ProgressViewerContentProvider is the content provider progress viewers.
+ */
+public class ProgressViewerContentProvider extends ProgressContentProvider {
+ protected AbstractProgressViewer progressViewer;
+
+ private KeptJobsListener keptJobListener;
+
+ private boolean showFinished;
+
+ private FinishedJobs finishedJobs;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param structured
+ * The Viewer we are providing content for
+ * @param debug
+ * If true debug information will be shown if the debug flag in
+ * the ProgressManager is true.
+ * @param showFinished
+ * A boolean that indicates whether or not the finished jobs
+ * should be shown.
+ */
+ public ProgressViewerContentProvider(AbstractProgressViewer structured,
+ FinishedJobs finishedJobs, ProgressViewUpdater viewUpdater,
+ ProgressManager progressManager, boolean debug, boolean showFinished) {
+ super(viewUpdater, progressManager, debug);
+ progressViewer = structured;
+ this.finishedJobs = finishedJobs;
+ this.showFinished = showFinished;
+ if (showFinished) {
+ finishedJobs.addListener(getKeptJobListener());
+ }
+ }
+
+ /**
+ * Return a listener for kept jobs.
+ *
+ * @return KeptJobsListener
+ */
+ private KeptJobsListener getKeptJobListener() {
+ keptJobListener = new KeptJobsListener() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.FinishedJobs.KeptJobsListener#finished(org.eclipse.ui.internal.progress.JobTreeElement)
+ */
+ public void finished(JobTreeElement jte) {
+ final JobTreeElement element = jte;
+ Job updateJob = new UIJob("Refresh finished") {//$NON-NLS-1$
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ refresh(new Object[] { element });
+ return Status.OK_STATUS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.progress.WorkbenchJob#shouldSchedule()
+ */
+ public boolean shouldSchedule() {
+ return !progressViewer.getControl().isDisposed();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.progress.WorkbenchJob#shouldRun()
+ */
+ public boolean shouldRun() {
+ return !progressViewer.getControl().isDisposed();
+ }
+ };
+ updateJob.setSystem(true);
+ updateJob.schedule();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.FinishedJobs.KeptJobsListener#removed(org.eclipse.ui.internal.progress.JobTreeElement)
+ */
+ public void removed(JobTreeElement jte) {
+ final JobTreeElement element = jte;
+ Job updateJob = new UIJob("Remove finished") {//$NON-NLS-1$
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (element == null) {
+ refresh();
+ } else {
+ ProgressViewerContentProvider.this
+ .remove(new Object[] { element });
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ updateJob.setSystem(true);
+ updateJob.schedule();
+
+ }
+
+ };
+ return keptJobListener;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IProgressUpdateCollector#refresh()
+ */
+ public void refresh() {
+ progressViewer.refresh(true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.IProgressUpdateCollector#refresh(org.eclipse.ui.internal.progress.JobTreeElement[])
+ */
+ public void refresh(Object[] elements) {
+ Object[] refreshes = getRoots(elements, true);
+ for (int i = 0; i < refreshes.length; i++) {
+ progressViewer.refresh(refreshes[i], true);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ Object[] elements = super.getElements(inputElement);
+
+ if (!showFinished)
+ return elements;
+
+ Set kept = finishedJobs.getKeptAsSet();
+
+ if (kept.size() == 0)
+ return elements;
+
+ Set all = new HashSet();
+
+ for (int i = 0; i < elements.length; i++) {
+ Object element = elements[i];
+ all.add(element);
+ }
+
+ Iterator keptIterator = kept.iterator();
+ while (keptIterator.hasNext()) {
+ JobTreeElement next = (JobTreeElement) keptIterator.next();
+ if (next.getParent() != null && all.contains(next.getParent()))
+ continue;
+ all.add(next);
+
+ }
+
+ return all.toArray();
+ }
+
+ /**
+ * Get the root elements of the passed elements as we only show roots.
+ * Replace the element with its parent if subWithParent is true
+ *
+ * @param elements
+ * the array of elements.
+ * @param subWithParent
+ * sub with parent flag.
+ * @return Object[]
+ */
+ private Object[] getRoots(Object[] elements, boolean subWithParent) {
+ if (elements.length == 0) {
+ return elements;
+ }
+ HashSet roots = new HashSet();
+ for (int i = 0; i < elements.length; i++) {
+ JobTreeElement element = (JobTreeElement) elements[i];
+ if (element.isJobInfo()) {
+ GroupInfo group = ((JobInfo) element).getGroupInfo();
+ if (group == null) {
+ roots.add(element);
+ } else {
+ if (subWithParent) {
+ roots.add(group);
+ }
+ }
+ } else {
+ roots.add(element);
+ }
+ }
+ return roots.toArray();
+ }
+
+ public void add(Object[] elements) {
+ progressViewer.add(elements);
+
+ }
+
+ public void remove(Object[] elements) {
+ progressViewer.remove(elements);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ super.dispose();
+ if (keptJobListener != null) {
+ finishedJobs.removeListener(keptJobListener);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerLabelProvider.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerLabelProvider.java
new file mode 100644
index 0000000..af00341
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ProgressViewerLabelProvider.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The ProgressViewerLabelProvider is the label provider for progress viewers.
+ */
+public class ProgressViewerLabelProvider extends LabelProvider {
+ private Control control;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ JobTreeElement info = (JobTreeElement) element;
+ return ProgressManagerUtil.shortenText(
+ info.getCondensedDisplayString(), control);
+ }
+
+ /**
+ * Create a new instance of the receiver within the control.
+ *
+ * @param progressControl The control that the label is
+ * being created for.
+ */
+ public ProgressViewerLabelProvider(Control progressControl) {
+ super();
+ control = progressControl;
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Services.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Services.java
new file mode 100644
index 0000000..7c5c8a8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/Services.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.contexts.Active;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.statusreporter.StatusReporter;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.service.log.LogService;
+
+public class Services {
+
+ // TODO E4 synchronization needed ?
+
+ @Inject
+ private Display display;
+
+ @Inject
+ @Optional
+ @Named(IServiceConstants.ACTIVE_SHELL)
+ public Shell shell;
+
+ @Inject
+ private MApplication mApplication;
+
+ @Inject
+ @Optional
+ @Active
+ private MWindow window;
+
+ @Inject
+ private EHandlerService eHandlerService;
+
+ @Inject
+ private IProgressService progressService;
+
+ @Inject
+ private EModelService modelService;
+
+ @Inject
+ private EPartService partService;
+
+ @Inject
+ private LogService logService;
+
+ @Inject
+ private StatusReporter statusReporter;
+
+ @Inject
+ private UISynchronize uiSynchronize;
+
+ @Inject
+ IEclipseContext localContext;
+
+ IEclipseContext appContext;
+
+ protected static Services instance;
+
+ Services() {
+ instance = this;
+ }
+
+ @PostConstruct
+ void init() {
+ appContext = mApplication.getContext();
+ appContext.set(Services.class, this);
+ }
+
+ public <T> T getService(Class<T> clazz) {
+ return localContext.get(clazz);
+ }
+
+ public <T> void registerService(Class<T> clazz, T value) {
+ appContext.set(clazz, value);
+ }
+
+ public static Services getInstance() {
+ return instance;
+ }
+
+ public Display getDisplay() {
+ return display != null ? display : getDefaultDisplay();
+ }
+
+ private Display getDefaultDisplay() {
+ Display display = Display.getCurrent();
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ return display;
+ }
+
+ public Shell getShell() {
+ return shell;
+ }
+
+ public UISynchronize getUISynchronize() {
+ return uiSynchronize;
+ }
+
+ public EHandlerService getEHandlerService() {
+ return eHandlerService;
+ }
+
+ public LogService getLogService() {
+ return logService;
+ }
+
+ public StatusReporter getStatusReporter() {
+ return statusReporter;
+ }
+
+ public IProgressService getProgressService() {
+ return progressService;
+ }
+
+ public EModelService getModelService() {
+ return modelService;
+ }
+
+ public EPartService getPartService() {
+ return partService;
+ }
+
+ public MWindow getMWindow() {
+ return window;
+ }
+
+ public MApplication getMApplication() {
+ return mApplication;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/StatusAdapterHelper.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/StatusAdapterHelper.java
new file mode 100644
index 0000000..a7fe954
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/StatusAdapterHelper.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal;
+
+import java.util.HashMap;
+
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.internal.legacy.StatusAdapter;
+
+/**
+ * StatusAdapterHelper is a class for caching {@link StatusAdapter} instances to make sure
+ * they are not created twice within the progress service.
+ * @since 3.3
+ */
+public class StatusAdapterHelper {
+ private static StatusAdapterHelper instance;
+
+ private HashMap map;
+
+ private StatusAdapterHelper() {
+ }
+
+ /**
+ * Return the singleton.
+ * @return StatusAdapterHelper
+ */
+ public static StatusAdapterHelper getInstance() {
+ if (instance == null) {
+ instance = new StatusAdapterHelper();
+ }
+ return instance;
+ }
+
+ /**
+ * Set the {@link StatusAdapter} for the {@link JobInfo}
+ * @param info
+ * @param statusAdapter
+ */
+ public void putStatusAdapter(JobInfo info, StatusAdapter statusAdapter) {
+ if (map == null) {
+ map = new HashMap();
+ }
+ map.put(info, statusAdapter);
+ }
+
+ /**
+ * Return the adapter for this info.
+ * @param info
+ * @return
+ */
+ public StatusAdapter getStatusAdapter(JobInfo info) {
+ if (map == null) {
+ return null;
+ }
+ StatusAdapter statusAdapter = (StatusAdapter) map.remove(info);
+ statusAdapter.setProperty(
+ IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY,
+ Boolean.FALSE);
+ return statusAdapter;
+ }
+
+ public void clear() {
+ if (map != null) {
+ map.clear();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/SubTaskInfo.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/SubTaskInfo.java
new file mode 100644
index 0000000..307fd76
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/SubTaskInfo.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+/**
+ * SubTaskInfo is the class that displays a subtask in the tree.
+ */
+class SubTaskInfo extends JobTreeElement {
+
+ protected String taskName;
+
+ JobInfo jobInfo;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param parentJob
+ * @param name
+ */
+ SubTaskInfo(JobInfo parentJob, String name) {
+ taskName = name;
+ jobInfo = parentJob;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getChildren()
+ */
+ Object[] getChildren() {
+ return ProgressManagerUtil.EMPTY_OBJECT_ARRAY;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString()
+ */
+ String getDisplayString() {
+ if (taskName == null) {
+ return ProgressMessages.SubTaskInfo_UndefinedTaskName;
+ }
+ return taskName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#hasChildren()
+ */
+ boolean hasChildren() {
+ return false;
+ }
+
+ /**
+ * Set the taskName of the receiver.
+ *
+ * @param name
+ */
+ void setTaskName(String name) {
+ if (name == null)
+ taskName = ProgressMessages.SubTaskInfo_UndefinedTaskName;
+ else
+ this.taskName = name;
+ }
+
+ /**
+ * Returns the taskName of the receiver.
+ */
+ String getTaskName() {
+ return taskName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getParent()
+ */
+ public Object getParent() {
+ return jobInfo;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isJobInfo()
+ */
+ boolean isJobInfo() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#isActive()
+ */
+ boolean isActive() {
+ return jobInfo.isActive();
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/TaskInfo.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/TaskInfo.java
new file mode 100644
index 0000000..78981e5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/TaskInfo.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * The TaskInfo is the info on a task with a job. It is assumed that there is
+ * only one task running at a time - any previous tasks in a Job will be
+ * deleted.
+ */
+public class TaskInfo extends SubTaskInfo {
+ double preWork = 0;
+
+ int totalWork = 0;
+
+ /**
+ * Create a new instance of the receiver with the supplied total work and
+ * task name.
+ *
+ * @param parentJobInfo
+ * @param infoName
+ * @param total
+ */
+ TaskInfo(JobInfo parentJobInfo, String infoName, int total) {
+ super(parentJobInfo, infoName);
+ totalWork = total;
+ }
+
+ /**
+ * Add the work increment to the total.
+ *
+ * @param workIncrement
+ */
+ void addWork(double workIncrement) {
+
+ // Don't bother if we are indeterminate
+ if (totalWork == IProgressMonitor.UNKNOWN) {
+ return;
+ }
+ preWork += workIncrement;
+
+ }
+
+ /**
+ * Add the amount of work to the recevier. Update a parent monitor by the
+ * increment scaled to the amount of ticks this represents.
+ *
+ * @param workIncrement
+ * int the amount of work in the receiver
+ * @param parentMonitor
+ * The IProgressMonitor that is also listening
+ * @param parentTicks
+ * the number of ticks this monitor represents
+ */
+ void addWork(double workIncrement, IProgressMonitor parentMonitor,
+ int parentTicks) {
+ // Don't bother if we are indeterminate
+ if (totalWork == IProgressMonitor.UNKNOWN) {
+ return;
+ }
+
+ addWork(workIncrement);
+ parentMonitor.internalWorked(workIncrement * parentTicks / totalWork);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.internal.progress.JobTreeElement#getDisplayString(boolean)
+ */
+ String getDisplayString(boolean showProgress) {
+
+ if (totalWork == IProgressMonitor.UNKNOWN) {
+ return unknownProgress();
+ }
+
+ if (taskName == null) {
+ return getDisplayStringWithoutTask(showProgress);
+ }
+
+ if (showProgress) {
+ String[] messageValues = new String[3];
+ messageValues[0] = String.valueOf(getPercentDone());
+ messageValues[1] = jobInfo.getJob().getName();
+ messageValues[2] = taskName;
+
+ return NLS
+ .bind(ProgressMessages.JobInfo_DoneMessage, messageValues);
+ }
+ String[] messageValues = new String[2];
+ messageValues[0] = jobInfo.getJob().getName();
+ messageValues[1] = taskName;
+
+ return NLS.bind(ProgressMessages.JobInfo_DoneNoProgressMessage,
+ messageValues);
+
+ }
+
+ /**
+ * Get the display String without the task name.
+ *
+ * @param showProgress
+ * Whether or not we are showing progress
+ *
+ * @return String
+ */
+ String getDisplayStringWithoutTask(boolean showProgress) {
+
+ if (!showProgress || totalWork == IProgressMonitor.UNKNOWN) {
+ return jobInfo.getJob().getName();
+ }
+
+ return NLS.bind(ProgressMessages.JobInfo_NoTaskNameDoneMessage, jobInfo
+ .getJob().getName(), String.valueOf(getPercentDone()));
+ }
+
+ /**
+ * Return an integer representing the amount of work completed. If progress
+ * is indeterminate return IProgressMonitor.UNKNOWN.
+ *
+ * @return int IProgressMonitor.UNKNOWN or a value between 0 and 100.
+ */
+ int getPercentDone() {
+ if (totalWork == IProgressMonitor.UNKNOWN) {
+ return IProgressMonitor.UNKNOWN;
+ }
+
+ return Math.min((int) (preWork * 100 / totalWork), 100);
+ }
+
+ /**
+ * Return the progress for a monitor whose totalWork is
+ * <code>IProgressMonitor.UNKNOWN</code>.
+ *
+ * @return String
+ */
+ private String unknownProgress() {
+ if (taskName == null) {
+ return jobInfo.getJob().getName();
+ }
+ String[] messageValues = new String[2];
+ messageValues[0] = jobInfo.getJob().getName();
+ messageValues[1] = taskName;
+ return NLS
+ .bind(ProgressMessages.JobInfo_UnknownProgress, messageValues);
+
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ViewSettingsDialog.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ViewSettingsDialog.java
new file mode 100644
index 0000000..357354f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/ViewSettingsDialog.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The ViewSettingsDialog is an abstract class that
+ * provides some common functionality for view preferences.
+ *
+ * @since 3.1
+ */
+public class ViewSettingsDialog extends Dialog {
+
+ private static int DEFAULTS_BUTTON_ID = 25;
+
+ /**
+ * Create a new instance of the receiver.
+ * @param parentShell
+ */
+ public ViewSettingsDialog(Shell parentShell) {
+ super(parentShell);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
+ */
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == DEFAULTS_BUTTON_ID) {
+ performDefaults();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ /**
+ * Performs special processing when this dialog Defaults button has been pressed.
+ * <p>
+ * This is a framework hook method for subclasses to do special things when
+ * the Defaults button has been pressed.
+ * Subclasses may override, but should call <code>super.performDefaults</code>.
+ * </p>
+ */
+ protected void performDefaults() {
+ //Do nothing by default
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ createButton(parent, DEFAULTS_BUTTON_ID, JFaceResources.getString("defaults"), false); //$NON-NLS-1$
+
+ Label l = new Label(parent, SWT.NONE);
+ l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ l = new Label(parent, SWT.NONE);
+ l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ GridLayout layout = (GridLayout) parent.getLayout();
+ layout.numColumns += 2;
+ layout.makeColumnsEqualWidth = false;
+
+ super.createButtonsForButtonBar(parent);
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/WorkbenchDialogBlockedHandler.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/WorkbenchDialogBlockedHandler.java
new file mode 100644
index 0000000..cc847d9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/WorkbenchDialogBlockedHandler.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.jface.dialogs.IDialogBlockedHandler;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The WorkbenchWizardBlockedHandler is the class that implements the blocked
+ * handler for the workbench.
+ */
+@Creatable
+@Singleton
+public class WorkbenchDialogBlockedHandler implements IDialogBlockedHandler {
+ IProgressMonitor outerMonitor;
+
+ @Inject
+ @Optional
+ IProgressService progressService;
+
+ @Inject
+ @Optional
+ ProgressManager progressManager;
+
+ @Inject
+ @Optional
+ FinishedJobs finishedJobs;
+
+ @Inject
+ @Optional
+ ProgressViewUpdater progressViewUpdater;
+
+
+
+
+ int nestingDepth = 0;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#clearBlocked()
+ */
+ public void clearBlocked() {
+ if (nestingDepth == 0) {
+ return;
+ }
+
+ nestingDepth--;
+
+ if (nestingDepth <= 0) {
+ BlockedJobsDialog.clear(outerMonitor);
+ outerMonitor = null;
+ nestingDepth = 0;
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.swt.widgets.Shell,
+ * org.eclipse.core.runtime.IProgressMonitor,
+ * org.eclipse.core.runtime.IStatus, java.lang.String)
+ */
+ public void showBlocked(Shell parentShell,
+ IProgressMonitor blockingMonitor, IStatus blockingStatus,
+ String blockedName) {
+
+ nestingDepth++;
+ if (outerMonitor == null) {
+ outerMonitor = blockingMonitor;
+ //Try to get a name as best as possible
+ if (blockedName == null && parentShell != null) {
+ blockedName = parentShell.getText();
+ }
+ BlockedJobsDialog.createBlockedDialog(parentShell, blockingMonitor,
+ blockingStatus, blockedName, progressService, finishedJobs,
+ progressViewUpdater, progressManager);
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogBlockedHandler#showBlocked(org.eclipse.core.runtime.IProgressMonitor,
+ * org.eclipse.core.runtime.IStatus, java.lang.String)
+ */
+ public void showBlocked(IProgressMonitor blocking, IStatus blockingStatus,
+ String blockedName) {
+ showBlocked(null, blocking, blockingStatus, blockedName);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/EventLoopProgressMonitor.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/EventLoopProgressMonitor.java
new file mode 100644
index 0000000..74e23a5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/EventLoopProgressMonitor.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.ProgressMonitorWrapper;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.widgets.Display;
+//import org.eclipse.ui.internal.Except.ionHandler;
+
+/**
+ * Used to run an event loop whenever progress monitor methods
+ * are invoked. <p>
+ * This is needed since editor save operations are done in the UI thread.
+ * Although save operations should be written to do the work in the non-UI thread,
+ * this was not done for 1.0, so this was added to keep the UI live
+ * (including allowing the cancel button to work).
+ */
+public class EventLoopProgressMonitor extends ProgressMonitorWrapper implements
+ IProgressMonitorWithBlocking {
+ /**
+ * Threshold for how often the event loop is spun, in ms.
+ */
+ private static int T_THRESH = 100;
+
+ /**
+ * Maximum amount of time to spend processing events, in ms.
+ */
+ private static int T_MAX = 50;
+
+ /**
+ * Last time the event loop was spun.
+ */
+ private long lastTime = System.currentTimeMillis();
+
+ /**
+ * The task name is the name of the current task
+ * in the event loop.
+ */
+ private String taskName;
+
+ /**
+ * Constructs a new instance of the receiver and forwards to monitor.
+ * @param monitor
+ */
+ public EventLoopProgressMonitor(IProgressMonitor monitor) {
+ super(monitor);
+ }
+
+ /**
+ * @see IProgressMonitor#beginTask
+ */
+ public void beginTask(String name, int totalWork) {
+ super.beginTask(name, totalWork);
+ taskName = name;
+ runEventLoop();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
+ */
+ public void clearBlocked() {
+ Dialog.getBlockedHandler().clearBlocked();
+ }
+
+ /**
+ * @see IProgressMonitor#done
+ */
+ public void done() {
+ super.done();
+ taskName = null;
+ runEventLoop();
+ }
+
+ /**
+ * @see IProgressMonitor#internalWorked
+ */
+ public void internalWorked(double work) {
+ super.internalWorked(work);
+ runEventLoop();
+ }
+
+ /**
+ * @see IProgressMonitor#isCanceled
+ */
+ public boolean isCanceled() {
+ runEventLoop();
+ return super.isCanceled();
+ }
+
+ /**
+ * Runs an event loop.
+ */
+ private void runEventLoop() {
+ // Only run the event loop so often, as it is expensive on some platforms
+ // (namely Motif).
+ long t = System.currentTimeMillis();
+ if (t - lastTime < T_THRESH) {
+ return;
+ }
+ lastTime = t;
+ // Run the event loop.
+ Display disp = Display.getDefault();
+ if (disp == null) {
+ return;
+ }
+
+ //TODO E4
+ //Initialize an exception handler from the window class.
+// ExceptionHandler handler = ExceptionHandler.getInstance();
+
+ for (;;) {
+ try {
+ if (!disp.readAndDispatch()) {
+ break;
+ }
+ } catch (Throwable e) {//Handle the exception the same way as the workbench
+ //TODO E4
+// handler.handleException(e);
+ break;
+ }
+
+ // Only run the event loop for so long.
+ // Otherwise, this would never return if some other thread was
+ // constantly generating events.
+ if (System.currentTimeMillis() - t > T_MAX) {
+ break;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ Dialog.getBlockedHandler().showBlocked(this, reason, taskName);
+ }
+
+ /**
+ * @see IProgressMonitor#setCanceled
+ */
+ public void setCanceled(boolean b) {
+ super.setCanceled(b);
+ taskName = null;
+ runEventLoop();
+ }
+
+ /**
+ * @see IProgressMonitor#setTaskName
+ */
+ public void setTaskName(String name) {
+ super.setTaskName(name);
+ taskName = name;
+ runEventLoop();
+ }
+
+ /**
+ * @see IProgressMonitor#subTask
+ */
+ public void subTask(String name) {
+ //Be prepared in case the first task was null
+ if (taskName == null) {
+ taskName = name;
+ }
+ super.subTask(name);
+ runEventLoop();
+ }
+
+ /**
+ * @see IProgressMonitor#worked
+ */
+ public void worked(int work) {
+ super.worked(work);
+ runEventLoop();
+ }
+
+ /**
+ * Return the name of the current task.
+ * @return Returns the taskName.
+ */
+ protected String getTaskName() {
+ return taskName;
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/PlatformUI.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/PlatformUI.java
new file mode 100644
index 0000000..3362718
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/PlatformUI.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+//TODO E4
+public class PlatformUI {
+
+ public static boolean isWorkbenchRunning() {
+ return true;
+ }
+
+ public static boolean isWorkbenchStarting() {
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/Policy.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/Policy.java
new file mode 100644
index 0000000..222e033
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/Policy.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+/**
+ * A common facility for parsing the <code>org.eclipse.ui/.options</code>
+ * file.
+ *
+ * @since 2.1
+ */
+public class Policy {
+ public static boolean DEFAULT = false;
+
+
+ /**
+ * Whether or not to show system jobs at all times.
+ */
+ public static boolean DEBUG_SHOW_ALL_JOBS = DEFAULT;
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusAdapter.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusAdapter.java
new file mode 100644
index 0000000..4194621
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusAdapter.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+
+/**
+ * <p>
+ * The StatusAdapter wraps an instance of IStatus subclass and can hold
+ * additional information either by using properties or by adding a new adapter. Used during
+ * status handling process.
+ * </p>
+ *
+ * @since 3.3
+ */
+public class StatusAdapter implements IAdaptable {
+
+ static final String PROPERTY_PREFIX = IProgressConstants.PROPERTY_PREFIX
+ + ".workbench.statusHandlers.adapters"; //$NON-NLS-1$
+
+ public static final QualifiedName TITLE_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "title"); //$NON-NLS-1$
+
+ public static final QualifiedName TIMESTAMP_PROPERTY = new QualifiedName(
+ PROPERTY_PREFIX, "timestamp"); //$NON-NLS-1$
+
+ private IStatus status;
+
+ private HashMap properties;
+
+ private HashMap adapters;
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param status
+ * the status to wrap. May not be <code>null</code>.
+ */
+ public StatusAdapter(IStatus status) {
+ this.status = status;
+ }
+
+ /**
+ * Associates new object which is an instance of the given class with this
+ * adapter. object will be returned when {@link IAdaptable#getAdapter(Class)}
+ * is called on the receiver with {@link Class} adapter as a parameter.
+ *
+ * @param adapter
+ * the adapter class
+ * @param object
+ * the adapter instance
+ */
+ public void addAdapter(Class adapter, Object object) {
+ if (adapters == null) {
+ adapters = new HashMap();
+ }
+ adapters.put(adapter, object);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @Override
+ public Object getAdapter(Class adapter) {
+ if (adapters == null) {
+ return null;
+ }
+ return adapters.get(adapter);
+ }
+
+ /**
+ * Returns the wrapped status.
+ *
+ * @return the wrapped status set in the constructor or in
+ * <code>setStatus(IStatus)</code>. Will not be <code>null</code>.
+ */
+ public IStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets a new status for this adapter.
+ *
+ * @param status
+ * the status to set. May not be <code>null</code>.
+ */
+ public void setStatus(IStatus status) {
+ this.status = status;
+ }
+
+ /**
+ * Returns the value of the adapter's property identified by the given key,
+ * or <code>null</code> if this adapter has no such property.
+ *
+ * @param key
+ * the qualified name of the property
+ * @return the value of the property, or <code>null</code> if this adapter
+ * has no such property
+ */
+ public Object getProperty(QualifiedName key) {
+ if (properties == null) {
+ return null;
+ }
+ return properties.get(key);
+ }
+
+ /**
+ * Sets the value of the receiver's property identified by the given key.
+ *
+ * @param key
+ * the qualified name of the property
+ * @param value
+ * the value of the property
+ */
+ public void setProperty(QualifiedName key, Object value) {
+ if (properties == null) {
+ properties = new HashMap();
+ }
+ properties.put(key, value);
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusUtil.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusUtil.java
new file mode 100644
index 0000000..61bface
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/StatusUtil.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+
+/**
+ * Utility class to create status objects.
+ *
+ * @private - This class is an internal implementation class and should
+ * not be referenced or subclassed outside of the workbench
+ */
+public class StatusUtil {
+
+ /**
+ * Answer a flat collection of the passed status and its recursive children
+ */
+ protected static List flatten(IStatus aStatus) {
+ List result = new ArrayList();
+
+ if (aStatus.isMultiStatus()) {
+ IStatus[] children = aStatus.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ IStatus currentChild = children[i];
+ if (currentChild.isMultiStatus()) {
+ Iterator childStatiiEnum = flatten(currentChild).iterator();
+ while (childStatiiEnum.hasNext()) {
+ result.add(childStatiiEnum.next());
+ }
+ } else {
+ result.add(currentChild);
+ }
+ }
+ } else {
+ result.add(aStatus);
+ }
+
+ return result;
+ }
+
+ /**
+ * This method must not be called outside the workbench.
+ *
+ * Utility method for creating status.
+ */
+ protected static IStatus newStatus(IStatus[] stati, String message,
+ Throwable exception) {
+
+ Assert.isTrue(message != null);
+ Assert.isTrue(message.trim().length() != 0);
+
+ return new MultiStatus(IProgressConstants.PLUGIN_ID, IStatus.ERROR,
+ stati, message, exception);
+ }
+
+ public static Throwable getCause(Throwable exception) {
+ // Figure out which exception should actually be logged -- if the given exception is
+ // a wrapper, unwrap it
+ Throwable cause = null;
+ if (exception != null) {
+ if (exception instanceof CoreException) {
+ // Workaround: CoreException contains a cause, but does not actually implement getCause().
+ // If we get a CoreException, we need to manually unpack the cause. Otherwise, use
+ // the general-purpose mechanism. Remove this branch if CoreException ever implements
+ // a correct getCause() method.
+ CoreException ce = (CoreException)exception;
+ cause = ce.getStatus().getException();
+ } else {
+ // use reflect instead of a direct call to getCause(), to allow compilation against JCL Foundation (bug 80053)
+ try {
+ Method causeMethod = exception.getClass().getMethod("getCause", new Class[0]); //$NON-NLS-1$
+ Object o = causeMethod.invoke(exception, new Object[0]);
+ if (o instanceof Throwable) {
+ cause = (Throwable) o;
+ }
+ }
+ catch (NoSuchMethodException e) {
+ // ignore
+ } catch (IllegalArgumentException e) {
+ // ignore
+ } catch (IllegalAccessException e) {
+ // ignore
+ } catch (InvocationTargetException e) {
+ // ignore
+ }
+ }
+
+ if (cause == null) {
+ cause = exception;
+ }
+ }
+
+ return cause;
+ }
+
+ /**
+ * This method must not be called outside the workbench.
+ *
+ * Utility method for creating status.
+ * @param severity
+ * @param message
+ * @param exception
+ * @return {@link IStatus}
+ */
+ public static IStatus newStatus(int severity, String message,
+ Throwable exception) {
+
+ String statusMessage = message;
+ if (message == null || message.trim().length() == 0) {
+ if (exception.getMessage() == null) {
+ statusMessage = exception.toString();
+ } else {
+ statusMessage = exception.getMessage();
+ }
+ }
+
+ return new Status(severity, IProgressConstants.PLUGIN_ID, severity,
+ statusMessage, getCause(exception));
+ }
+
+ /**
+ * This method must not be called outside the workbench.
+ *
+ * Utility method for creating status.
+ * @param children
+ * @param message
+ * @param exception
+ * @return {@link IStatus}
+ */
+ public static IStatus newStatus(List children, String message,
+ Throwable exception) {
+
+ List flatStatusCollection = new ArrayList();
+ Iterator iter = children.iterator();
+ while (iter.hasNext()) {
+ IStatus currentStatus = (IStatus) iter.next();
+ Iterator childrenIter = flatten(currentStatus).iterator();
+ while (childrenIter.hasNext()) {
+ flatStatusCollection.add(childrenIter.next());
+ }
+ }
+
+ IStatus[] stati = new IStatus[flatStatusCollection.size()];
+ flatStatusCollection.toArray(stati);
+ return newStatus(stati, message, exception);
+ }
+
+ /**
+ * Returns a localized message describing the given exception. If the given exception does not
+ * have a localized message, this returns the string "An error occurred".
+ *
+ * @param exception
+ * @return
+ */
+ public static String getLocalizedMessage(Throwable exception) {
+ String message = exception.getLocalizedMessage();
+
+ if (message != null) {
+ return message;
+ }
+
+ // Workaround for the fact that CoreException does not implement a getLocalizedMessage() method.
+ // Remove this branch when and if CoreException implements getLocalizedMessage()
+ if (exception instanceof CoreException) {
+ CoreException ce = (CoreException)exception;
+ return ce.getStatus().getMessage();
+ }
+
+ //TODO localize
+// return WorkbenchMessages.StatusUtil_errorOccurred;
+ return "ERROR OCCURRED";
+ }
+
+
+
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/TrimUtil.java b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/TrimUtil.java
new file mode 100644
index 0000000..b83705a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/legacy/TrimUtil.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.progress.internal.legacy;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * Simple class to provide some common internal Trim support.
+ *
+ * @since 3.2
+ *
+ */
+public class TrimUtil {
+
+ /**
+ * Default height for workbench trim.
+ */
+ public static final int TRIM_DEFAULT_HEIGHT;
+ static {
+ Shell s = new Shell(Display.getCurrent(), SWT.NONE);
+ s.setLayout(new GridLayout());
+ ToolBar t = new ToolBar(s, SWT.NONE);
+ t.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ ToolItem ti = new ToolItem(t, SWT.PUSH);
+ ti.setImage(JFaceResources.getImageRegistry().get(Dialog.DLG_IMG_MESSAGE_INFO));
+ s.layout();
+ int toolItemHeight = t.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+ GC gc = new GC(s);
+ Point fontSize = gc.textExtent("Wg"); //$NON-NLS-1$
+ gc.dispose();
+ TRIM_DEFAULT_HEIGHT = Math.max(toolItemHeight, fontSize.y);
+ s.dispose();
+
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/messages.properties b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/messages.properties
new file mode 100644
index 0000000..7964b41
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.progress/src/org/eclipse/e4/ui/progress/internal/messages.properties
@@ -0,0 +1,76 @@
+###############################################################################
+# Copyright (c) 2003, 2009 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+# Sebastian Davids <sdavids@gmx.de> - Fix for Bug 132158 [Progress] Job, Operation, Task used interchangably
+###############################################################################
+PendingUpdateAdapter_PendingLabel=Pending...
+JobInfo_DoneMessage = ({0}%) {1}: {2}
+JobInfo_DoneNoProgressMessage = {0}: {1}
+JobInfo_NoTaskNameDoneMessage = {0}: ({1}%)
+JobsViewPreferenceDialog_ShowSystemJobs=&Show sleeping and system operations
+JobsViewPreferenceDialog_RunInBackground=&Run jobs in the background
+JobErrorDialog_CustomJobText=Custom Operation Action
+JobInfo_UnknownProgress = {0}: {1}
+JobInfo_Waiting = {0} (Waiting)
+JobInfo_Sleeping = {0} (Sleeping)
+JobInfo_System = System: {0}
+JobInfo_Cancelled = {0} (Canceled)
+JobInfo_Cancel_Requested = {0} (Cancel Requested)
+JobInfo_Error = {0} (Time of error: {1})
+JobInfo_Blocked = {0} (Blocked: {1})
+JobInfo_Finished = {0} (Finished)
+JobInfo_FinishedAt = {0} (Finished at {1})
+JobErrorDialog_CloseDialogMessage=Performing this action will close the error dialog and clear the errors being displayed.
+InternalError = An internal error has occurred.
+DeferredTreeContentManager_NotDeferred=Not an IDeferredWorkbenchAdapter
+DeferredTreeContentManager_AddingChildren=Adding children
+DeferredTreeContentManager_FetchingName = Fetching children of {0}
+ProgressView_CancelAction=&Cancel
+ProgressView_ClearAllAction=Remove &All Finished Operations
+ProgressView_NoOperations=No operations to display at this time.
+
+NewProgressView_RemoveAllJobsToolTip=Remove All Finished Operations
+NewProgressView_CancelJobToolTip=Cancel Operation
+NewProgressView_ClearJobToolTip=Remove From View
+NewProgressView_errorDialogTitle= Error Occurred
+NewProgressView_errorDialogMessage= Operation Finished with Error
+ProgressAnimationItem_tasks=Shows background operations in Progress view
+ProgressAnimationItem_ok=Operation ''{0}'' returned result; press button for details
+ProgressAnimationItem_error=Operation ''{0}'' finished with errors; press button for details
+SubTaskInfo_UndefinedTaskName=Undefined
+DeferredTreeContentManager_ClearJob=Clear
+ProgressContentProvider_UpdateProgressJob=Update Progress
+JobErrorDialog_MultipleErrorsTitle=Multiple Errors have Occurred
+ProgressManager_openJobName=Open progress monitor
+ProgressManager_showInDialogName=Show In Dialog
+
+ProgressMonitorJobsDialog_DetailsTitle=&Details >>
+ProgressMonitorJobsDialog_HideTitle=<< &Details
+ErrorNotificationManager_OpenErrorDialogJob=Open error dialog
+AnimationManager_AnimationStart=Animation start
+ProgressFloatingWindow_EllipsisValue=...
+
+BlockedJobsDialog_UserInterfaceTreeElement=Waiting User Operation
+BlockedJobsDialog_BlockedTitle=User Operation is Waiting
+WorkbenchSiteProgressService_CursorJob=Change cursor
+ProgressMonitorFocusJobDialog_UserDialogJob=Open user dialog
+ProgressMonitorFocusJobDialog_CLoseDialogJob=Close dialog
+ProgressMonitorFocusJobDialog_RunInBackgroundButton=Run in &Background
+
+JobErrorDialog_MultipleErrorsMessage=Multiple operations have reported errors. Select an error to view its details.
+JobErrorDialog_CloseDialogTitle=OK to Close?
+JobsViewPreferenceDialog_Title=Progress Preferences
+JobErrorDialog_DoNotShowAgainMessage=Don't &show this again
+
+EventLoopProgressMonitor_OpenDialogJobName=Open Blocked Dialog
+
+WorkbenchPreference_RunInBackgroundButton=Always r&un in background
+WorkbenchPreference_RunInBackgroundToolTip=Run long operations in the background where possible
+
+TrimCommon_Progress_TrimName=&Progress
diff --git a/examples/org.eclipse.e4.ui.examples.job/.classpath b/examples/org.eclipse.e4.ui.examples.job/.classpath
new file mode 100644
index 0000000..deb6736
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/examples/org.eclipse.e4.ui.examples.job/.cvsignore b/examples/org.eclipse.e4.ui.examples.job/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/examples/org.eclipse.e4.ui.examples.job/.project b/examples/org.eclipse.e4.ui.examples.job/.project
new file mode 100644
index 0000000..85267cb
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.e4.ui.examples.job</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.core.runtime.prefs b/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.jdt.core.prefs b/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c537b63
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/examples/org.eclipse.e4.ui.examples.job/META-INF/MANIFEST.MF b/examples/org.eclipse.e4.ui.examples.job/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..938450e
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Progress Examples Plug-in
+Bundle-SymbolicName: org.eclipse.e4.ui.examples.job;singleton:=true
+Bundle-Version: 0.1.0
+Bundle-ClassPath: ProgressExamples.jar
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Export-Package: org.eclipse.e4.ui.examples.jobs,
+ org.eclipse.e4.ui.examples.jobs.views
+Require-Bundle: org.eclipse.core.resources,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text,
+ org.eclipse.e4.ui.progress;bundle-version="0.1.0",
+ org.eclipse.swt,
+ org.eclipse.e4.ui.di,
+ org.eclipse.jface;bundle-version="3.10.0"
+Eclipse-AutoStart: true
+Import-Package: javax.annotation;version="1.1.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.core.di.annotations
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/examples/org.eclipse.e4.ui.examples.job/about.html b/examples/org.eclipse.e4.ui.examples.job/about.html
new file mode 100644
index 0000000..4602330
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 2, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/examples/org.eclipse.e4.ui.examples.job/build.properties b/examples/org.eclipse.e4.ui.examples.job/build.properties
new file mode 100644
index 0000000..384a829
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/build.properties
@@ -0,0 +1,6 @@
+source.ProgressExamples.jar = src/
+bin.includes = plugin.xml,\
+ icons/,\
+ *.jar,\
+ ProgressExamples.jar,\
+ META-INF/
diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/job_view.gif b/examples/org.eclipse.e4.ui.examples.job/icons/job_view.gif
new file mode 100644
index 0000000..81fb7b4
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/icons/job_view.gif
Binary files differ
diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif b/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif
new file mode 100644
index 0000000..34fb3c9
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif
Binary files differ
diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif b/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif
new file mode 100644
index 0000000..0d71e42
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif
Binary files differ
diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/tree_view.gif b/examples/org.eclipse.e4.ui.examples.job/icons/tree_view.gif
new file mode 100644
index 0000000..ce8bdb9
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/icons/tree_view.gif
Binary files differ
diff --git a/examples/org.eclipse.e4.ui.examples.job/job_factory_view.e4xmi b/examples/org.eclipse.e4.ui.examples.job/job_factory_view.e4xmi
new file mode 100644
index 0000000..e5ab741
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/job_factory_view.e4xmi
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmi:id="_igBBMG_1EeO3G4cNJzljEA">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="children" parentElementId="_SeXUC-8EEd6FC9cDb6iV7g" positionInList="first">
+ <elements xsi:type="basic:Part" xmi:id="_j3Yf8G_5EeO3G4cNJzljEA" elementId="org.eclipse.ui.examples.jobs.views.JobsView" contributionURI="bundleclass://org.eclipse.e4.ui.examples.job/org.eclipse.e4.ui.examples.jobs.views.JobsView" label="Job Factory" iconURI="platform:/plugin/org.eclipse.e4.ui.examples.job/icons/job_view.gif" closeable="true">
+ <tags>View</tags>
+ <tags>categoryTag:General</tags>
+ </elements>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/examples/org.eclipse.e4.ui.examples.job/plugin.xml b/examples/org.eclipse.e4.ui.examples.job/plugin.xml
new file mode 100644
index 0000000..4fac4cf
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+ <extension
+ id="org.eclipse.e4.ui.examples.job.model"
+ point="org.eclipse.e4.workbench.model">
+ <fragment
+ uri="progress_view.e4xmi">
+ </fragment>
+ <fragment
+ uri="job_factory_view.e4xmi">
+ </fragment>
+ </extension>
+
+</plugin>
diff --git a/examples/org.eclipse.e4.ui.examples.job/pom.xml b/examples/org.eclipse.e4.ui.examples.job/pom.xml
new file mode 100644
index 0000000..43cd042
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 Eclipse Foundation.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Distribution License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/org/documents/edl-v10.php
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>eclipse.platform.ui</artifactId>
+ <groupId>eclipse.platform.ui</groupId>
+ <version>4.4.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+ <groupId>org.eclipse.ui</groupId>
+ <artifactId>org.eclipse.e4.ui.examples.job</artifactId>
+ <version>0.1.0</version>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/examples/org.eclipse.e4.ui.examples.job/programmatic_progress_view.e4xmi b/examples/org.eclipse.e4.ui.examples.job/programmatic_progress_view.e4xmi
new file mode 100644
index 0000000..d00f988
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/programmatic_progress_view.e4xmi
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_igBBMG_1EeO3G4cNJzljEA">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_iZEnQIQjEeOJOIhruxA5nw" featurename="addons" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="application:Addon" xmi:id="_zd72cIQjEeOJOIhruxA5nw" elementId="org.eclipse.e4.demo.contacts.jobs.addon.progressmanager" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressViewAddon"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="children" parentElementId="org.eclipse.e4.demo.contacts.partstacks.second" positionInList="first">
+ <elements xsi:type="basic:Part" xmi:id="_j3Yf8G_5EeO3G4cNJzljEA" elementId="org.eclipse.e4.ui.progress.ProgressView" containerData="" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgrammaticProgressView" label="E4 Progress" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/progress/pview.png" closeable="true">
+ <tags>View</tags>
+ <tags>categoryTag:General</tags>
+ <tags>active</tags>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="trimBars" parentElementId="org.eclipse.e4.demo.contacts.main" positionInList="">
+ <elements xsi:type="basic:TrimBar" xmi:id="_lcYOoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.trimbar.0" side="Bottom">
+ <children xsi:type="menu:ToolControl" xmi:id="_peGXoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.toolcontrol.0" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.internal.ProgressRegion"/>
+ </elements>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/examples/org.eclipse.e4.ui.examples.job/progress_view.e4xmi b/examples/org.eclipse.e4.ui.examples.job/progress_view.e4xmi
new file mode 100644
index 0000000..a35c8be
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/progress_view.e4xmi
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:commands="http://www.eclipse.org/ui/2010/UIModel/application/commands" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_igBBMG_1EeO3G4cNJzljEA">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_iZEnQIQjEeOJOIhruxA5nw" featurename="addons" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="application:Addon" xmi:id="_zd72cIQjEeOJOIhruxA5nw" elementId="org.eclipse.e4.demo.contacts.jobs.addon.progressmanager" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressViewAddon"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="children" parentElementId="org.eclipse.e4.demo.contacts.partstacks.second" positionInList="first">
+ <elements xsi:type="basic:Part" xmi:id="_j3Yf8G_5EeO3G4cNJzljEA" elementId="org.eclipse.e4.ui.progress.ProgressView" containerData="" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ProgressView" label="E4 Progress" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/progress/pview.png" closeable="true">
+ <tags>View</tags>
+ <tags>categoryTag:General</tags>
+ <tags>active</tags>
+ <handlers xmi:id="_LA4DQHX1EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.handlers.clearAll" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.ClearAllHandler" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ <handlers xmi:id="_BYE10HYdEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handler.showPreferences" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.OpenPreferenceDialogHandler" command="_IX1dQHYdEeOGuo0e7MGxvQ"/>
+ <menus xmi:id="_rv030HYYEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.menu">
+ <tags>ViewMenu</tags>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_FgL3gHYZEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handledmenuitem.0" label="Clear All" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_Qe7jYHYhEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.handledmenuitem.1" label="Preferences" command="_IX1dQHYdEeOGuo0e7MGxvQ"/>
+ </menus>
+ <toolbar xmi:id="_a-JNsHX0EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.toolbar">
+ <children xsi:type="menu:HandledToolItem" xmi:id="_hTniAHX0EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.toolbar.clearAll" label="" iconURI="platform:/plugin/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png" command="_Cf0oMHX1EeOL1rlhtuWd8w"/>
+ </toolbar>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8IDN0HX0EeOL1rlhtuWd8w" featurename="commands" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="commands:Command" xmi:id="_Cf0oMHX1EeOL1rlhtuWd8w" elementId="org.eclipse.e4.ui.views.progress.commands.clearAll" commandName="Clear All" description="Clear All"/>
+ <elements xsi:type="commands:Command" xmi:id="_IX1dQHYdEeOGuo0e7MGxvQ" elementId="org.eclipse.e4.ui.views.progress.commands.showPreferences" commandName="Show Preferences" description="Show Preferences"/>
+ <elements xsi:type="commands:Command" xmi:id="_726IYJWOEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.commands.openProgressView" commandName="Open Progress View"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_8jAhoG_4EeO3G4cNJzljEA" featurename="trimBars" parentElementId="org.eclipse.e4.demo.contacts.main" positionInList="">
+ <elements xsi:type="basic:TrimBar" xmi:id="_lcYOoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.trimbar.0" side="Bottom">
+ <children xsi:type="menu:ToolControl" xmi:id="_peGXoIfxEeOFHvFErFdA4A" elementId="org.eclipse.e4.ui.examples.job.toolcontrol.0" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.internal.ProgressRegion"/>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_2nrN8JWPEeOLZ7rxqbmDow" featurename="handlers" parentElementId="org.eclipse.e4.demo.contacts.application">
+ <elements xsi:type="commands:Handler" xmi:id="_h2PmYJWPEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.handlers.openProgressView" contributionURI="bundleclass://org.eclipse.e4.ui.progress/org.eclipse.e4.ui.progress.OpenProgressViewHandler" command="_726IYJWOEeOLZ7rxqbmDow"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="__pfzwJWPEeOLZ7rxqbmDow" featurename="bindings" parentElementId="_SeXUEO8EEd6FC9cDb6iV7x">
+ <elements xsi:type="commands:KeyBinding" xmi:id="_JKsdMJWQEeOLZ7rxqbmDow" elementId="org.eclipse.e4.ui.views.progress.keybinding.openProgressView" keySequence="M1+P" command="_726IYJWOEeOLZ7rxqbmDow"/>
+ </fragments>
+</fragment:ModelFragments>
diff --git a/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJob.java b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJob.java
new file mode 100644
index 0000000..e056929
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJob.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.examples.jobs;
+
+import java.net.URL;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ * Base class for a simple test job with configurable parameters
+ */
+public class TestJob extends Job {
+ /**
+ * A family identifier for all test jobs
+ */
+ public static final Object FAMILY_TEST_JOB = new Object();
+ /**
+ * Total duration that the test job should sleep, in milliseconds.
+ */
+ private final long duration;
+ /**
+ * Whether the test job should fail.
+ */
+ private final boolean failure;
+ /**
+ * Whether the job should report unknown progress.
+ */
+ private final boolean unknown;
+ private final boolean reschedule;
+ private final long rescheduleWait;
+
+ /**
+ * Creates a new test job
+ *
+ * @param duration
+ * Total time that the test job should sleep, in milliseconds.
+ * @param lock
+ * Whether the job should use a workspace scheduling rule
+ * @param failure
+ * Whether the job should fail
+ * @param indeterminate
+ * Whether the job should report indeterminate progress
+ * @param rescheduleWait
+ * @param reschedule
+ */
+ public TestJob(long duration, boolean lock, boolean failure,
+ boolean indeterminate, boolean reschedule, long rescheduleWait) {
+ super("Test job"); //$NON-NLS-1$
+ this.duration = duration;
+ this.failure = failure;
+ this.unknown = indeterminate;
+ this.reschedule = reschedule;
+ this.rescheduleWait = rescheduleWait;
+
+ setProperty(IProgressConstants.ICON_PROPERTY,
+ getImageDescriptor("icons/sample.gif"));
+ if (lock)
+ setRule(ResourcesPlugin.getWorkspace().getRoot());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
+ */
+ @Override
+ public boolean belongsTo(Object family) {
+ if (family instanceof TestJob) {
+ return true;
+ }
+ return family == FAMILY_TEST_JOB;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.internal.jobs.InternalJob#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ if (failure) {
+ MultiStatus result = new MultiStatus(
+ "org.eclipse.ui.examples.jobs", 1, "This is the MultiStatus message", new RuntimeException("This is the MultiStatus exception")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ result
+ .add(new Status(
+ IStatus.ERROR,
+ "org.eclipse.ui.examples.jobs", 1, "This is the child status message", new RuntimeException("This is the child exception"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return result;
+ }
+ final long sleep = 10;
+ int ticks = (int) (duration / sleep);
+ if (this.unknown)
+ monitor.beginTask(toString(), IProgressMonitor.UNKNOWN);
+ else
+ monitor.beginTask(toString(), ticks);
+ try {
+ for (int i = 0; i < ticks; i++) {
+ if (monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ monitor.subTask("Processing tick #" + i); //$NON-NLS-1$
+ try {
+ Thread.sleep(sleep);
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
+ }
+ monitor.worked(1);
+ }
+ } finally {
+ if (reschedule)
+ schedule(rescheduleWait);
+ monitor.done();
+ }
+ return Status.OK_STATUS;
+ }
+
+ private static ImageDescriptor getImageDescriptor(
+ String relativePath) {
+ URL url = FileLocator.find(Platform
+ .getBundle("org.eclipse.e4.ui.examples.job"), new Path(
+ relativePath), null);
+ return ImageDescriptor.createFromURL(url);
+ }
+} \ No newline at end of file
diff --git a/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJobRule.java b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJobRule.java
new file mode 100644
index 0000000..dd74b6b
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/TestJobRule.java
@@ -0,0 +1,43 @@
+package org.eclipse.e4.ui.examples.jobs;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+
+/**
+ * TestJobRule is a scheduling rules that makes all jobs sequential.
+ *
+ */
+public class TestJobRule implements ISchedulingRule {
+ private int jobOrder;
+
+ public TestJobRule(int order) {
+ jobOrder = order;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean contains(ISchedulingRule rule) {
+ if (rule instanceof IResource || rule instanceof TestJobRule)
+ return true;
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
+ */
+ public boolean isConflicting(ISchedulingRule rule) {
+ if (!(rule instanceof TestJobRule))
+ return false;
+ return ((TestJobRule) rule).getJobOrder() >= jobOrder;
+ }
+
+ /**
+ * Return the order of this rule.
+ * @return
+ */
+ public int getJobOrder() {
+ return jobOrder;
+ }
+
+}
diff --git a/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/UITestJob.java b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/UITestJob.java
new file mode 100644
index 0000000..214d776
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/UITestJob.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.examples.jobs;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.progress.UIJob;
+/**
+ * Base class for a simple test UI job with configurable parameters
+ */
+public class UITestJob extends UIJob {
+ private final long duration;
+ private final boolean failure;
+ private final boolean unknown;
+ public UITestJob(long duration, boolean lock, boolean failure, boolean indeterminate) {
+ super("Test job"); //$NON-NLS-1$
+ this.duration = duration;
+ this.failure = failure;
+ this.unknown = indeterminate;
+
+ if (lock)
+ setRule(ResourcesPlugin.getWorkspace().getRoot());
+ }
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (failure)
+ throw new RuntimeException();
+ final long sleep = 10;
+ int ticks = (int) (duration / sleep);
+ if(unknown)
+ monitor.beginTask(toString(), IProgressMonitor.UNKNOWN);
+ else
+ monitor.beginTask(toString(), ticks);
+ try {
+ for (int i = 0; i < ticks; i++) {
+ if (monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ monitor.subTask("Processing tick #" + i); //$NON-NLS-1$
+ try {
+ Thread.sleep(sleep);
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
+ }
+ monitor.worked(1);
+ }
+ } finally {
+ monitor.done();
+ }
+ return Status.OK_STATUS;
+ }
+} \ No newline at end of file
diff --git a/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/views/JobsView.java b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/views/JobsView.java
new file mode 100644
index 0000000..d8b599e
--- /dev/null
+++ b/examples/org.eclipse.e4.ui.examples.job/src/org/eclipse/e4/ui/examples/jobs/views/JobsView.java
@@ -0,0 +1,597 @@
+package org.eclipse.e4.ui.examples.jobs.views;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.contexts.Active;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.examples.jobs.TestJob;
+import org.eclipse.e4.ui.examples.jobs.TestJobRule;
+import org.eclipse.e4.ui.examples.jobs.UITestJob;
+import org.eclipse.e4.ui.progress.IProgressConstants;
+import org.eclipse.e4.ui.progress.IProgressService;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * A view that allows a user to create jobs of various types, and interact with
+ * and test other job-related APIs.
+ */
+public class JobsView {
+ private Combo durationField;
+ private Button lockField, failureField, threadField, systemField,
+ userField, groupField, rescheduleField, keepField, keepOneField,
+ unknownField, gotoActionField;
+ private Text quantityField, delayField, rescheduleDelay;
+ private Button schedulingRuleField;
+ private Button noPromptField;
+
+ Composite parent;
+
+ @Inject
+ @Optional
+ IProgressService progressService;
+
+ @Inject
+ @Optional
+ @Active
+ Shell shell;
+
+
+ protected void busyCursorWhile() {
+ try {
+ final long duration = getDuration();
+ final boolean shouldLock = lockField.getSelection();
+ progressService.busyCursorWhile(
+ new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor) {
+ if (shouldLock)
+ doRunInWorkspace(duration, monitor);
+ else
+ doRun(duration, monitor);
+ }
+
+ });
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ // ignore - interrupt means cancel in this context
+ }
+ }
+
+ protected void createJobs() {
+ int jobCount = Integer.parseInt(quantityField.getText());
+ boolean ui = threadField.getSelection();
+ long duration = getDuration();
+ boolean lock = lockField.getSelection();
+ boolean failure = failureField.getSelection();
+ boolean noPrompt = noPromptField.getSelection();
+ boolean system = systemField.getSelection();
+ boolean useGroup = groupField.getSelection();
+ boolean unknown = unknownField.getSelection();
+ boolean user = userField.getSelection();
+ boolean reschedule = rescheduleField.getSelection();
+ final long rescheduleWait = Long.parseLong(rescheduleDelay.getText());
+ boolean keep = keepField.getSelection();
+ boolean keepOne = keepOneField.getSelection();
+ boolean gotoAction = gotoActionField.getSelection();
+ boolean schedulingRule = schedulingRuleField.getSelection();
+
+ int groupIncrement = IProgressMonitor.UNKNOWN;
+ IProgressMonitor group = new NullProgressMonitor();
+ int total = IProgressMonitor.UNKNOWN;
+
+ if (jobCount > 1) {
+ total = 100;
+ groupIncrement = 100 / jobCount;
+ }
+
+ if (useGroup) {
+ group = Platform.getJobManager().createProgressGroup();
+ group.beginTask("Group", total); //$NON-NLS-1$
+ }
+
+ long delay = Integer.parseInt(delayField.getText());
+ for (int i = 0; i < jobCount; i++) {
+ Job result;
+ if (ui)
+ result = new UITestJob(duration, lock, failure, unknown);
+ else
+ result = new TestJob(duration, lock, failure, unknown,
+ reschedule, rescheduleWait);
+
+ result.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean
+ .valueOf(keep));
+ result.setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean
+ .valueOf(keepOne));
+ result.setProperty(
+ IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY,
+ Boolean.valueOf(noPrompt));
+ if (gotoAction)
+ result.setProperty(IProgressConstants.ACTION_PROPERTY,
+ new Action("Pop up a dialog") { //$NON-NLS-1$
+ @Override
+ public void run() {
+ MessageDialog
+ .openInformation(
+ parent.getShell(),
+ "Goto Action", "The job can have an action associated with it"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+
+ result.setProgressGroup(group, groupIncrement);
+ result.setSystem(system);
+ result.setUser(user);
+
+ if (schedulingRule)
+ result.setRule(new TestJobRule(i));
+ result.schedule(delay);
+ }
+ }
+
+ /**
+ * @see ViewPart#createPartControl(Composite)
+ */
+ @PostConstruct
+ public void createPartControl(Composite parent) {
+ this.parent = parent;
+ Composite body = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.makeColumnsEqualWidth = false;
+ body.setLayout(layout);
+
+ createEntryFieldGroup(body);
+ createPushButtonGroup(body);
+ createCheckboxGroup(body);
+ }
+
+ /**
+ * Create all push button parts for the jobs view.
+ *
+ * @param parent
+ */
+ private void createPushButtonGroup(Composite parent) {
+ Composite group = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ group.setLayout(layout);
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ // create jobs
+ Button create = new Button(group, SWT.PUSH);
+ create.setText("Create jobs"); //$NON-NLS-1$
+ create
+ .setToolTipText("Creates and schedules jobs according to above parameters"); //$NON-NLS-1$
+ create.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ create.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ createJobs();
+ }
+ });
+
+ // busy cursor while
+ Button busyWhile = new Button(group, SWT.PUSH);
+ busyWhile.setText("busyCursorWhile"); //$NON-NLS-1$
+ busyWhile.setToolTipText("Uses IProgressService.busyCursorWhile"); //$NON-NLS-1$
+ busyWhile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ busyWhile.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ busyCursorWhile();
+ }
+ });
+ // progress monitor dialog with fork=false
+ Button noFork = new Button(group, SWT.PUSH);
+ noFork.setText("runInUI"); //$NON-NLS-1$
+ noFork.setToolTipText("Uses IProgressService.runInUI"); //$NON-NLS-1$
+ noFork.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ noFork.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ progressNoFork();
+ }
+ });
+
+ // progress monitor dialog with fork=false
+ Button exception = new Button(group, SWT.PUSH);
+ exception.setText("Runtime Exception"); //$NON-NLS-1$
+ exception.setToolTipText("NullPointerException when running"); //$NON-NLS-1$
+ exception.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ exception.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ jobWithRuntimeException();
+ }
+ });
+
+ // join the running test jobs
+ Button join = new Button(group, SWT.PUSH);
+ join.setText("Join Test Jobs"); //$NON-NLS-1$
+ join.setToolTipText("IJobManager.join() on test jobs"); //$NON-NLS-1$
+ join.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ join.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ joinTestJobs();
+ }
+ });
+
+ // join the running test jobs
+ Button sleep = new Button(group, SWT.PUSH);
+ sleep.setText("Sleep"); //$NON-NLS-1$
+ sleep.setToolTipText("Calls sleep() on all TestJobs"); //$NON-NLS-1$
+ sleep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ sleep.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ doSleep();
+ }
+ });
+
+ // join the running test jobs
+ Button wake = new Button(group, SWT.PUSH);
+ wake.setText("WakeUp"); //$NON-NLS-1$
+ wake.setToolTipText("Calls wakeUp() on all TestJobs"); //$NON-NLS-1$
+ wake.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ wake.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ doWakeUp();
+ }
+ });
+
+ // show in dialog
+ Button showInDialog = new Button(group, SWT.PUSH);
+ showInDialog.setText("showInDialog"); //$NON-NLS-1$
+ showInDialog.setToolTipText("Uses IProgressService.showInDialog"); //$NON-NLS-1$
+ showInDialog.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ showInDialog.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ showInDialog();
+ }
+ });
+
+ }
+
+ /**
+ * Test the showInDialog API
+ *
+ */
+ protected void showInDialog() {
+
+ Job showJob = new Job("Show In Dialog") {//$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ monitor.beginTask("Run in dialog", 100);//$NON-NLS-1$
+
+ for (int i = 0; i < 100; i++) {
+ if (monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
+ }
+ monitor.worked(1);
+
+ }
+ return Status.OK_STATUS;
+
+ }
+ };
+ showJob.schedule();
+ progressService.showInDialog(shell, showJob);
+
+ }
+
+ /**
+ * Wakes up all sleeping test jobs.
+ */
+ protected void doWakeUp() {
+ Platform.getJobManager().wakeUp(TestJob.FAMILY_TEST_JOB);
+ }
+
+ /**
+ * Puts to sleep all waiting test jobs.
+ */
+ protected void doSleep() {
+ Platform.getJobManager().sleep(TestJob.FAMILY_TEST_JOB);
+ }
+
+ /**
+ * @param body
+ */
+ private void createEntryFieldGroup(Composite body) {
+ // duration
+ Label label = new Label(body, SWT.NONE);
+ label.setText("Duration:"); //$NON-NLS-1$
+ durationField = new Combo(body, SWT.DROP_DOWN | SWT.READ_ONLY);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+ durationField.setLayoutData(data);
+ durationField.add("0"); //$NON-NLS-1$
+ durationField.add("1 millisecond"); //$NON-NLS-1$
+ durationField.add("1 second"); //$NON-NLS-1$
+ durationField.add("10 seconds"); //$NON-NLS-1$
+ durationField.add("1 minute"); //$NON-NLS-1$
+ durationField.add("10 minutes"); //$NON-NLS-1$
+ durationField.select(4);
+
+ // delay
+ label = new Label(body, SWT.NONE);
+ label.setText("Start delay (ms):"); //$NON-NLS-1$
+ delayField = new Text(body, SWT.BORDER);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+ delayField.setLayoutData(data);
+ delayField.setText("0"); //$NON-NLS-1$
+
+ // quantity
+ label = new Label(body, SWT.NONE);
+ label.setText("Quantity:"); //$NON-NLS-1$
+ quantityField = new Text(body, SWT.BORDER);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+ quantityField.setLayoutData(data);
+ quantityField.setText("1"); //$NON-NLS-1$
+
+ // reschedule delay
+ label = new Label(body, SWT.NONE);
+ label.setText("Reschedule Delay (ms):"); //$NON-NLS-1$
+ rescheduleDelay = new Text(body, SWT.BORDER);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+ rescheduleDelay.setLayoutData(data);
+ rescheduleDelay.setText("1000"); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates all of the checkbox buttons.
+ */
+ private void createCheckboxGroup(Composite parent) {
+ Composite group = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ group.setLayout(layout);
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ // lock
+ lockField = new Button(group, SWT.CHECK);
+ lockField.setText("Lock the workspace"); //$NON-NLS-1$
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ lockField.setLayoutData(data);
+
+ // system
+ systemField = new Button(group, SWT.CHECK);
+ systemField.setText("System job"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ systemField.setLayoutData(data);
+
+ // thread
+ threadField = new Button(group, SWT.CHECK);
+ threadField.setText("Run in UI thread"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ threadField.setLayoutData(data);
+
+ // groups
+ groupField = new Button(group, SWT.CHECK);
+ groupField.setText("Run in Group"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ groupField.setLayoutData(data);
+
+ // reschedule
+ rescheduleField = new Button(group, SWT.CHECK);
+ rescheduleField.setText("Reschedule"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ rescheduleField.setLayoutData(data);
+
+ // keep
+ keepField = new Button(group, SWT.CHECK);
+ keepField.setText("Keep"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ keepField.setLayoutData(data);
+
+ // keep one
+ keepOneField = new Button(group, SWT.CHECK);
+ keepOneField.setText("KeepOne"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ keepOneField.setLayoutData(data);
+
+ // IProgressMonitor.UNKNOWN
+ unknownField = new Button(group, SWT.CHECK);
+ unknownField.setText("Indeterminate Progress"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ unknownField.setLayoutData(data);
+
+ // whether the job is a user job
+ userField = new Button(group, SWT.CHECK);
+ userField.setText("User job"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ userField.setLayoutData(data);
+
+ // whether the job has a goto action
+ gotoActionField = new Button(group, SWT.CHECK);
+ gotoActionField.setText("Goto action"); //$NON-NLS-1$
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ gotoActionField.setLayoutData(data);
+
+ // whether the job should use a scheduling rule
+ schedulingRuleField = new Button(group, SWT.CHECK);
+ schedulingRuleField.setText("Schedule sequentially"); //$NON-NLS-1$
+ schedulingRuleField
+ .setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // failure
+ failureField = new Button(group, SWT.CHECK);
+ failureField.setText("Fail"); //$NON-NLS-1$
+ failureField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // failure
+ noPromptField = new Button(group, SWT.CHECK);
+ noPromptField.setText("No Prompt"); //$NON-NLS-1$
+ noPromptField
+ .setToolTipText("Set the IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY to true");
+ noPromptField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ }
+
+ protected void doRun(long duration, IProgressMonitor monitor) {
+ final long sleep = 10;
+ int ticks = (int) (duration / sleep);
+ monitor.beginTask(
+ "Spinning inside IProgressService.busyCursorWhile", ticks); //$NON-NLS-1$
+ monitor.setTaskName("Spinning inside IProgressService.busyCursorWhile"); //$NON-NLS-1$
+ for (int i = 0; i < ticks; i++) {
+ monitor.subTask("Processing tick #" + i); //$NON-NLS-1$
+ if (monitor.isCanceled())
+ return;
+ try {
+ Thread.sleep(sleep);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ monitor.worked(1);
+ }
+ }
+
+ protected void doRunInWorkspace(final long duration,
+ IProgressMonitor monitor) {
+ try {
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ doRun(duration, monitor);
+ }
+ }, monitor);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected long getDuration() {
+ switch (durationField.getSelectionIndex()) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return 1000;
+ case 3:
+ return 10000;
+ case 4:
+ return 60000;
+ case 5:
+ default:
+ return 600000;
+ }
+ }
+
+ protected void jobWithRuntimeException() {
+ Job runtimeExceptionJob = new Job("Job with Runtime exception") { //$NON-NLS-1$
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ throw new NullPointerException();
+ }
+ };
+ runtimeExceptionJob.schedule();
+ }
+
+ /**
+ * Example usage of the IJobManager.join method.
+ */
+ protected void joinTestJobs() {
+ try {
+ // note that when a null progress monitor is used when in the UI
+ // thread, the workbench will create a default progress monitor
+ // that reports progress in a modal dialog with details area
+ progressService.busyCursorWhile(
+ new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor)
+ throws InterruptedException {
+ Job.getJobManager().join(TestJob.FAMILY_TEST_JOB,
+ monitor);
+ }
+ });
+ } catch (InterruptedException e) {
+ // thrown if the user interrupts the join by canceling the progress
+ // monitor
+ // A UI component should swallow the exception and finish the action
+ // or operation. A lower level component should just propagate the
+ // exception
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // Thrown when the operation running within busyCursorWhile throws
+ // an
+ // exception. This should either be propagated or displayed to the
+ // user
+ e.printStackTrace();
+ }
+ }
+
+ protected void progressNoFork() {
+ try {
+ final long duration = getDuration();
+ final boolean shouldLock = lockField.getSelection();
+ progressService.runInUI(progressService,
+ new IRunnableWithProgress() {
+ @Override
+ public void run(IProgressMonitor monitor)
+ throws InterruptedException {
+ if (shouldLock)
+ doRunInWorkspace(duration, monitor);
+ else
+ doRun(duration, monitor);
+ }
+ }, ResourcesPlugin.getWorkspace().getRoot());
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @see ViewPart#setFocus()
+ */
+ @Focus
+ public void setFocus() {
+ if (durationField != null && !durationField.isDisposed())
+ durationField.setFocus();
+ }
+
+} \ No newline at end of file