diff options
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 00000000000..ad32c83a788 --- /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 00000000000..5e56e040ec0 --- /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 00000000000..cba6b1f1ab3 --- /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 00000000000..c537b63063c --- /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 00000000000..9c8a13aa93a --- /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 00000000000..706f07e8a5d --- /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 00000000000..5923b5680c8 --- /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 00000000000..125fe58ab4f --- /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 00000000000..31dc406d59e --- /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 00000000000..d00f988787c --- /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 00000000000..a35c8be0c95 --- /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 Binary files differnew file mode 100644 index 00000000000..c5df1cd37e2 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_rem.png 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 Binary files differnew file mode 100644 index 00000000000..e7ac19a5531 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_remall.png 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 Binary files differnew file mode 100644 index 00000000000..570f479e972 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/dlcl16/progress_stop.png 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 Binary files differnew file mode 100644 index 00000000000..c5df1cd37e2 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_rem.png 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 Binary files differnew file mode 100644 index 00000000000..5b5869dc7ee --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_remall.png 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 Binary files differnew file mode 100644 index 00000000000..80683841e2e --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/elcl16/progress_stop.png 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 Binary files differnew file mode 100644 index 00000000000..56d01c4f32d --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/errorstate.png 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 Binary files differnew file mode 100644 index 00000000000..eb528bbb751 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/lockedstate.png 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 Binary files differnew file mode 100644 index 00000000000..d6eda68cb19 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_error.png 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 Binary files differnew file mode 100644 index 00000000000..e4d0b008079 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_none.png 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 Binary files differnew file mode 100644 index 00000000000..8096d77b8de --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_ok.png 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 Binary files differnew file mode 100644 index 00000000000..32b333a695c --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/progress_task.png 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 Binary files differnew file mode 100644 index 00000000000..03b71f61e01 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/pview.png 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 Binary files differnew file mode 100644 index 00000000000..db0635c0a1a --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/sleeping.png 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 Binary files differnew file mode 100644 index 00000000000..eebf3cf6491 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.progress/icons/full/progress/waiting.png 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 00000000000..1c07c676cfc --- /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 00000000000..df11148b89e --- /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 00000000000..8ceec6b7dad --- /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 00000000000..3ff6038f682 --- /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 00000000000..72a71ef6a5e --- /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 00000000000..df3a41433e4 --- /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 00000000000..a87a0d02560 --- /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 00000000000..dd0b13b836d --- /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 00000000000..07a791a97b0 --- /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 00000000000..6704f8b61de --- /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 00000000000..1d18d94f398 --- /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 00000000000..f790d424008 --- /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 00000000000..6ffc67c9ea4 --- /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 00000000000..37b79a29a3f --- /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 00000000000..41830148915 --- /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 00000000000..2176bad4699 --- /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 00000000000..534aff1bb69 --- /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 00000000000..1c9bf6302f1 --- /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 00000000000..f859a0c157c --- /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 00000000000..b01901ce332 --- /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 00000000000..47445b7c70a --- /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 00000000000..d148d4f9f91 --- /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 00000000000..d94b658890b --- /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 00000000000..f526781fd54 --- /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 00000000000..36f7c0b9b73 --- /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 00000000000..871640f5572 --- /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 00000000000..3ebd422596b --- /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 00000000000..702d876957d --- /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 00000000000..00845c334b7 --- /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 00000000000..4fa41a921fc --- /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 00000000000..155a00d1599 --- /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 00000000000..77561189cbe --- /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 00000000000..84f8e1df7eb --- /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 00000000000..3709abae08a --- /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 00000000000..010748959aa --- /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 00000000000..1c2c1d814e5 --- /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 00000000000..94a368a24fe --- /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 00000000000..d228edb24a1 --- /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 00000000000..5eb083df34c --- /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 00000000000..aec1cda2bdb --- /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 00000000000..b9f24bc13bb --- /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 00000000000..8ac0406e9fa --- /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 00000000000..cd109e56c9a --- /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 00000000000..6a9845c8e62 --- /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 00000000000..7bd511ee256 --- /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 00000000000..3c42fc2a704 --- /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 00000000000..1c4d727564d --- /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 00000000000..48942809f68 --- /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 00000000000..f06d377e864 --- /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 00000000000..00629345965 --- /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 00000000000..af003416ad9 --- /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 00000000000..7c5c8a8fda4 --- /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 00000000000..a7fe9543833 --- /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 00000000000..307fd7653b2 --- /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 00000000000..78981e58fd2 --- /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 00000000000..357354fc02b --- /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 00000000000..cc847d9584c --- /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 00000000000..74e23a52009 --- /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 00000000000..33627184c27 --- /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 00000000000..222e033e2f0 --- /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 00000000000..41946211bcf --- /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 00000000000..61bfacee7b8 --- /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 00000000000..b83705a0dbb --- /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 00000000000..7964b4148cf --- /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 00000000000..deb673668e9 --- /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 00000000000..ba077a4031a --- /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 00000000000..85267cbbea6 --- /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 00000000000..c522e1f4ae2 --- /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 00000000000..c537b63063c --- /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 00000000000..938450e4a69 --- /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 00000000000..460233046ee --- /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 ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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 00000000000..384a829a54b --- /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 Binary files differnew file mode 100644 index 00000000000..81fb7b4a39d --- /dev/null +++ b/examples/org.eclipse.e4.ui.examples.job/icons/job_view.gif diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif b/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif Binary files differnew file mode 100644 index 00000000000..34fb3c9d8cb --- /dev/null +++ b/examples/org.eclipse.e4.ui.examples.job/icons/sample.gif diff --git a/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif b/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif Binary files differnew file mode 100644 index 00000000000..0d71e428d79 --- /dev/null +++ b/examples/org.eclipse.e4.ui.examples.job/icons/suspend.gif 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 Binary files differnew file mode 100644 index 00000000000..ce8bdb99b73 --- /dev/null +++ b/examples/org.eclipse.e4.ui.examples.job/icons/tree_view.gif 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 00000000000..e5ab7414243 --- /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 00000000000..4fac4cf7777 --- /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 00000000000..43cd042eefe --- /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 00000000000..d00f988787c --- /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 00000000000..a35c8be0c95 --- /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 00000000000..e056929307e --- /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 00000000000..dd74b6baff1 --- /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 00000000000..214d77638e9 --- /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 00000000000..d8b599e800b --- /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 |