[e4] Move RAP e4 incubator project to main RAP Runtime project

Use commit 594b007f1f564cdcf7b77b947affea8f58999c94 from the RAP e4
Incubator Git repository [1] and move the bundles, features, and
demo/example projects into the matching directories of the main RAP
Runtime repository.

The tooling projects remain in the incubator Git repository for the time
being.

The releng projects won't be migrated as they will be replaced with new
ones during the migration process.

[1]
https://git.eclipse.org/c/rap/incubator/org.eclipse.rap.incubator.e4.git/

Change-Id: Id2290c781dfc81dcb2f72f1e375eb1e45197a445
Signed-off-by: Markus Knauer <mknauer@eclipsesource.com>
diff --git a/bundles/org.eclipse.e4.core.commands/.classpath b/bundles/org.eclipse.e4.core.commands/.classpath
new file mode 100644
index 0000000..bd3096f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-rap"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.core.commands/.project b/bundles/org.eclipse.e4.core.commands/.project
new file mode 100644
index 0000000..9ceac7a
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.core.commands</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>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.core.prefs
new file mode 100755
index 0000000..adbdd50
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,418 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.ui.prefs
new file mode 100755
index 0000000..f6f4c8f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,124 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment"/><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=true
+sp_cleanup.remove_unused_imports=true
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..486a796
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,35 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=0
+compilers.p.discouraged-class=1
+compilers.p.illegal-att-value=0
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=2
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=1
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.core.commands/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.core.commands/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b6f1066
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/META-INF/MANIFEST.MF
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.core.commands;singleton:=true
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-Version: 0.11.0.qualifier
+Bundle-Activator: org.eclipse.e4.core.commands.internal.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.core.commands,
+ org.eclipse.core.commands.common,
+ org.eclipse.core.expressions,
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.core.services.log,
+ org.osgi.framework;version="1.5.0"
+Export-Package: org.eclipse.e4.core.commands;
+  x-friends:="org.eclipse.e4.ui.bindings,
+   org.eclipse.e4.ui.workbench,
+   org.eclipse.e4.ui.workbench.renderers.swt,
+   org.eclipse.ui.workbench,
+   org.eclipse.e4.ui.workbench.swt,
+   org.eclipse.e4.ui.progress,
+   org.eclipse.e4.core.commands.tests",
+ org.eclipse.e4.core.commands.internal;x-friends:="org.eclipse.e4.ui.bindings,org.eclipse.ui.workbench"
+Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.e4.core.di;bundle-version="0.9.0"
+Require-Capability: org.eclipse.rap
diff --git a/bundles/org.eclipse.e4.core.commands/META-INF/p2.inf b/bundles/org.eclipse.e4.core.commands/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.core.commands/OSGI-INF/commands.xml b/bundles/org.eclipse.e4.core.commands/OSGI-INF/commands.xml
new file mode 100644
index 0000000..c450539
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/OSGI-INF/commands.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.core.commands">
+   <implementation class="org.eclipse.e4.core.commands.internal.CommandServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.commands.ECommandService"/>
+</scr:component>
+   
diff --git a/bundles/org.eclipse.e4.core.commands/OSGI-INF/handlers.xml b/bundles/org.eclipse.e4.core.commands/OSGI-INF/handlers.xml
new file mode 100644
index 0000000..6498971
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/OSGI-INF/handlers.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.core.handlers">
+   <implementation class="org.eclipse.e4.core.commands.internal.HandlerServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.commands.EHandlerService"/>
+</scr:component>
+   
diff --git a/bundles/org.eclipse.e4.core.commands/about.html b/bundles/org.eclipse.e4.core.commands/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.commands/build.properties b/bundles/org.eclipse.e4.core.commands/build.properties
new file mode 100644
index 0000000..849e0b7
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/build.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2013, 2015 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
+###############################################################################
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               OSGI-INF/,\
+               about.html,\
+               plugin.properties
+source.. = src/,\
+           src-rap/
+src.includes = about.html
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.core.commands/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.core.commands/forceQualifierUpdate.txt
new file mode 100644
index 0000000..56f1032
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
diff --git a/bundles/org.eclipse.e4.core.commands/plugin.properties b/bundles/org.eclipse.e4.core.commands/plugin.properties
new file mode 100644
index 0000000..85ce14d
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 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
+###############################################################################
+pluginName = Eclipse e4 core commands
+providerName = Eclipse.org
diff --git a/bundles/org.eclipse.e4.core.commands/pom.xml b/bundles/org.eclipse.e4.core.commands/pom.xml
new file mode 100644
index 0000000..f0ba8f8
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.core.commands</artifactId>
+  <version>0.11.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/CommandServiceAddon.java b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/CommandServiceAddon.java
new file mode 100644
index 0000000..b7097cc
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/CommandServiceAddon.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 431180
+ ******************************************************************************/
+
+package org.eclipse.e4.core.commands;
+
+import java.lang.reflect.Field;
+import java.util.LinkedList;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.e4.core.commands.internal.CommandServiceImpl;
+import org.eclipse.e4.core.commands.internal.HandlerServiceCreationFunction;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl.ExecutionContexts;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ * Provide the command and handler service as an add-on. Must be instantiated against the
+ * application level context.
+ *
+ * @noinstantiate
+ */
+public class CommandServiceAddon {
+	private IEclipseContext context;
+
+	@Inject
+	public CommandServiceAddon(IEclipseContext context) {
+		this.context = context;
+	}
+
+	@PostConstruct
+	void init(IEclipseContext context) {
+		// global command service. There can be only one ... per application :-)
+		CommandManager manager = context.get(CommandManager.class);
+		if (manager == null) {
+			manager = new CommandManager();
+			// setCommandFireEvents(manager, false);
+			context.set(CommandManager.class, manager);
+		}
+
+		CommandServiceImpl service = ContextInjectionFactory
+				.make(CommandServiceImpl.class, context);
+		context.set(ECommandService.class, service);
+
+		// handler service
+		context.set(EHandlerService.class.getName(), new HandlerServiceCreationFunction());
+		context.set("_handlerExecutionStack", new LinkedList<ExecutionContexts>()); //$NON-NLS-1$
+		// provide the initial application context, just in case.
+		HandlerServiceImpl.push(context, null);
+	}
+
+	@PreDestroy
+	void cleanup() {
+		HandlerServiceImpl.pop(context);
+	}
+
+	/**
+	 * @param manager
+	 * @param b
+	 */
+	void setCommandFireEvents(CommandManager manager, boolean b) {
+		try {
+			Field f = CommandManager.class.getDeclaredField("shouldCommandFireEvents"); //$NON-NLS-1$
+			f.setAccessible(true);
+			f.set(manager, Boolean.valueOf(b));
+		} catch (SecurityException e) {
+			e.printStackTrace();
+		} catch (NoSuchFieldException e) {
+			e.printStackTrace();
+		} catch (IllegalArgumentException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/CommandServiceImpl.java b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/CommandServiceImpl.java
new file mode 100644
index 0000000..052e713
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/CommandServiceImpl.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.core.commands.internal;
+
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ *
+ */
+public class CommandServiceImpl implements ECommandService {
+
+	private CommandManager commandManager;
+	private IEclipseContext context;
+
+	@Inject
+	public void setManager(CommandManager m, IEclipseContext c) {
+		commandManager = m;
+		context = c;
+	}
+
+	@Override
+	public ParameterizedCommand createCommand(String id, Map<String, Object> parameters) {
+		Command command = getCommand(id);
+		if (command == null) {
+			return null;
+		}
+		return ParameterizedCommand.generateCommand(command, parameters);
+	}
+
+	@Override
+	public Category defineCategory(String id, String name, String description) {
+		Category cat = commandManager.getCategory(id);
+		if (!cat.isDefined()) {
+			cat.define(name, description);
+		}
+		return cat;
+	}
+
+	@Override
+	public Command defineCommand(String id, String name, String description, Category category,
+			IParameter[] parameters) {
+		Command cmd = commandManager.getCommand(id);
+		if (!cmd.isDefined()) {
+			cmd.define(name, description, category, parameters);
+			cmd.setHandler(HandlerServiceImpl.getHandler(id, context));
+		}
+		return cmd;
+	}
+
+	@Override
+	public Category getCategory(String categoryId) {
+		return commandManager.getCategory(categoryId);
+	}
+
+	@Override
+	public Command getCommand(String commandId) {
+		return commandManager.getCommand(commandId);
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceHandler.java b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceHandler.java
new file mode 100644
index 0000000..60a1984
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceHandler.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 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.core.commands.internal;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.HandlerEvent;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.NotHandledException;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl.ExecutionContexts;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+
+/**
+ * Provide an IHandler to delegate calls to.
+ */
+public class HandlerServiceHandler extends AbstractHandler {
+
+	private static final String FAILED_TO_FIND_HANDLER_DURING_EXECUTION = "Failed to find handler during execution"; //$NON-NLS-1$
+	private static final String HANDLER_MISSING_EXECUTE_ANNOTATION = "Handler is missing @Execute"; //$NON-NLS-1$
+	private static final Object missingExecute = new Object();
+
+	protected String commandId;
+	private IEclipseContext context;
+
+	public HandlerServiceHandler(String commandId, IEclipseContext context) {
+		this.commandId = commandId;
+		this.context = context;
+	}
+
+	@Override
+	public boolean isEnabled() {
+		ExecutionContexts contexts = HandlerServiceImpl.peek(context);
+		// setEnabled(contexts);
+		IEclipseContext executionContext = contexts != null ? contexts.context : null; // getExecutionContext(contexts);
+		if (executionContext == null) {
+			return super.isEnabled();
+		}
+		Object handler = HandlerServiceImpl.lookUpHandler(executionContext, commandId);
+		if (handler == null) {
+			setBaseEnabled(false);
+			return super.isEnabled();
+		}
+		IEclipseContext staticContext = contexts.staticContext; // getStaticContext(contexts);
+		Boolean result = (Boolean) ContextInjectionFactory.invoke(handler, CanExecute.class,
+				executionContext, staticContext, Boolean.TRUE);
+		setBaseEnabled(result.booleanValue());
+		return super.isEnabled();
+	}
+
+	@Override
+	public void setEnabled(Object evaluationContext) {
+		boolean createContext = false;
+		IEclipseContext executionContext = getExecutionContext(evaluationContext);
+		if (executionContext == null) {
+			return;
+		}
+		Object handler = HandlerServiceImpl.lookUpHandler(executionContext, commandId);
+		if (handler == null) {
+			return;
+		}
+		IEclipseContext staticContext = getStaticContext(executionContext);
+		if (staticContext == null) {
+			staticContext = EclipseContextFactory.create();
+			createContext = true;
+		}
+		ContextInjectionFactory.invoke(handler, SetEnabled.class, executionContext, staticContext,
+				Boolean.TRUE);
+		if (createContext) {
+			staticContext.dispose();
+		}
+	}
+
+	private IEclipseContext getStaticContext(IEclipseContext executionContext) {
+		final ExecutionContexts pair = HandlerServiceImpl.peek(context);
+		if (pair != null) {
+			if (pair.context != executionContext) {
+				// log this
+			}
+			return pair.staticContext;
+		}
+		return null;
+	}
+
+	protected IEclipseContext getExecutionContext(Object evalObj) {
+		// if (evalObj instanceof ExecutionContexts) {
+		// return ((ExecutionContexts) evalObj).context;
+		// }
+		if (evalObj instanceof IEclipseContext) {
+			return (IEclipseContext) evalObj;
+		}
+		if (evalObj instanceof ExpressionContext) {
+			return ((ExpressionContext) evalObj).eclipseContext;
+		}
+		if (evalObj instanceof IEvaluationContext) {
+			return getExecutionContext(((IEvaluationContext) evalObj).getParent());
+		}
+		final ExecutionContexts pair = HandlerServiceImpl.peek(context);
+		if (pair != null) {
+			return pair.context;
+		}
+		return null;
+	}
+
+	@Override
+	public boolean isHandled() {
+		ExecutionContexts contexts = HandlerServiceImpl.peek(context);
+		if (contexts != null) {
+			Object handler = HandlerServiceImpl.lookUpHandler(contexts.context, commandId);
+			if (handler instanceof IHandler) {
+				return ((IHandler) handler).isHandled();
+			}
+			return handler != null;
+
+		}
+		return false;
+	}
+
+	@Override
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEclipseContext executionContext = getExecutionContext(event.getApplicationContext());
+		if (executionContext == null) {
+			throw new ExecutionException(FAILED_TO_FIND_HANDLER_DURING_EXECUTION,
+					new NotHandledException(FAILED_TO_FIND_HANDLER_DURING_EXECUTION));
+		}
+
+		Object handler = HandlerServiceImpl.lookUpHandler(executionContext, commandId);
+		if (handler == null) {
+			return null;
+		}
+		IEclipseContext staticContext = getStaticContext(executionContext);
+		IEclipseContext localStaticContext = null;
+		try {
+			if (staticContext == null) {
+				staticContext = localStaticContext = EclipseContextFactory
+						.create(HandlerServiceImpl.TMP_STATIC_CONTEXT);
+				staticContext.set(HandlerServiceImpl.PARM_MAP, event.getParameters());
+			}
+			Object result = ContextInjectionFactory.invoke(handler, Execute.class, executionContext, staticContext,
+					missingExecute);
+			if (result == missingExecute) {
+				throw new ExecutionException(HANDLER_MISSING_EXECUTE_ANNOTATION,
+						new NotHandledException(getClass().getName()));
+			}
+			return result;
+		} finally {
+			if (localStaticContext != null) {
+				localStaticContext.dispose();
+			}
+		}
+	}
+
+	@Override
+	public void fireHandlerChanged(HandlerEvent handlerEvent) {
+		super.fireHandlerChanged(handlerEvent);
+	}
+
+	public void overrideEnabled(boolean b) {
+		setBaseEnabled(b);
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceImpl.java b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceImpl.java
new file mode 100644
index 0000000..ad283fc
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src-rap/org/eclipse/e4/core/commands/internal/HandlerServiceImpl.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 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.core.commands.internal;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.commands.AbstractParameterValueConverter;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.NotEnabledException;
+import org.eclipse.core.commands.NotHandledException;
+import org.eclipse.core.commands.ParameterType;
+import org.eclipse.core.commands.ParameterValueConversionException;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+
+/**
+ *
+ */
+public class HandlerServiceImpl implements EHandlerService {
+	/**
+	 * The static context key under which a command 'trigger' from legacy code is stored during
+	 * calls to {@link #executeHandler(ParameterizedCommand, IEclipseContext)}
+	 *
+	 * @see IEclipseContext
+	 * @see HandlerServiceImpl#executeHandler(ParameterizedCommand, IEclipseContext)
+	 */
+	private static final String SWT_TRIGGER = "org.eclipse.swt.widgets.Event"; //$NON-NLS-1$
+	static final String TMP_STATIC_CONTEXT = "tmp-staticContext"; //$NON-NLS-1$
+	public final static String H_ID = "handler::"; //$NON-NLS-1$
+	public final static String PARM_MAP = "parmMap::"; //$NON-NLS-1$
+	public final static String CAN_EXECUTE = "HandlerServiceImpl.canExecute"; //$NON-NLS-1$
+	public final static String NOT_HANDLED = "HandlerServiceImpl.notHandled"; //$NON-NLS-1$
+	public final static String STATIC_CONTEXT = "HandlerServiceImpl.staticContext"; //$NON-NLS-1$
+	public final static String HANDLER_EXCEPTION = "HandlerServiceImpl.exception"; //$NON-NLS-1$
+
+	public static ContextFunction handlerGenerator = null;
+
+	private static LinkedList<ExecutionContexts> DEFAULT_STACKLIST = new LinkedList<HandlerServiceImpl.ExecutionContexts>();
+
+	public static IHandler getHandler(String commandId, IEclipseContext context) {
+		if (handlerGenerator != null) {
+			return (IHandler) handlerGenerator.compute(null, commandId);
+		}
+		return new HandlerServiceHandler(commandId, context);
+	}
+
+	public static class ExecutionContexts {
+		public IEclipseContext context;
+		public IEclipseContext staticContext;
+
+		public ExecutionContexts(IEclipseContext ctx, IEclipseContext staticCtx) {
+			context = ctx;
+			staticContext = staticCtx;
+		}
+	}
+
+	static LinkedList<ExecutionContexts> getContextStack(IEclipseContext context) {
+		if (context == null) {
+			return DEFAULT_STACKLIST;
+		}
+		Object handlerExecutionStack = context.get("_handlerExecutionStack"); //$NON-NLS-1$
+		if (handlerExecutionStack == null) {
+			return DEFAULT_STACKLIST;
+		}
+		return (LinkedList<ExecutionContexts>) handlerExecutionStack;
+	}
+
+	public static void push(IEclipseContext ctx, IEclipseContext staticCtx) {
+		getContextStack(ctx).addFirst(new ExecutionContexts(ctx, staticCtx));
+	}
+
+	public static ExecutionContexts pop(IEclipseContext ctx) {
+		return getContextStack(ctx).poll();
+	}
+
+	static ExecutionContexts peek(IEclipseContext ctx) {
+		return getContextStack(ctx).peek();
+	}
+
+	/**
+	 * @param context
+	 *            the context to start the lookup process
+	 * @param commandId
+	 * @return a handler, or <code>null</code>
+	 */
+	public static Object lookUpHandler(IEclipseContext context, String commandId) {
+		return context.getActiveLeaf().get(H_ID + commandId);
+	}
+
+	/**
+	 * Fill in a temporary static context for execution.
+	 *
+	 * @param command
+	 */
+	@SuppressWarnings("rawtypes")
+	private void addParms(ParameterizedCommand command, IEclipseContext staticContext) {
+		final Map parms = command.getParameterMap();
+		Iterator i = parms.entrySet().iterator();
+		while (i.hasNext()) {
+			Map.Entry entry = (Map.Entry) i.next();
+			String parameterId = (String) entry.getKey();
+			staticContext.set(
+					parameterId,
+					convertParameterValue(command.getCommand(), parameterId,
+							(String) entry.getValue()));
+		}
+		staticContext.set(PARM_MAP, parms);
+		staticContext.set(ParameterizedCommand.class, command);
+	}
+
+	/**
+	 * Convert the parameter's value according to it's type.
+	 *
+	 * @param command
+	 * @param parameterId
+	 * @param value
+	 * @return converted value
+	 * @see org.eclipse.e4.ui.model.application.commands.MCommandParameter#getTypeId()
+	 */
+	private Object convertParameterValue(Command command, String parameterId, String value) {
+		try {
+			ParameterType parameterType = command.getParameterType(parameterId);
+
+			if (parameterType != null) {
+				AbstractParameterValueConverter valueConverter = parameterType.getValueConverter();
+				if (valueConverter != null) {
+					return valueConverter.convertToObject(value);
+				}
+			}
+		} catch (NotDefinedException e) {
+		} catch (ParameterValueConversionException e) {
+		}
+		return value;
+	}
+
+	private IEclipseContext context;
+
+	@Inject
+	@Optional
+	Logger logger;
+
+	@Override
+	public void activateHandler(String commandId, Object handler) {
+		String handlerId = H_ID + commandId;
+		context.set(handlerId, handler);
+	}
+
+	@Override
+	public boolean canExecute(ParameterizedCommand command) {
+		final IEclipseContext staticContext = EclipseContextFactory.create(TMP_STATIC_CONTEXT);
+		try {
+			return canExecute(command, staticContext);
+		} finally {
+			staticContext.dispose();
+		}
+	}
+
+	@Override
+	public boolean canExecute(ParameterizedCommand command, IEclipseContext staticContext) {
+		final IEclipseContext executionContext = getExecutionContext();
+		addParms(command, staticContext);
+		// executionContext.set(STATIC_CONTEXT, staticContext);
+		push(executionContext, staticContext);
+		try {
+			Command cmd = command.getCommand();
+			cmd.setEnabled(new ExpressionContext(peek(executionContext).context));
+			return cmd.isEnabled();
+		} finally {
+			pop(executionContext);
+			// executionContext.remove(STATIC_CONTEXT);
+		}
+	}
+
+	@Override
+	public void deactivateHandler(String commandId, Object handler) {
+		context.remove(H_ID + commandId);
+	}
+
+	@Override
+	public Object executeHandler(ParameterizedCommand command) {
+		final IEclipseContext staticContext = EclipseContextFactory.create(TMP_STATIC_CONTEXT);
+		try {
+			return executeHandler(command, staticContext);
+		} finally {
+			staticContext.dispose();
+		}
+	}
+
+	@Override
+	public Object executeHandler(ParameterizedCommand command, IEclipseContext staticContext) {
+		final IEclipseContext executionContext = getExecutionContext();
+		addParms(command, staticContext);
+		// executionContext.set(STATIC_CONTEXT, staticContext);
+		push(executionContext, staticContext);
+		try {
+			// Command cmd = command.getCommand();
+			return command.executeWithChecks(staticContext.get(SWT_TRIGGER), new ExpressionContext(
+					peek(executionContext).context));
+		} catch (ExecutionException e) {
+			staticContext.set(HANDLER_EXCEPTION, e);
+		} catch (NotDefinedException e) {
+			staticContext.set(HANDLER_EXCEPTION, e);
+		} catch (NotEnabledException e) {
+			staticContext.set(HANDLER_EXCEPTION, e);
+		} catch (NotHandledException e) {
+			staticContext.set(HANDLER_EXCEPTION, e);
+		} finally {
+			pop(executionContext);
+			// executionContext.remove(STATIC_CONTEXT);
+		}
+		return null;
+	}
+
+	@Inject
+	public void setContext(IEclipseContext c) {
+		context = c;
+	}
+
+	public IEclipseContext getContext() {
+		return context;
+	}
+
+	public IEclipseContext getExecutionContext() {
+		return context.getActiveLeaf();
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ECommandService.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ECommandService.java
new file mode 100644
index 0000000..7aa81c6
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ECommandService.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.core.commands;
+
+import java.util.Map;
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.ParameterizedCommand;
+
+/**
+ * @noimplement
+ */
+public interface ECommandService {
+	public ParameterizedCommand createCommand(String id, Map<String, Object> parameters);
+
+	/**
+	 * @param id
+	 * @param name
+	 * @param description
+	 * @return
+	 * @noreference
+	 */
+	public Category defineCategory(String id, String name, String description);
+
+	/**
+	 * @param id
+	 * @param name
+	 * @param description
+	 * @param category
+	 * @param parameters
+	 * @return
+	 * @noreference
+	 */
+	public Command defineCommand(String id, String name, String description, Category category,
+			IParameter[] parameters);
+
+	public Category getCategory(String categoryId);
+
+	public Command getCommand(String commandId);
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/EHandlerService.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/EHandlerService.java
new file mode 100644
index 0000000..1843b25
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/EHandlerService.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.core.commands;
+
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ * @noimplement
+ */
+public interface EHandlerService {
+
+	public void activateHandler(String commandId, Object handler);
+
+	public void deactivateHandler(String commandId, Object handler);
+
+	public Object executeHandler(ParameterizedCommand command);
+
+	public boolean canExecute(ParameterizedCommand command);
+
+	/**
+	 * Execute a handler for the command.
+	 *
+	 * @param command
+	 *            Must not be <code>null</code>
+	 * @param staticContext
+	 *            Must not be <code>null</code>. You must dispose your context
+	 *            when you are done.
+	 * @return the command return value.
+	 */
+	public Object executeHandler(ParameterizedCommand command, IEclipseContext staticContext);
+
+	/**
+	 * Check if a command can be executed.
+	 *
+	 * @param command
+	 *            Must not be <code>null</code>.
+	 * @param staticContext
+	 *            Must not be <code>null</code>. You must dispose your context
+	 *            when you are done.
+	 * @return true if the command can be executed.
+	 */
+	public boolean canExecute(ParameterizedCommand command, IEclipseContext staticContext);
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ExpressionContext.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ExpressionContext.java
new file mode 100644
index 0000000..18dc2cf
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/ExpressionContext.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.core.commands;
+
+import java.util.Collections;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ * @noreference
+ * @since 1.0
+ */
+public class ExpressionContext implements IEvaluationContext {
+	/**
+	 * See org.eclipse.e4.ui.services.IServiceConstants.ACTIVE_SELECTION
+	 */
+	private static final String ORG_ECLIPSE_UI_SELECTION = "org.eclipse.ui.selection"; //$NON-NLS-1$
+
+	public static final String ALLOW_ACTIVATION = "org.eclipse.e4.core.commands.ExpressionContext.allowActivation"; //$NON-NLS-1$
+
+	public IEclipseContext eclipseContext;
+	public static IContextFunction defaultVariableConverter = null;
+
+	public ExpressionContext(IEclipseContext eclipseContext) {
+		this.eclipseContext = eclipseContext;
+	}
+
+	@Override
+	public IEvaluationContext getParent() {
+		IEclipseContext parent = eclipseContext.getParent();
+		return parent == null ? null : new ExpressionContext(parent);
+	}
+
+	@Override
+	public IEvaluationContext getRoot() {
+		IEclipseContext current = eclipseContext;
+		IEclipseContext parent = current.getParent();
+		while (parent != null) {
+			current = parent;
+			parent = current.getParent();
+		}
+		if (current == eclipseContext) {
+			return this;
+		}
+		return new ExpressionContext(current);
+	}
+
+	@Override
+	public void setAllowPluginActivation(boolean value) {
+		eclipseContext.set(ALLOW_ACTIVATION, Boolean.valueOf(value));
+	}
+
+	@Override
+	public boolean getAllowPluginActivation() {
+		Object obj = eclipseContext.get(ALLOW_ACTIVATION);
+		return obj instanceof Boolean ? ((Boolean) obj).booleanValue() : false;
+	}
+
+	@Override
+	public Object getDefaultVariable() {
+		final Object sel;
+		if (defaultVariableConverter != null) {
+			sel = defaultVariableConverter.compute(eclipseContext, null);
+		} else {
+			sel = eclipseContext.getActive(ORG_ECLIPSE_UI_SELECTION);
+		}
+		return sel == null ? Collections.EMPTY_LIST : sel;
+	}
+
+	@Override
+	public void addVariable(String name, Object value) {
+		eclipseContext.set(name, value);
+	}
+
+	@Override
+	public Object removeVariable(String name) {
+		Object obj = eclipseContext.getLocal(name);
+		eclipseContext.remove(name);
+		return obj;
+	}
+
+	@Override
+	public Object getVariable(String name) {
+		if (IEclipseContext.class.getName().equals(name)) {
+			return eclipseContext;
+		}
+		Object obj = eclipseContext.getActive(name);
+		return obj == null ? IEvaluationContext.UNDEFINED_VARIABLE : obj;
+	}
+
+	@Override
+	public Object resolveVariable(String name, Object[] args) throws CoreException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/Activator.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/Activator.java
new file mode 100644
index 0000000..a31e460
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/Activator.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 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.core.commands.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator implements BundleActivator {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.e4.core.commands"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+
+	@Override
+	public void start(BundleContext context) throws Exception {
+		plugin = this;
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/CommandServiceCreationFunction.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/CommandServiceCreationFunction.java
new file mode 100644
index 0000000..f813155
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/CommandServiceCreationFunction.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.core.commands.internal;
+
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ *
+ */
+public class CommandServiceCreationFunction extends ContextFunction {
+	/**
+	 * A context key (value "rootContext") that identifies the root of this context chain. It does
+	 * not have to be the global root, but signifies the topmost context for the purposes of
+	 * function management and active context chains.
+	 */
+	public static final String ROOT_CONTEXT = "rootContext"; //$NON-NLS-1$
+
+	private CommandManager manager = null;
+	private CommandServiceImpl service = null;
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		if (service == null) {
+			IEclipseContext root = getRootContext(context);
+			manager = new CommandManager();
+			root.set(CommandManager.class.getName(), manager);
+			service = ContextInjectionFactory.make(CommandServiceImpl.class, root);
+		}
+		return service;
+	}
+
+	/**
+	 * @param context
+	 * @return the topmost "root" context
+	 */
+	private IEclipseContext getRootContext(IEclipseContext context) {
+		IEclipseContext current = (IEclipseContext) context.get(ROOT_CONTEXT);
+		if (current != null) {
+			return current;
+		}
+		current = context;
+		IEclipseContext parent = current.getParent();
+		while (parent != null) {
+			current = parent;
+			parent = current.getParent();
+		}
+		if (current != null) {
+			current.set(ROOT_CONTEXT, current);
+		}
+		return current;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/HandlerServiceCreationFunction.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/HandlerServiceCreationFunction.java
new file mode 100644
index 0000000..e671f00
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/HandlerServiceCreationFunction.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.core.commands.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+public class HandlerServiceCreationFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		return ContextInjectionFactory.make(HandlerServiceImpl.class, context);
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/ICommandHelpService.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/ICommandHelpService.java
new file mode 100644
index 0000000..a19132f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/ICommandHelpService.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 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.core.commands.internal;
+
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ * Provides services related to the command context help.
+ */
+public interface ICommandHelpService {
+
+	/**
+	 * Calculates the active help context for the command and returns the ID of the help context.
+	 *
+	 * @param commandId
+	 *            the ID of the command for which the help context ID is calculated
+	 * @param context
+	 *            the Eclipse context in which handlers of the command will be sought
+	 * @return the ID of help context which is active for the command
+	 */
+	public String getHelpContextId(String commandId, IEclipseContext context);
+
+	/**
+	 * Assigns the help context ID to the command handler.
+	 *
+	 * @param handler
+	 *            the command handler to which the help context ID will be assigned
+	 * @param contextId
+	 *            the help context ID to assign
+	 */
+	public void setHelpContextId(IHandler handler, String contextId);
+}
diff --git a/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/SetEnabled.java b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/SetEnabled.java
new file mode 100644
index 0000000..593e97d
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.commands/src/org/eclipse/e4/core/commands/internal/SetEnabled.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 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.core.commands.internal;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to tag a method to call the handler setEnabled method.
+ * <p>
+ * This annotation must not be applied to more than one method per class. If
+ * several class methods are tagged with this annotation, only one of them will
+ * be called.
+ * </p>
+ *
+ * @since 1.3
+ * @noreference
+ */
+@Documented
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SetEnabled {
+	// intentionally left empty
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/.classpath b/bundles/org.eclipse.e4.ui.bindings/.classpath
new file mode 100644
index 0000000..bd3096f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-rap"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.bindings/.project b/bundles/org.eclipse.e4.ui.bindings/.project
new file mode 100644
index 0000000..093b5d2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.bindings</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>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bd457c1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,419 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.ui.prefs
new file mode 100755
index 0000000..b058cde
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment"/><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=true
+sp_cleanup.remove_unused_imports=true
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.bindings/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.bindings/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..2d5f844
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/META-INF/MANIFEST.MF
@@ -0,0 +1,32 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.ui.bindings;singleton:=true
+Bundle-Version: 0.11.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.e4.core.commands,
+ org.eclipse.e4.core.commands.internal,
+ org.eclipse.e4.core.services.log,
+ org.eclipse.jface.bindings,
+ org.eclipse.jface.bindings.keys,
+ org.eclipse.jface.bindings.keys.formatting,
+ org.eclipse.jface.dialogs,
+ org.eclipse.jface.window,
+ org.osgi.framework;version="1.5.0"
+Require-Bundle: org.eclipse.core.commands;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.e4.core.contexts;bundle-version="1.0.0",
+ org.eclipse.e4.core.di;bundle-version="1.1.0",
+ org.eclipse.rap.rwt
+Require-Capability: org.eclipse.rap
+Export-Package: org.eclipse.e4.ui.bindings;
+  x-friends:="org.eclipse.e4.ui.workbench,
+   org.eclipse.e4.ui.workbench.renderers.swt,
+   org.eclipse.e4.ui.workbench.swt,
+   org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.bindings.internal;x-friends:="org.eclipse.e4.ui.workbench,org.eclipse.e4.ui.workbench.swt,org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.bindings.keys;x-friends:="org.eclipse.e4.ui.workbench.swt,org.eclipse.ui.workbench"
diff --git a/bundles/org.eclipse.e4.ui.bindings/META-INF/p2.inf b/bundles/org.eclipse.e4.ui.bindings/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.ui.bindings/OSGI-INF/bindings.xml b/bundles/org.eclipse.e4.ui.bindings/OSGI-INF/bindings.xml
new file mode 100644
index 0000000..0f3796f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/OSGI-INF/bindings.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.bindings">
+   <implementation class="org.eclipse.e4.ui.bindings.internal.BindingServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.ui.bindings.EBindingService"/>
+</scr:component>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.bindings/about.html b/bundles/org.eclipse.e4.ui.bindings/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.bindings/build.properties b/bundles/org.eclipse.e4.ui.bindings/build.properties
new file mode 100644
index 0000000..4ad436e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/build.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2013, 2015 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
+###############################################################################
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               OSGI-INF/,\
+               plugin.properties,\
+               about.html
+source.. = src/,\
+           src-rap/
+src.includes = about.html
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.ui.bindings/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.ui.bindings/forceQualifierUpdate.txt
new file mode 100644
index 0000000..56f1032
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
diff --git a/bundles/org.eclipse.e4.ui.bindings/plugin.properties b/bundles/org.eclipse.e4.ui.bindings/plugin.properties
new file mode 100644
index 0000000..76a2694
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 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
+###############################################################################
+pluginName = Eclipse Bindings Support
+providerName = Eclipse.org
diff --git a/bundles/org.eclipse.e4.ui.bindings/pom.xml b/bundles/org.eclipse.e4.ui.bindings/pom.xml
new file mode 100644
index 0000000..ecbdc08
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.bindings</artifactId>
+  <version>0.11.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/internal/KeyAssistDialog.java b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/internal/KeyAssistDialog.java
new file mode 100644
index 0000000..9a295ab
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/internal/KeyAssistDialog.java
@@ -0,0 +1,589 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.bindings.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.CommandException;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.PopupDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+/**
+ * <p>
+ * A dialog displaying a list of key bindings. The dialog will execute a command
+ * if it is selected.
+ * </p>
+ * <p>
+ * The methods on this class are not thread-safe and must be run from the UI
+ * thread.
+ * </p>
+ *
+ * @since 3.1
+ */
+public class KeyAssistDialog extends PopupDialog {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * The data key for the binding stored on an SWT widget. The key is a
+	 * fully-qualified name, but in reverse order. This is so that the equals
+	 * method will detect misses faster.
+	 */
+	private static final String BINDING_KEY = "Binding.bindings.jface.eclipse.org"; //$NON-NLS-1$
+
+	/**
+	 * The value of <code>previousWidth</code> to set if there is no remembered
+	 * width.
+	 */
+	private static final int NO_REMEMBERED_WIDTH = -1;
+
+	/**
+	 * The ordered list of command identifiers corresponding to the table.
+	 */
+	private List<Binding> bindings = new ArrayList<Binding>();
+
+	/**
+	 * The table containing of the possible completions. This value is
+	 * <code>null</code> until the dialog is created.
+	 */
+	private Table completionsTable = null;
+
+	/**
+	 * The width of the shell when it was previously open. This is only
+	 * remembered until <code>clearRememberedState()</code> is called.
+	 */
+	private int previousWidth = NO_REMEMBERED_WIDTH;
+
+	/**
+	 * The key binding listener for the associated workbench.
+	 */
+	private KeyBindingDispatcher workbenchKeyboard;
+
+	/**
+	 * A sorted map of conflicts or partial matches to be used when the dialog
+	 * pops up.
+	 *
+	 * @since 3.3
+	 */
+	private Collection<Binding> matches;
+
+	private IEclipseContext context;
+
+	/**
+	 * Constructs a new instance of <code>KeyAssistDialog</code>. When the
+	 * dialog is first constructed, it contains no widgets. The dialog is first
+	 * created with no parent. If a parent is required, call
+	 * <code>setParentShell()</code>. Also, between uses, it might be necessary
+	 * to call <code>setParentShell()</code> as well.
+	 *
+	 * @param context
+	 *            The context in which this dialog is created; must not be
+	 *            <code>null</code>.
+	 * @param associatedKeyboard
+	 *            The key binding listener for the workbench; must not be
+	 *            <code>null</code>.
+	 */
+	public KeyAssistDialog(IEclipseContext context, KeyBindingDispatcher associatedKeyboard) {
+		super((Shell) null, PopupDialog.INFOPOPUP_SHELLSTYLE, true, false, false, false, null, null);
+		// super(null, PopupDialog.INFOPOPUP_SHELLSTYLE, true, false, false,
+		// false, false, DIALOG_TITLE, getKeySequenceString()); //$NON-NLS-1$
+
+		this.context = context;
+		this.workbenchKeyboard = associatedKeyboard;
+	}
+
+	/**
+	 * Clears out the remembered state of the key assist dialog. This includes
+	 * its width, as well as the selected binding.
+	 */
+	public void clearRememberedState() {
+		previousWidth = NO_REMEMBERED_WIDTH;
+	}
+
+	/**
+	 * Closes this shell, but first remembers some state of the dialog. This way
+	 * it will have a response if asked to open the dialog again or if asked to
+	 * open the keys preference page. This does not remember the internal state.
+	 *
+	 * @return Whether the shell was already closed.
+	 */
+	@Override
+	public boolean close() {
+		return close(false);
+	}
+
+	/**
+	 * Closes this shell, but first remembers some state of the dialog. This way
+	 * it will have a response if asked to open the dialog again or if asked to
+	 * open the keys preference page.
+	 *
+	 * @param rememberState
+	 *            Whether the internal state should be remembered.
+	 * @return Whether the shell was already closed.
+	 */
+	public boolean close(boolean rememberState) {
+		return close(rememberState, true);
+	}
+
+	/**
+	 * Closes this shell, but first remembers some state of the dialog. This way
+	 * it will have a response if asked to open the dialog again or if asked to
+	 * open the keys preference page.
+	 *
+	 * @param rememberState
+	 *            Whether the internal state should be remembered.
+	 * @param resetState
+	 *            Whether the state should be reset.
+	 * @return Whether the shell was already closed.
+	 */
+	private boolean close(boolean rememberState, boolean resetState) {
+		Shell shell = getShell();
+		if (rememberState) {
+
+			// Remember the previous width.
+			int widthToRemember;
+			if ((shell != null) && (!shell.isDisposed())) {
+				widthToRemember = getShell().getSize().x;
+			} else {
+				widthToRemember = NO_REMEMBERED_WIDTH;
+			}
+
+			this.previousWidth = widthToRemember;
+			completionsTable = null;
+		}
+		matches = null;
+		boolean popupClosed = super.close();
+		if (resetState) {
+			workbenchKeyboard.resetState();
+		}
+		return popupClosed;
+	}
+
+	/**
+	 * Sets the position for the dialog based on the position of the workbench
+	 * window. The dialog is flush with the bottom right corner of the workbench
+	 * window. However, the dialog will not appear outside of the display's
+	 * client area.
+	 *
+	 * @param size
+	 *            The final size of the dialog; must not be <code>null</code>.
+	 */
+	private void configureLocation(Point size) {
+		Shell shell = getShell();
+
+		Shell workbenchWindowShell = (Shell) shell.getParent();
+		int xCoord;
+		int yCoord;
+		if (workbenchWindowShell != null) {
+			/*
+			 * Position the shell at the bottom right corner of the workbench
+			 * window
+			 */
+			Rectangle workbenchWindowBounds = workbenchWindowShell.getBounds();
+			xCoord = workbenchWindowBounds.x + workbenchWindowBounds.width - size.x - 10;
+			yCoord = workbenchWindowBounds.y + workbenchWindowBounds.height - size.y - 10;
+
+		} else {
+			xCoord = 0;
+			yCoord = 0;
+
+		}
+		Rectangle bounds = new Rectangle(xCoord, yCoord, size.x, size.y);
+		shell.setBounds(getConstrainedShellBounds(bounds));
+	}
+
+	/**
+	 * Sets the size for the dialog based on its previous size. The width of the
+	 * dialog is its previous width, if it exists. Otherwise, it is simply the
+	 * packed width of the dialog. The maximum width is 40% of the workbench
+	 * window's width. The dialog's height is the packed height of the dialog to
+	 * a maximum of half the height of the workbench window.
+	 *
+	 * @return The size of the dialog
+	 */
+	private Point configureSize() {
+		Shell shell = getShell();
+
+		// Get the packed size of the shell.
+		shell.pack();
+		Point size = shell.getSize();
+
+		// Use the previous width if appropriate.
+		if ((previousWidth != NO_REMEMBERED_WIDTH) && (previousWidth > size.x)) {
+			size.x = previousWidth;
+		}
+
+		// Enforce maximum sizing.
+		Shell workbenchWindowShell = (Shell) shell.getParent();
+		if (workbenchWindowShell != null) {
+			Point workbenchWindowSize = workbenchWindowShell.getSize();
+			int maxWidth = workbenchWindowSize.x * 2 / 5;
+			int maxHeight = workbenchWindowSize.y / 2;
+			if (size.x > maxWidth) {
+				size.x = maxWidth;
+			}
+			if (size.y > maxHeight) {
+				size.y = maxHeight;
+			}
+		}
+
+		// Set the size for the shell.
+		shell.setSize(size);
+		return size;
+	}
+
+	/**
+	 * Creates the content area for the key assistant. This creates a table and
+	 * places it inside the composite. The composite will contain a list of all
+	 * the key bindings.
+	 *
+	 * @param parent
+	 *            The parent composite to contain the dialog area; must not be
+	 *            <code>null</code>.
+	 */
+	@Override
+	protected Control createDialogArea(Composite parent) {
+
+		// Create a composite for the dialog area.
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout compositeLayout = new GridLayout();
+		compositeLayout.marginHeight = 0;
+		compositeLayout.marginWidth = 0;
+		composite.setLayout(compositeLayout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		composite.setBackground(parent.getBackground());
+
+		// Layout the partial matches.
+		Collection<Binding> bindings;
+		// if we're going to display a list of conflicts or partial matches...
+		if (matches != null) {
+			bindings = matches;
+		}
+		// else just grab the entire list of active bindings
+		else {
+			bindings = getActiveBindings();
+		}
+
+		if (bindings == null || bindings.isEmpty()) {
+			createEmptyDialogArea(composite);
+		} else {
+			createTableDialogArea(composite, bindings);
+		}
+		return composite;
+	}
+
+	/**
+	 * Creates an empty dialog area with a simple message saying there were no
+	 * matches. This is used if no partial matches could be found. This should
+	 * not really ever happen, but might be possible if the commands are
+	 * changing while waiting for this dialog to open.
+	 *
+	 * @param parent
+	 *            The parent composite for the dialog area; must not be
+	 *            <code>null</code>.
+	 */
+	private void createEmptyDialogArea(Composite parent) {
+		Label noMatchesLabel = new Label(parent, SWT.NULL);
+		noMatchesLabel.setText("No matches"); //$NON-NLS-1$
+		noMatchesLabel.setLayoutData(new GridData(GridData.FILL_BOTH));
+		noMatchesLabel.setBackground(parent.getBackground());
+	}
+
+	/**
+	 * Creates a dialog area with a table of the partial matches for the current
+	 * key binding state. The table will be either the minimum width, or
+	 * <code>previousWidth</code> if it is not <code>NO_REMEMBERED_WIDTH</code>.
+	 *
+	 * @param parent
+	 *            The parent composite for the dialog area; must not be
+	 *            <code>null</code>.
+	 * @param partialMatches
+	 *            The lexicographically sorted map of partial matches for the
+	 *            current state; must not be <code>null</code> or empty.
+	 */
+	private void createTableDialogArea(Composite parent, Collection<Binding> partialMatches) {
+		// Layout the table.
+		completionsTable = new Table(parent, SWT.FULL_SELECTION | SWT.SINGLE);
+		GridData gridData = new GridData(GridData.FILL_BOTH);
+		completionsTable.setLayoutData(gridData);
+		completionsTable.setBackground(parent.getBackground());
+		completionsTable.setLinesVisible(true);
+
+		// Initialize the columns and rows.
+		bindings.clear();
+		TableColumn columnCommandName = new TableColumn(completionsTable, SWT.LEFT, 0);
+		TableColumn columnKeySequence = new TableColumn(completionsTable, SWT.LEFT, 1);
+		Iterator<Binding> itemsItr = partialMatches.iterator();
+		while (itemsItr.hasNext()) {
+			Binding binding = itemsItr.next();
+			String sequence = binding.getTriggerSequence().format();
+			ParameterizedCommand command = binding.getParameterizedCommand();
+			try {
+				String[] text = { command.getName(), sequence };
+				TableItem item = new TableItem(completionsTable, SWT.NULL);
+				item.setText(text);
+				item.setData(BINDING_KEY, binding);
+				bindings.add(binding);
+			} catch (NotDefinedException e) {
+				// Not much to do, but this shouldn't really happen.
+			}
+		}
+
+		Dialog.applyDialogFont(parent);
+		columnKeySequence.pack();
+		if (previousWidth != NO_REMEMBERED_WIDTH) {
+			columnKeySequence.setWidth(previousWidth);
+		}
+		columnCommandName.pack();
+		if (completionsTable.getItems().length > 0) {
+			completionsTable.setSelection(0);
+		}
+
+		/*
+		 * If you double-click on the table, it should execute the selected
+		 * command.
+		 */
+		completionsTable.addListener(SWT.DefaultSelection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				executeKeyBinding(event);
+			}
+		});
+	}
+
+	/**
+	 * Handles the default selection event on the table of possible completions.
+	 * This attempts to execute the given command.
+	 */
+	private void executeKeyBinding(Event trigger) {
+		int selectionIndex = completionsTable.getSelectionIndex();
+		// Try to execute the corresponding command.
+		if (selectionIndex >= 0) {
+			close();
+			Binding binding = bindings.get(selectionIndex);
+			try {
+				// workbenchKeyboard.updateShellKludge(null);
+				workbenchKeyboard.executeCommand(binding.getParameterizedCommand(), trigger);
+			} catch (CommandException e) {
+				// WorkbenchPlugin.log(binding.getParameterizedCommand().toString(),
+				// e);
+				// TODO we probably need to log something here.
+				System.err.println(binding.getParameterizedCommand().toString() + " : " + e); //$NON-NLS-1$
+			}
+		}
+	}
+
+	private Collection<Binding> getActiveBindings() {
+
+		EBindingService bindingService = context.getActiveLeaf().get(EBindingService.class);
+
+		Iterator<Binding> iter, matchesIter;
+		Binding binding, bindingToAdd;
+		Collection<Binding> matchesForCommand;
+		Collection<Binding> activeBindings = bindingService.getActiveBindings();
+		Collection<Binding> conflictBindings = bindingService.getAllConflicts();
+		Collection<Binding> sortedMatches = new TreeSet<Binding>(new Comparator<Binding>() {
+			@Override
+			public int compare(Binding binding1, Binding binding2) {
+				ParameterizedCommand cmdA = binding1.getParameterizedCommand();
+				ParameterizedCommand cmdB = binding2.getParameterizedCommand();
+				int result = 0;
+				try {
+					result = cmdA.getName().compareTo(cmdB.getName());
+				} catch (NotDefinedException e) {
+					// whaaa?
+				}
+				return result;
+			}
+		});
+
+		// if the active scheme is not the default scheme then we should clean
+		// up the active
+		// bindings list... if we find multiple bindings for the same command
+		// and they are for
+		// different schemes, then we need to handle which one should be
+		// displayed in the dialog
+		if (activeBindings != null) {
+			iter = activeBindings.iterator();
+			while (iter.hasNext()) {
+				binding = iter.next();
+				matchesForCommand = bindingService.getBindingsFor(binding.getParameterizedCommand());
+				// if there is more than one match, then look for a binding that
+				// does not belong to
+				// the default scheme. If they all belong to the default scheme
+				// or they all do NOT
+				// belong to the default scheme, then arbitrarily choose one
+				if (matchesForCommand != null && matchesForCommand.size() > 1) {
+					bindingToAdd = null;
+
+					matchesIter = matchesForCommand.iterator();
+					while (matchesIter.hasNext()) {
+						bindingToAdd = matchesIter.next();
+						if (!bindingToAdd.getSchemeId().equals(EBindingService.DEFAULT_SCHEME_ID)) {
+							sortedMatches.add(bindingToAdd);
+							break;
+						}
+					}
+					// if they're all the same, arbitrarily choose one
+					if (bindingToAdd != null) {
+						sortedMatches.add(bindingToAdd);
+					}
+				}
+				// if there is only one match, then just add it
+				else if (matchesForCommand != null && matchesForCommand.size() == 1) {
+					sortedMatches.addAll(matchesForCommand);
+				}
+			}
+		}
+		if (conflictBindings != null) {
+			iter = conflictBindings.iterator();
+			while (iter.hasNext()) {
+				binding = iter.next();
+				sortedMatches.add(binding);
+			}
+		}
+		return sortedMatches;
+	}
+
+	/**
+	 * Opens this dialog. This method can be called multiple times on the same
+	 * dialog. This only opens the dialog if there is no remembered state; if
+	 * there is remembered state, then it tries to open the preference page
+	 * instead.
+	 *
+	 * @return The return code from this dialog.
+	 */
+	@Override
+	public int open() {
+		// If the dialog is already open, dispose the shell and recreate it.
+		Shell shell = getShell();
+		if (shell != null) {
+			close(false, false);
+			return Window.OK;
+		}
+		create();
+		// Bug 412001. Stop ShellActivationListener from creating a context for
+		// this.
+		getShell().setData("org.eclipse.e4.ui.ignoreDialog", Boolean.TRUE); //$NON-NLS-1$
+
+		// Configure the size and location.
+		Point size = configureSize();
+		configureLocation(size);
+
+		// Call the super method.
+		return super.open();
+	}
+
+	/**
+	 * Opens this dialog with the list of bindings for the user to select from.
+	 *
+	 * @return The return code from this dialog.
+	 * @since 3.3
+	 */
+	public int open(Collection<Binding> bindings) {
+		matches = new TreeSet<Binding>(new Comparator<Binding>() {
+			@Override
+			public int compare(Binding a, Binding b) {
+				Binding bindingA = a;
+				Binding bindingB = b;
+				ParameterizedCommand commandA = bindingA.getParameterizedCommand();
+				ParameterizedCommand commandB = bindingB.getParameterizedCommand();
+				try {
+					return commandA.getName().compareTo(commandB.getName());
+				} catch (NotDefinedException e) {
+					// should not happen
+					return 0;
+				}
+			}
+		});
+		matches.addAll(bindings);
+
+		// If the dialog is already open, dispose the shell and recreate it.
+		Shell shell = getShell();
+		if (shell != null) {
+			close(false, false);
+			return Window.OK;
+		}
+		create();
+		// Bug 369860. Stop ShellActivationListener from creating a context for
+		// this.
+		getShell().setData("org.eclipse.e4.ui.ignoreDialog", Boolean.TRUE); //$NON-NLS-1$
+		// Configure the size and location.
+		Point size = configureSize();
+		configureLocation(size);
+
+		// Call the super method.
+		return super.open();
+	}
+
+	/**
+	 * Exposing this within the keys package.
+	 *
+	 * @param newParentShell
+	 *            The new parent shell; this value may be <code>null</code> if
+	 *            there is to be no parent.
+	 */
+	@Override
+	public void setParentShell(Shell newParentShell) {
+		super.setParentShell(newParentShell);
+	}
+
+	/**
+	 * Returns the currently selected binding from the table if the table is not
+	 * disposed
+	 *
+	 * @return the currently selected binding or <code>null</code>
+	 */
+	protected Binding getSelectedBinding() {
+		if ((completionsTable != null) && (!completionsTable.isDisposed())) {
+			int selectedIndex = completionsTable.getSelectionIndex();
+			if (selectedIndex != -1) {
+				TableItem selectedItem = completionsTable.getItem(selectedIndex);
+				return (Binding) selectedItem.getData(BINDING_KEY);
+			}
+		}
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/KeyBindingDispatcher.java b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/KeyBindingDispatcher.java
new file mode 100644
index 0000000..beaa383
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/KeyBindingDispatcher.java
@@ -0,0 +1,617 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.bindings.keys;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.CommandException;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.bindings.internal.KeyAssistDialog;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.keys.KeySequence;
+import org.eclipse.jface.bindings.keys.KeyStroke;
+import org.eclipse.jface.bindings.keys.ParseException;
+import org.eclipse.jface.bindings.keys.SWTKeySupport;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.custom.CCombo;
+//TODO RAP unsupported import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * <p>
+ * Controls the keyboard input into the workbench key binding architecture. This allows key events
+ * to be programmatically pushed into the key binding architecture -- potentially triggering the
+ * execution of commands. It is used by the <code>e4 Workbench</code> to listen for events on the
+ * <code>Display</code>.
+ * </p>
+ */
+public class KeyBindingDispatcher {
+
+	private KeyAssistDialog keyAssistDialog = null;
+
+	/**
+	 * A display filter for handling key bindings. This filter can either be enabled or disabled. If
+	 * disabled, the filter does not process incoming events. The filter starts enabled.
+	 * 
+	 * @since 3.1
+	 */
+	public final class KeyDownFilter implements Listener {
+
+		/**
+		 * 
+		 */
+		private static final long serialVersionUID = 1L;
+		/**
+		 * Whether the filter is enabled.
+		 */
+		private transient boolean enabled = true;
+
+		/**
+		 * Handles an incoming traverse or key down event.
+		 * 
+		 * @param event
+		 *            The event to process; must not be <code>null</code>.
+		 */
+		@Override
+		public final void handleEvent(final Event event) {
+			if (!enabled) {
+				return;
+			}
+
+			filterKeySequenceBindings(event);
+		}
+
+		/**
+		 * Returns whether the key binding filter is enabled.
+		 * 
+		 * @return Whether the key filter is enabled.
+		 */
+		public final boolean isEnabled() {
+			return enabled;
+		}
+
+		/**
+		 * Sets whether this filter should be enabled or disabled.
+		 * 
+		 * @param enabled
+		 *            Whether key binding filter should be enabled.
+		 */
+		public final void setEnabled(final boolean enabled) {
+			this.enabled = enabled;
+		}
+	}
+
+	/** The collection of keys that are to be processed out-of-order. */
+	static KeySequence outOfOrderKeys;
+
+	static {
+
+		try {
+			outOfOrderKeys = KeySequence.getInstance("ESC DEL"); //$NON-NLS-1$
+		} catch (ParseException e) {
+			outOfOrderKeys = KeySequence.getInstance();
+			// String message = "Could not parse out-of-order keys definition: 'ESC DEL'.  Continuing with no out-of-order keys."; //$NON-NLS-1$
+			// TODO we need to do some logging here
+		}
+	}
+
+	/**
+	 * Generates any key strokes that are near matches to the given event. The first such key stroke
+	 * is always the exactly matching key stroke.
+	 * 
+	 * @param event
+	 *            The event from which the key strokes should be generated; must not be
+	 *            <code>null</code>.
+	 * @return The set of nearly matching key strokes. It is never <code>null</code>, but may be
+	 *         empty.
+	 */
+	public static List<KeyStroke> generatePossibleKeyStrokes(Event event) {
+		final List<KeyStroke> keyStrokes = new ArrayList<KeyStroke>(3);
+
+		/*
+		 * If this is not a keyboard event, then there are no key strokes. This can happen if we are
+		 * listening to focus traversal events.
+		 */
+		if ((event.stateMask == 0) && (event.keyCode == 0) && (event.character == 0)) {
+			return keyStrokes;
+		}
+
+		// Add each unique key stroke to the list for consideration.
+		final int firstAccelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(event);
+		keyStrokes.add(SWTKeySupport.convertAcceleratorToKeyStroke(firstAccelerator));
+
+		// We shouldn't allow delete to undergo shift resolution.
+		if (event.character == SWT.DEL) {
+			return keyStrokes;
+		}
+
+		final int secondAccelerator = SWTKeySupport
+				.convertEventToUnshiftedModifiedAccelerator(event);
+		if (secondAccelerator != firstAccelerator) {
+			keyStrokes.add(SWTKeySupport.convertAcceleratorToKeyStroke(secondAccelerator));
+		}
+
+		final int thirdAccelerator = SWTKeySupport.convertEventToModifiedAccelerator(event);
+		if ((thirdAccelerator != secondAccelerator) && (thirdAccelerator != firstAccelerator)) {
+			keyStrokes.add(SWTKeySupport.convertAcceleratorToKeyStroke(thirdAccelerator));
+		}
+
+		return keyStrokes;
+	}
+
+	/**
+	 * <p>
+	 * Determines whether the given event represents a key press that should be handled as an
+	 * out-of-order event. An out-of-order key press is one that is passed to the focus control
+	 * first. Only if the focus control fails to respond will the regular key bindings get applied.
+	 * </p>
+	 * <p>
+	 * Care must be taken in choosing which keys are chosen as out-of-order keys. This method has
+	 * only been designed and test to work with the unmodified "Escape" key stroke.
+	 * </p>
+	 * 
+	 * @param keyStrokes
+	 *            The key stroke in which to look for out-of-order keys; must not be
+	 *            <code>null</code>.
+	 * @return <code>true</code> if the key is an out-of-order key; <code>false</code> otherwise.
+	 */
+	private static boolean isOutOfOrderKey(List<KeyStroke> keyStrokes) {
+		// Compare to see if one of the possible key strokes is out of order.
+		final KeyStroke[] outOfOrderKeyStrokes = outOfOrderKeys.getKeyStrokes();
+		final int outOfOrderKeyStrokesLength = outOfOrderKeyStrokes.length;
+		for (int i = 0; i < outOfOrderKeyStrokesLength; i++) {
+			if (keyStrokes.contains(outOfOrderKeyStrokes[i])) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * The time in milliseconds to wait after pressing a key before displaying the key assist
+	 * dialog.
+	 */
+	private static final int DELAY = 1000;
+
+	private EBindingService bindingService;
+
+	private IEclipseContext context;
+
+	private EHandlerService handlerService;
+
+	/**
+	 * The listener that runs key events past the global key bindings.
+	 */
+	private final KeyDownFilter keyDownFilter = new KeyDownFilter();
+
+	/**
+	 * The single out-of-order listener used by the workbench. This listener is attached to one
+	 * widget at a time, and is used to catch key down events after all processing is done. This
+	 * technique is used so that some keys will have their native behaviour happen first.
+	 * 
+	 * @since 3.1
+	 */
+	private final OutOfOrderListener outOfOrderListener = new OutOfOrderListener(this);
+
+	// TODO RAP unsupported
+	// /**
+	// * The single out-of-order verify listener used by the workbench. This listener is attached to
+	// * one</code> StyledText</code> at a time, and is used to catch verify events after all
+	// * processing is done. This technique is used so that some keys will have their native
+	// behaviour
+	// * happen first.
+	// *
+	// * @since 3.1
+	// */
+	// private final OutOfOrderVerifyListener outOfOrderVerifyListener = new
+	// OutOfOrderVerifyListener(
+	// outOfOrderListener);
+
+	/**
+	 * The mode is the current state of the key binding architecture. In the case of multi-stroke
+	 * key bindings, this can be a partially complete key binding.
+	 */
+	private KeySequence state = KeySequence.getInstance();
+
+	private long startTime;
+
+	@Inject
+	@Optional
+	private Logger logger;
+
+	/**
+	 * Performs the actual execution of the command by looking up the current handler from the
+	 * command manager. If there is a handler and it is enabled, then it tries the actual execution.
+	 * Execution failures are logged. When this method completes, the key binding state is reset.
+	 * 
+	 * @param parameterizedCommand
+	 *            The command that should be executed; should not be <code>null</code>.
+	 * @param trigger
+	 *            The triggering event; may be <code>null</code>.
+	 * @return <code>true</code> if there was a handler; <code>false</code> otherwise.
+	 * @throws CommandException
+	 *             if the handler does not complete execution for some reason. It is up to the
+	 *             caller of this method to decide whether to log the message, display a dialog, or
+	 *             ignore this exception entirely.
+	 */
+	public final boolean executeCommand(final ParameterizedCommand parameterizedCommand,
+			final Event trigger) throws CommandException {
+
+		// Reset the key binding state (close window, clear status line, etc.)
+		resetState(false);
+
+		final EHandlerService handlerService = getHandlerService();
+		final Command command = parameterizedCommand.getCommand();
+
+		final IEclipseContext staticContext = EclipseContextFactory.create("keys-staticContext"); //$NON-NLS-1$
+		staticContext.set(Event.class, trigger);
+
+		final boolean commandDefined = command.isDefined();
+		// boolean commandEnabled;
+		boolean commandHandled = false;
+
+		try {
+			// commandEnabled = handlerService.canExecute(parameterizedCommand, staticContext);
+			Object obj = HandlerServiceImpl.lookUpHandler(context, command.getId());
+			if (obj != null) {
+				if (obj instanceof IHandler) {
+					commandHandled = ((IHandler) obj).isHandled();
+				} else {
+					commandHandled = true;
+				}
+			}
+
+			handlerService.executeHandler(parameterizedCommand, staticContext);
+			final Object commandException = staticContext.get(HandlerServiceImpl.HANDLER_EXCEPTION);
+			if (commandException instanceof CommandException) {
+				commandHandled = false;
+				if (logger != null && commandException instanceof ExecutionException) {
+					logger.error((Throwable) commandException);
+				}
+			}
+			/*
+			 * Now that the command has executed (and had the opportunity to use the remembered
+			 * state of the dialog), it is safe to delete that information.
+			 */
+			if (keyAssistDialog != null) {
+				keyAssistDialog.clearRememberedState();
+			}
+		} finally {
+			staticContext.dispose();
+		}
+		return (commandDefined && commandHandled);
+	}
+
+	/**
+	 * <p>
+	 * Launches the command matching a the typed key. This filter an incoming
+	 * <code>SWT.KeyDown</code> or <code>SWT.Traverse</code> event at the level of the display
+	 * (i.e., before it reaches the widgets). It does not allow processing in a dialog or if the key
+	 * strokes does not contain a natural key.
+	 * </p>
+	 * <p>
+	 * Some key strokes (defined as a property) are declared as out-of-order keys. This means that
+	 * they are processed by the widget <em>first</em>. Only if the other widget listeners do no
+	 * useful work does it try to process key bindings. For example, "ESC" can cancel the current
+	 * widget action, if there is one, without triggering key bindings.
+	 * </p>
+	 * 
+	 * @param event
+	 *            The incoming event; must not be <code>null</code>.
+	 */
+	private void filterKeySequenceBindings(Event event) {
+		/*
+		 * Only process key strokes containing natural keys to trigger key bindings.
+		 */
+		if ((event.keyCode & SWT.MODIFIER_MASK) != 0) {
+			return;
+		}
+
+		// Allow special key out-of-order processing.
+		List<KeyStroke> keyStrokes = generatePossibleKeyStrokes(event);
+		if (isOutOfOrderKey(keyStrokes)) {
+			Widget widget = event.widget;
+			if ((event.character == SWT.DEL)
+					&& ((event.stateMask & SWT.MODIFIER_MASK) == 0)
+					&& ((widget instanceof Text) || (widget instanceof Combo)
+							|| (widget instanceof Browser) || (widget instanceof CCombo))) {
+				/*
+				 * KLUDGE. Bug 54654. The text widget relies on no listener doing any work before
+				 * dispatching the native delete event. This does not work, as we are restricted to
+				 * listeners. However, it can be said that pressing a delete key in a text widget
+				 * will never use key bindings. This can be shown be considering how the event
+				 * dispatching is expected to work in a text widget. So, we should do nothing ...
+				 * ever.
+				 */
+				return;
+				// TODO RAP unsupported
+				// } else if (widget instanceof StyledText) {
+				//
+				// if (event.type == SWT.KeyDown) {
+				// /*
+				// * KLUDGE. Some people try to do useful work in verify listeners. The way verify
+				// * listeners work in SWT, we need to verify the key as well; otherwise, we can't
+				// * detect that useful work has been done.
+				// */
+				// if (!outOfOrderVerifyListener.isActive(event.time)) {
+				// ((StyledText) widget).addVerifyKeyListener(outOfOrderVerifyListener);
+				// outOfOrderVerifyListener.setActive(event.time);
+				// }
+				// }
+				//
+			} else {
+				if (!outOfOrderListener.isActive(event.time)) {
+					widget.addListener(SWT.KeyDown, outOfOrderListener);
+					outOfOrderListener.setActive(event.time);
+				}
+			}
+
+			/*
+			 * Otherwise, we count on a key down arriving eventually. Expecting out of order
+			 * handling on Ctrl+Tab, for example, is a bad idea (stick to keys that are not window
+			 * traversal keys).
+			 */
+
+		} else {
+			processKeyEvent(keyStrokes, event);
+		}
+	}
+
+	private EBindingService getBindingService() {
+		if (bindingService == null) {
+			bindingService = (EBindingService) context.get(EBindingService.class.getName());
+		}
+		return bindingService;
+	}
+
+	private EHandlerService getHandlerService() {
+		if (handlerService == null) {
+			handlerService = (EHandlerService) context.get(EHandlerService.class.getName());
+		}
+		return handlerService;
+	}
+
+	private Display getDisplay() {
+		return Display.getCurrent();
+	}
+
+	/**
+	 * An accessor for the filter that processes key down and traverse events on the display.
+	 * 
+	 * @return The global key down and traverse filter; never <code>null</code>.
+	 */
+	public KeyDownFilter getKeyDownFilter() {
+		return keyDownFilter;
+	}
+
+	/**
+	 * Determines whether the key sequence is a perfect match for any command. If there is a match,
+	 * then the corresponding command identifier is returned.
+	 * 
+	 * @param keySequence
+	 *            The key sequence to check for a match; must never be <code>null</code>.
+	 * @return The perfectly matching command; <code>null</code> if no command matches.
+	 */
+	private ParameterizedCommand getPerfectMatch(KeySequence keySequence) {
+		Binding perfectMatch = getBindingService().getPerfectMatch(keySequence);
+		return perfectMatch == null ? null : perfectMatch.getParameterizedCommand();
+	}
+
+	/**
+	 * Changes the key binding state to the given value. This should be an incremental change, but
+	 * there are no checks to guarantee this is so. It also sets up a <code>Shell</code> to be
+	 * displayed after one second has elapsed. This shell will show the user the possible
+	 * completions for what they have typed.
+	 * 
+	 * @param sequence
+	 *            The new key sequence for the state; should not be <code>null</code>.
+	 */
+	private void incrementState(final KeySequence sequence) {
+		state = sequence;
+		// Record the starting time.
+		startTime = System.currentTimeMillis();
+		final long myStartTime = startTime;
+		final Display display = getDisplay();
+		display.timerExec(DELAY, new Runnable() {
+			@Override
+			public void run() {
+				if ((System.currentTimeMillis() > (myStartTime - DELAY))
+						&& (startTime == myStartTime)) {
+					Collection<Binding> partialMatches = bindingService.getPartialMatches(sequence);
+					openKeyAssistShell(partialMatches);
+				}
+			}
+		});
+
+	}
+
+	/**
+	 * Opens a <code>KeyAssistDialog</code> to assist the user in completing a multi-stroke key
+	 * binding. This method lazily creates a <code>keyAssistDialog</code> and shares it between
+	 * executions.
+	 */
+	private final void openKeyAssistShell(final Collection<Binding> bindings) {
+		if (keyAssistDialog == null) {
+			keyAssistDialog = new KeyAssistDialog(context, this);
+		}
+		if (keyAssistDialog.getShell() == null) {
+			keyAssistDialog.setParentShell(getDisplay().getActiveShell());
+		}
+		keyAssistDialog.open(bindings);
+	}
+
+	/**
+	 * Determines whether the key sequence partially matches on of the active key bindings.
+	 * 
+	 * @param keySequence
+	 *            The key sequence to check for a partial match; must never be <code>null</code>.
+	 * @return <code>true</code> if there is a partial match; <code>false</code> otherwise.
+	 */
+	private boolean isPartialMatch(KeySequence keySequence) {
+		return getBindingService().isPartialMatch(keySequence);
+	}
+
+	/**
+	 * Determines whether the key sequence perfectly matches on of the active key bindings.
+	 * 
+	 * @param keySequence
+	 *            The key sequence to check for a perfect match; must never be <code>null</code>.
+	 * @return <code>true</code> if there is a perfect match; <code>false</code> otherwise.
+	 */
+	private boolean isPerfectMatch(KeySequence keySequence) {
+		return getBindingService().isPerfectMatch(keySequence);
+	}
+
+	/**
+	 * @param potentialKeyStrokes
+	 * @param event
+	 * @return
+	 */
+	public boolean press(List<KeyStroke> potentialKeyStrokes, Event event) {
+		KeySequence errorSequence = null;
+		Collection<Binding> errorMatch = null;
+
+		KeySequence sequenceBeforeKeyStroke = state;
+		for (Iterator<KeyStroke> iterator = potentialKeyStrokes.iterator(); iterator.hasNext();) {
+			KeySequence sequenceAfterKeyStroke = KeySequence.getInstance(sequenceBeforeKeyStroke,
+					iterator.next());
+			if (isPartialMatch(sequenceAfterKeyStroke)) {
+				incrementState(sequenceAfterKeyStroke);
+				return true;
+
+			} else if (isPerfectMatch(sequenceAfterKeyStroke)) {
+				final ParameterizedCommand cmd = getPerfectMatch(sequenceAfterKeyStroke);
+				try {
+					return executeCommand(cmd, event) || !sequenceBeforeKeyStroke.isEmpty();
+				} catch (final CommandException e) {
+					return true;
+				}
+
+			} else if ((keyAssistDialog != null)
+					&& (keyAssistDialog.getShell() != null)
+					&& ((event.keyCode == SWT.ARROW_DOWN) || (event.keyCode == SWT.ARROW_UP)
+							|| (event.keyCode == SWT.ARROW_LEFT)
+							|| (event.keyCode == SWT.ARROW_RIGHT) || (event.keyCode == SWT.CR)
+							|| (event.keyCode == SWT.PAGE_UP) || (event.keyCode == SWT.PAGE_DOWN))) {
+				// We don't want to swallow keyboard navigation keys.
+				return false;
+
+			} else {
+				Collection<Binding> matches = getBindingService().getConflictsFor(
+						sequenceAfterKeyStroke);
+				if (matches != null && !matches.isEmpty()) {
+					errorSequence = sequenceAfterKeyStroke;
+					errorMatch = matches;
+				}
+			}
+		}
+		resetState(true);
+		if (sequenceBeforeKeyStroke.isEmpty() && errorSequence != null) {
+			openKeyAssistShell(errorMatch);
+		}
+		return !sequenceBeforeKeyStroke.isEmpty();
+	}
+
+	/**
+	 * <p>
+	 * Actually performs the processing of the key event by interacting with the
+	 * <code>ICommandManager</code>. If work is carried out, then the event is stopped here (i.e.,
+	 * <code>event.doit = false</code>). It does not do any processing if there are no matching key
+	 * strokes.
+	 * </p>
+	 * <p>
+	 * If the active <code>Shell</code> is not the same as the one to which the state is associated,
+	 * then a reset occurs.
+	 * </p>
+	 * 
+	 * @param keyStrokes
+	 *            The set of all possible matching key strokes; must not be <code>null</code>.
+	 * @param event
+	 *            The event to process; must not be <code>null</code>.
+	 */
+	void processKeyEvent(List<KeyStroke> keyStrokes, Event event) {
+		// Dispatch the keyboard shortcut, if any.
+		boolean eatKey = false;
+		if (!keyStrokes.isEmpty()) {
+			eatKey = press(keyStrokes, event);
+		}
+
+		if (eatKey) {
+			switch (event.type) {
+			case SWT.KeyDown:
+				event.doit = false;
+				break;
+			case SWT.Traverse:
+				event.detail = SWT.TRAVERSE_NONE;
+				event.doit = true;
+				break;
+			default:
+			}
+			event.type = SWT.NONE;
+		}
+	}
+
+	public void resetState() {
+		resetState(true);
+	}
+
+	private void resetState(boolean clearRememberedState) {
+		startTime = Long.MAX_VALUE;
+		state = KeySequence.getInstance();
+		closeMultiKeyAssistShell();
+		if (keyAssistDialog != null && clearRememberedState) {
+			keyAssistDialog.clearRememberedState();
+		}
+	}
+
+	final public KeySequence getBuffer() {
+		return state;
+	}
+
+	@Inject
+	public void setContext(IEclipseContext context) {
+		this.context = context;
+	}
+
+	/**
+	 * Closes the multi-stroke key binding assistant shell, if it exists and isn't already disposed.
+	 */
+	private void closeMultiKeyAssistShell() {
+		if (keyAssistDialog != null) {
+			final Shell shell = keyAssistDialog.getShell();
+			if ((shell != null) && (!shell.isDisposed()) && (shell.isVisible())) {
+				keyAssistDialog.close(true);
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderListener.java b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderListener.java
new file mode 100644
index 0000000..b24f427
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderListener.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 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.bindings.keys;
+
+import java.util.List;
+import org.eclipse.jface.bindings.keys.KeyStroke;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * A listener that makes sure that global key bindings are processed if no other listeners do any
+ * useful work.
+ * 
+ * @since 3.0
+ */
+final class OutOfOrderListener implements Listener {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * The time at which this listener was last registered to an event. This is the
+	 * <code>event.time</code> value.
+	 * 
+	 * @since 3.1
+	 */
+	private int active = Integer.MIN_VALUE;
+
+	/**
+	 * The keyboard interface to which the event should be passed if it is not eaten.
+	 */
+	private final KeyBindingDispatcher keyboard;
+
+	/**
+	 * Constructs a new instance of <code>OutOfOrderListener</code> with a reference to the keyboard
+	 * interface which should be allowed to process uneaten events.
+	 * 
+	 * @param workbenchKeyboard
+	 *            The keyboard interface for the workbench capable of processing key bindings; must
+	 *            not be <code>null</code>.
+	 */
+	public OutOfOrderListener(KeyBindingDispatcher workbenchKeyboard) {
+		keyboard = workbenchKeyboard;
+	}
+
+	/**
+	 * Handles the key down event on a widget by passing uneaten events to the key binding
+	 * architecture. This is used to allow special keys to reach the widget first -- before being
+	 * processed by the key binding architecture.
+	 * 
+	 * @param event
+	 *            The event to process; must not be <code>null</code>
+	 */
+	@Override
+	public void handleEvent(Event event) {
+		// Always remove myself as a listener.
+		final Widget widget = event.widget;
+		if ((widget != null) && (!widget.isDisposed())) {
+			widget.removeListener(event.type, this);
+		}
+
+		/*
+		 * If the event is still up for grabs, then re-route through the global key filter.
+		 */
+		if (event.doit) {
+			List<KeyStroke> keyStrokes = KeyBindingDispatcher.generatePossibleKeyStrokes(event);
+			keyboard.processKeyEvent(keyStrokes, event);
+		}
+	}
+
+	/**
+	 * Returns whether this listener has been hooked by this event already.
+	 * 
+	 * @param timeRegistered
+	 *            The <code>event.time</code> for the current event.
+	 * @return <code>true</code> if this listener is registered for a different event;
+	 *         <code>false</code> otherwise.
+	 * 
+	 * @since 3.1
+	 */
+	final boolean isActive(final int timeRegistered) {
+		return (active == timeRegistered);
+	}
+
+	/**
+	 * Sets the event time at which this listener was last registered with a widget.
+	 * 
+	 * @param timeRegistered
+	 *            The time at which this listener was last registered with a widget.
+	 * 
+	 * @since 3.1
+	 */
+	final void setActive(final int timeRegistered) {
+		active = timeRegistered;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderVerifyListener.java b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderVerifyListener.java
new file mode 100644
index 0000000..5c7d397
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src-rap/org/eclipse/e4/ui/bindings/keys/OutOfOrderVerifyListener.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 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.bindings.keys;
+
+//TODO RAP unsupported 
+//import org.eclipse.swt.custom.StyledText;
+//import org.eclipse.swt.custom.VerifyKeyListener;
+
+/**
+ * A listener that makes sure that out-of-order processing occurs if no other verify listeners do
+ * any work.
+ * 
+ * @since 3.0
+ */
+// TODO RAP unsupported
+final class OutOfOrderVerifyListener /* implements VerifyKeyListener */{
+	//
+	// /**
+	// * The time at which this listener was last registered to an event. This is the
+	// * <code>event.time</code> value.
+	// *
+	// * @since 3.1
+	// */
+	// private int active = Integer.MIN_VALUE;
+	//
+	// /**
+	// * The listener that will be chained in if the verify event has not been eaten yet.
+	// */
+	// private OutOfOrderListener chainedListener;
+	//
+	// /**
+	// * Constructs a new instance of <code>OutOfOrderVerifyListener</code> with the listener that
+	// * will be chained in.
+	// *
+	// * @param outOfOrderListener
+	// * The listener that should be attached to the widget if the verify event is not
+	// * eaten; must not be <code>null</code>.
+	// */
+	// OutOfOrderVerifyListener(OutOfOrderListener outOfOrderListener) {
+	// chainedListener = outOfOrderListener;
+	// }
+	//
+	// /**
+	// * Returns whether this listener has been hooked by this event already.
+	// *
+	// * @param timeRegistered
+	// * The <code>event.time</code> for the current event.
+	// * @return <code>true</code> if this listener is registered for a different event;
+	// * <code>false</code> otherwise.
+	// *
+	// * @since 3.1
+	// */
+	// final boolean isActive(final int timeRegistered) {
+	// return (active == timeRegistered);
+	// }
+	//
+	// /**
+	// * Sets the event time at which this listener was last registered with a widget.
+	// *
+	// * @param timeRegistered
+	// * The time at which this listener was last registered with a widget.
+	// *
+	// * @since 3.1
+	// */
+	// final void setActive(final int timeRegistered) {
+	// active = timeRegistered;
+	// }
+	//
+	// /**
+	// * Checks whether any other verify listeners have triggered. If not, then it sets up the
+	// * top-level out-of-order listener.
+	// *
+	// * @param event
+	// * The verify event after it has been processed by all other verify listeners; must
+	// * not be <code>null</code>.
+	// */
+	// public void verifyKey(VerifyEvent event) {
+	// // Always remove the listener.
+	// final Widget widget = event.widget;
+	// if ((widget instanceof StyledText) && (!widget.isDisposed())) {
+	// ((StyledText) widget).removeVerifyKeyListener(this);
+	// }
+	//
+	// /*
+	// * If the event is still up for grabs, then re-route through the global key filter.
+	// */
+	// if (event.doit) {
+	// widget.addListener(SWT.Modify, new CancelOnModifyListener(chainedListener));
+	// widget.addListener(SWT.KeyDown, chainedListener);
+	// }
+	// }
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/BindingServiceAddon.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/BindingServiceAddon.java
new file mode 100644
index 0000000..f182376
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/BindingServiceAddon.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 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.bindings;
+
+import javax.annotation.PostConstruct;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.bindings.internal.BindingServiceCreationFunction;
+import org.eclipse.e4.ui.bindings.internal.BindingTableManager;
+import org.eclipse.e4.ui.bindings.internal.ContextSet;
+
+/**
+ * Provide the binding and context id services as an add-on. Must be instantiated against the
+ * application level context.
+ */
+public final class BindingServiceAddon {
+	/**
+	 * @param context
+	 */
+	@PostConstruct
+	public void init(IEclipseContext context) {
+		ContextManager contextManager = context.get(ContextManager.class);
+		ContextSet.setComparator(new ContextSet.CComp(contextManager));
+
+		context.set(BindingTableManager.class,
+				ContextInjectionFactory.make(BindingTableManager.class, context));
+
+		context.set(EBindingService.class.getName(), new BindingServiceCreationFunction());
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/EBindingService.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/EBindingService.java
new file mode 100644
index 0000000..0440713
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/EBindingService.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.bindings;
+
+import java.util.Collection;
+import java.util.Map;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.TriggerSequence;
+
+/**
+ */
+public interface EBindingService {
+
+	public static final String DIALOG_CONTEXT_ID = "org.eclipse.ui.contexts.dialog"; //$NON-NLS-1$
+	public static final String DEFAULT_SCHEME_ID = "org.eclipse.ui.defaultAcceleratorConfiguration"; //$NON-NLS-1$
+	public static final String MODEL_TO_BINDING_KEY = "binding"; //$NON-NLS-1$
+	public static final String ACTIVE_SCHEME_TAG = "activeSchemeId"; //$NON-NLS-1$
+	public static final String SCHEME_ID_ATTR_TAG = "schemeId"; //$NON-NLS-1$
+	public static final String LOCALE_ATTR_TAG = "locale"; //$NON-NLS-1$
+	public static final String PLATFORM_ATTR_TAG = "platform"; //$NON-NLS-1$
+	public static final String TYPE_ATTR_TAG = "type"; //$NON-NLS-1$
+	public static final String DELETED_BINDING_TAG = "deleted"; //$NON-NLS-1$
+
+	Binding createBinding(TriggerSequence sequence, ParameterizedCommand command, String contextId,
+			Map<String, String> attributes);
+
+	void activateBinding(Binding binding);
+
+	void deactivateBinding(Binding binding);
+
+	TriggerSequence createSequence(String sequence);
+
+	Collection<Binding> getConflictsFor(TriggerSequence sequence);
+
+	Collection<Binding> getAllConflicts();
+
+	Binding getPerfectMatch(TriggerSequence trigger);
+
+	boolean isPartialMatch(TriggerSequence keySequence);
+
+	boolean isPerfectMatch(TriggerSequence sequence);
+
+	TriggerSequence getBestSequenceFor(ParameterizedCommand command);
+
+	Collection<TriggerSequence> getSequencesFor(ParameterizedCommand command);
+
+	Collection<Binding> getPartialMatches(TriggerSequence sequence);
+
+	Collection<Binding> getActiveBindings();
+
+	Collection<Binding> getBindingsFor(ParameterizedCommand cmd);
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceCreationFunction.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceCreationFunction.java
new file mode 100644
index 0000000..5b59259
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceCreationFunction.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.bindings.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ *
+ */
+public class BindingServiceCreationFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		return ContextInjectionFactory.make(BindingServiceImpl.class, context);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java
new file mode 100644
index 0000000..2b0f7f4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.bindings.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.bindings.keys.KeyBinding;
+import org.eclipse.jface.bindings.keys.KeySequence;
+import org.eclipse.jface.bindings.keys.ParseException;
+
+/**
+ *
+ */
+public class BindingServiceImpl implements EBindingService {
+
+	final static String ACTIVE_CONTEXTS = "activeContexts"; //$NON-NLS-1$
+	final static String USER_TYPE = "user"; //$NON-NLS-1$
+
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	private BindingTableManager manager;
+
+	@Inject
+	private ContextManager contextManager;
+
+	private ContextSet contextSet = ContextSet.EMPTY;
+
+	@Override
+	public Binding createBinding(TriggerSequence sequence, ParameterizedCommand command,
+			String contextId, Map<String, String> attributes) {
+
+		String schemeId = DEFAULT_SCHEME_ID;
+		String locale = null;
+		String platform = null;
+		int bindingType = Binding.SYSTEM;
+
+		if (sequence != null && !sequence.isEmpty() && contextId != null) {
+			if (attributes != null) {
+				String tmp = attributes.get(SCHEME_ID_ATTR_TAG);
+				if (tmp != null && tmp.length() > 0) {
+					schemeId = tmp;
+				}
+				locale = attributes.get(LOCALE_ATTR_TAG);
+				platform = attributes.get(PLATFORM_ATTR_TAG);
+				if (USER_TYPE.equals(attributes.get(TYPE_ATTR_TAG))) {
+					bindingType = Binding.USER;
+				}
+			}
+			return new KeyBinding((KeySequence) sequence, command, schemeId, contextId, locale,
+					platform, null, bindingType);
+		}
+		return null;
+	}
+
+	@Override
+	public void activateBinding(Binding binding) {
+		String contextId = binding.getContextId();
+		BindingTable table = manager.getTable(contextId);
+		if (table == null) {
+			return;
+		}
+		table.addBinding(binding);
+	}
+
+	@Override
+	public void deactivateBinding(Binding binding) {
+		String contextId = binding.getContextId();
+		BindingTable table = manager.getTable(contextId);
+		if (table == null) {
+			//System.err.println("No binding table for " + contextId); //$NON-NLS-1$
+			return;
+		}
+		table.removeBinding(binding);
+	}
+
+	@Override
+	public TriggerSequence createSequence(String sequence) {
+		try {
+			return KeySequence.getInstance(sequence);
+		} catch (ParseException e) {
+			// should probably log
+		}
+		return null;
+	}
+
+	@Override
+	public Collection<Binding> getConflictsFor(TriggerSequence sequence) {
+		return manager.getConflictsFor(contextSet, sequence);
+	}
+
+	@Override
+	public Collection<Binding> getAllConflicts() {
+		return manager.getAllConflicts();
+	}
+
+	@Override
+	public Binding getPerfectMatch(TriggerSequence trigger) {
+		return manager.getPerfectMatch(contextSet, trigger);
+	}
+
+	@Override
+	public boolean isPartialMatch(TriggerSequence keySequence) {
+		return manager.isPartialMatch(contextSet, keySequence);
+	}
+
+	@Override
+	public TriggerSequence getBestSequenceFor(ParameterizedCommand command) {
+		Binding binding = manager.getBestSequenceFor(contextSet, command);
+		return binding == null ? null : binding.getTriggerSequence();
+	}
+
+	@Override
+	public Collection<TriggerSequence> getSequencesFor(ParameterizedCommand command) {
+		Collection<Binding> bindings = manager.getSequencesFor(contextSet, command);
+		ArrayList<TriggerSequence> sequences = new ArrayList<TriggerSequence>(bindings.size());
+		for (Binding binding : bindings) {
+			sequences.add(binding.getTriggerSequence());
+		}
+		return sequences;
+	}
+
+	@Override
+	public Collection<Binding> getBindingsFor(ParameterizedCommand command) {
+		return manager.getBindingsFor(contextSet, command);
+	}
+
+	@Override
+	public boolean isPerfectMatch(TriggerSequence sequence) {
+		return getPerfectMatch(sequence) != null;
+	}
+
+	@Override
+	public Collection<Binding> getPartialMatches(TriggerSequence sequence) {
+		return manager.getPartialMatches(contextSet, sequence);
+	}
+
+	/**
+	 * @return the context for this service.
+	 */
+	public IEclipseContext getContext() {
+		return context;
+	}
+
+	@Inject
+	public void setContextIds(@Named(ACTIVE_CONTEXTS) @Optional Set<String> set) {
+		if (set == null || set.isEmpty() || contextManager == null) {
+			contextSet = ContextSet.EMPTY;
+			return;
+		}
+		ArrayList<Context> contexts = new ArrayList<Context>();
+		for (String id : set) {
+			contexts.add(contextManager.getContext(id));
+		}
+		contextSet = manager.createContextSet(contexts);
+	}
+
+	@Override
+	public Collection<Binding> getActiveBindings() {
+		return manager.getActiveBindings();
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTable.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTable.java
new file mode 100644
index 0000000..032cca6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTable.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.bindings.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.Trigger;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.bindings.keys.IKeyLookup;
+import org.eclipse.jface.bindings.keys.KeyLookupFactory;
+import org.eclipse.jface.bindings.keys.KeyStroke;
+
+/**
+ * manage tables of bindings that can be used to look up commands from keys.
+ */
+public class BindingTable {
+	private static int compareSchemes(String[] activeSchemeIds, final String schemeId1,
+			final String schemeId2) {
+		if (activeSchemeIds == null || activeSchemeIds.length == 0) {
+			return 0;
+		}
+		if (!schemeId2.equals(schemeId1)) {
+			for (int i = 0; i < activeSchemeIds.length; i++) {
+				final String schemePointer = activeSchemeIds[i];
+				if (schemeId2.equals(schemePointer)) {
+					return 1;
+				} else if (schemeId1.equals(schemePointer)) {
+					return -1;
+				}
+			}
+		}
+		return 0;
+	}
+
+	static class BindingComparator implements Comparator<Binding> {
+		private String[] activeSchemeIds;
+
+		public void setActiveSchemes(String[] activeSchemeIds) {
+			this.activeSchemeIds = activeSchemeIds;
+		}
+
+		public String[] getActiveSchemes() {
+			return this.activeSchemeIds;
+		}
+
+		@Override
+		public int compare(Binding o1, Binding o2) {
+			int rc = compareSchemes(activeSchemeIds, o1.getSchemeId(), o2.getSchemeId());
+			if (rc != 0) {
+				return rc;
+			}
+
+			/*
+			 * Check to see which has the least number of triggers in the trigger sequence.
+			 */
+			final Trigger[] bestTriggers = o1.getTriggerSequence().getTriggers();
+			final Trigger[] currentTriggers = o2.getTriggerSequence().getTriggers();
+			int compareTo = bestTriggers.length - currentTriggers.length;
+			if (compareTo != 0) {
+				return compareTo;
+			}
+
+			/*
+			 * Compare the number of keys pressed in each trigger sequence. Some types of keys count
+			 * less than others (i.e., some types of modifiers keys are less likely to be chosen).
+			 */
+			compareTo = countStrokes(bestTriggers) - countStrokes(currentTriggers);
+			if (compareTo != 0) {
+				return compareTo;
+			}
+
+			// If this is still a tie, then just chose the shortest text.
+			return o1.getTriggerSequence().format().length()
+					- o2.getTriggerSequence().format().length();
+		}
+
+		private final int countStrokes(final Trigger[] triggers) {
+			int strokeCount = triggers.length;
+			for (int i = 0; i < triggers.length; i++) {
+				final Trigger trigger = triggers[i];
+				if (trigger instanceof KeyStroke) {
+					final KeyStroke keyStroke = (KeyStroke) trigger;
+					final int modifierKeys = keyStroke.getModifierKeys();
+					final IKeyLookup lookup = KeyLookupFactory.getDefault();
+					if ((modifierKeys & lookup.getAlt()) != 0) {
+						strokeCount += 8;
+					}
+					if ((modifierKeys & lookup.getCtrl()) != 0) {
+						strokeCount += 2;
+					}
+					if ((modifierKeys & lookup.getShift()) != 0) {
+						strokeCount += 4;
+					}
+					if ((modifierKeys & lookup.getCommand()) != 0) {
+						strokeCount += 2;
+					}
+				} else {
+					strokeCount += 99;
+				}
+			}
+
+			return strokeCount;
+		}
+	}
+
+	public static final BindingComparator BEST_SEQUENCE = new BindingComparator();
+
+	private Context tableId;
+	private ArrayList<Binding> bindings = new ArrayList<Binding>();
+	private Map<TriggerSequence, Binding> bindingsByTrigger = new HashMap<TriggerSequence, Binding>();
+	private Map<ParameterizedCommand, ArrayList<Binding>> bindingsByCommand = new HashMap<ParameterizedCommand, ArrayList<Binding>>();
+	private Map<TriggerSequence, ArrayList<Binding>> bindingsByPrefix = new HashMap<TriggerSequence, ArrayList<Binding>>();
+	private Map<TriggerSequence, ArrayList<Binding>> conflicts = new HashMap<TriggerSequence, ArrayList<Binding>>();
+	private Map<TriggerSequence, ArrayList<Binding>> orderedBindingsByTrigger = new HashMap<TriggerSequence, ArrayList<Binding>>();
+
+	/**
+	 * @param context
+	 */
+	public BindingTable(Context context) {
+		tableId = context;
+	}
+
+	public Context getTableId() {
+		return tableId;
+	}
+
+	public String getId() {
+		return tableId.getId();
+	}
+
+	public Collection<Binding> getConflicts() {
+		Collection<Binding> conflictsList = new ArrayList<Binding>();
+		for (TriggerSequence key : conflicts.keySet()) {
+			ArrayList<Binding> conflictsForTrigger = conflicts.get(key);
+			if (conflictsForTrigger != null) {
+				conflictsList.addAll(conflictsForTrigger);
+			}
+		}
+		return conflictsList;
+	}
+
+	// checks both the active bindings and conflicts list
+	public Collection<Binding> getConflictsFor(TriggerSequence triggerSequence) {
+		return conflicts.get(triggerSequence);
+	}
+
+	public void addBinding(Binding binding) {
+		if (!getId().equals(binding.getContextId())) {
+			throw new IllegalArgumentException("Binding context " + binding.getContextId() //$NON-NLS-1$
+					+ " does not match " + getId()); //$NON-NLS-1$
+		}
+		ArrayList<Binding> bindingList = orderedBindingsByTrigger.get(binding.getTriggerSequence());
+		Binding possibleConflict = bindingsByTrigger.get(binding.getTriggerSequence());
+		if (bindingList == null || bindingList.isEmpty()) {
+			if (possibleConflict != null) {
+				if (bindingList == null) {
+					bindingList = new ArrayList<Binding>();
+					orderedBindingsByTrigger.put(binding.getTriggerSequence(), bindingList);
+				}
+				bindingList.add(binding);
+				bindingList.add(possibleConflict);
+				Collections.sort(bindingList, BEST_SEQUENCE);
+			}
+		} else {
+			bindingList.add(binding);
+			Collections.sort(bindingList, BEST_SEQUENCE);
+		}
+
+		if (possibleConflict != null && bindingList != null && !bindingList.isEmpty()
+				&& bindingList.get(0) != possibleConflict) {
+			removeBindingSimple(possibleConflict);
+			possibleConflict = null;
+		}
+
+		evaluateOrderedBindings(binding.getTriggerSequence(), binding);
+	}
+
+	private void addBindingSimple(Binding binding) {
+		bindings.add(binding);
+		bindingsByTrigger.put(binding.getTriggerSequence(), binding);
+
+		ArrayList<Binding> sequences = bindingsByCommand.get(binding.getParameterizedCommand());
+		if (sequences == null) {
+			sequences = new ArrayList<Binding>();
+			bindingsByCommand.put(binding.getParameterizedCommand(), sequences);
+		}
+		sequences.add(binding);
+		Collections.sort(sequences, BEST_SEQUENCE);
+
+		TriggerSequence[] prefs = binding.getTriggerSequence().getPrefixes();
+		for (int i = 1; i < prefs.length; i++) {
+			ArrayList<Binding> bindings = bindingsByPrefix.get(prefs[i]);
+			if (bindings == null) {
+				bindings = new ArrayList<Binding>();
+				bindingsByPrefix.put(prefs[i], bindings);
+			}
+			bindings.add(binding);
+		}
+	}
+
+	private void removeBindingSimple(Binding binding) {
+		bindings.remove(binding);
+		bindingsByTrigger.remove(binding.getTriggerSequence());
+		ArrayList<Binding> sequences = bindingsByCommand.get(binding.getParameterizedCommand());
+
+		if (sequences != null) {
+			sequences.remove(binding);
+		}
+		TriggerSequence[] prefs = binding.getTriggerSequence().getPrefixes();
+		for (int i = 1; i < prefs.length; i++) {
+			ArrayList<Binding> bindings = bindingsByPrefix.get(prefs[i]);
+			if (bindings != null) {
+				bindings.remove(binding);
+			}
+		}
+	}
+
+	public void removeBinding(Binding binding) {
+		if (!getId().equals(binding.getContextId())) {
+			throw new IllegalArgumentException("Binding context " + binding.getContextId() //$NON-NLS-1$
+					+ " does not match " + getId()); //$NON-NLS-1$
+		}
+		ArrayList<Binding> bindingList = orderedBindingsByTrigger.get(binding.getTriggerSequence());
+		Binding possibleConflict = bindingsByTrigger.get(binding.getTriggerSequence());
+		if (possibleConflict == binding) {
+			removeBindingSimple(binding);
+			if (bindingList != null) {
+				bindingList.remove(binding);
+				if (bindingList.isEmpty()) {
+					orderedBindingsByTrigger.remove(binding.getTriggerSequence());
+				} else {
+					evaluateOrderedBindings(binding.getTriggerSequence(), null);
+				}
+			}
+		} else if (bindingList != null) {
+			bindingList.remove(binding);
+			if (bindingList.isEmpty()) {
+				orderedBindingsByTrigger.remove(binding.getTriggerSequence());
+			} else {
+				evaluateOrderedBindings(binding.getTriggerSequence(), null);
+			}
+		}
+	}
+
+	/**
+	 * @param binding
+	 */
+	private void evaluateOrderedBindings(TriggerSequence sequence, Binding binding) {
+		ArrayList<Binding> bindingList = orderedBindingsByTrigger.get(sequence);
+
+		// calculate binding to be used or any conflicts
+		if (bindingList != null) {
+			if (bindingList.isEmpty()) {
+				orderedBindingsByTrigger.remove(sequence);
+			} else if (bindingList.size() > 1) {
+				Binding msb = bindingList.get(0);
+				Binding lsb = bindingList.get(1);
+				int rc = compareSchemes(BEST_SEQUENCE.getActiveSchemes(), msb.getSchemeId(),
+						lsb.getSchemeId());
+				if (rc == 0) {
+					ArrayList<Binding> conflictList = conflicts.get(sequence);
+					if (conflictList == null) {
+						conflictList = new ArrayList<Binding>();
+						conflicts.put(sequence, conflictList);
+					} else {
+						conflictList.clear();
+					}
+					Iterator<Binding> i = bindingList.iterator();
+					Binding prev = i.next();
+					conflictList.add(prev);
+					while (i.hasNext() && rc == 0) {
+						Binding next = i.next();
+						rc = compareSchemes(BEST_SEQUENCE.getActiveSchemes(), prev.getSchemeId(),
+								next.getSchemeId());
+						if (rc == 0) {
+							conflictList.add(next);
+						}
+						prev = next;
+					}
+				} else {
+					conflicts.remove(sequence);
+					if (bindingsByTrigger.get(sequence) == null) {
+						addBindingSimple(msb);
+					}
+				}
+			} else {
+				if (bindingsByTrigger.get(sequence) == null) {
+					addBindingSimple(bindingList.get(0));
+				}
+				orderedBindingsByTrigger.remove(sequence);
+			}
+		} else if (binding != null) {
+			conflicts.remove(sequence);
+			if (bindingsByTrigger.get(sequence) == null) {
+				addBindingSimple(binding);
+			}
+		}
+	}
+
+	public Binding getPerfectMatch(TriggerSequence trigger) {
+		return bindingsByTrigger.get(trigger);
+	}
+
+	public Binding getBestSequenceFor(ParameterizedCommand command) {
+		ArrayList<Binding> sequences = bindingsByCommand.get(command);
+		if (sequences != null && sequences.size() > 0) {
+			return sequences.get(0);
+		}
+		return null;
+	}
+
+	@SuppressWarnings("unchecked")
+	public Collection<Binding> getSequencesFor(ParameterizedCommand command) {
+		ArrayList<Binding> triggers = bindingsByCommand.get(command);
+		return (Collection<Binding>) (triggers == null ? Collections.EMPTY_LIST : triggers.clone());
+	}
+
+	public Collection<Binding> getPartialMatches(TriggerSequence sequence) {
+		return bindingsByPrefix.get(sequence);
+	}
+
+	public boolean isPartialMatch(TriggerSequence seq) {
+		return bindingsByPrefix.get(seq) != null;
+	}
+
+	public Collection<Binding> getBindings() {
+		return Collections.unmodifiableCollection(bindings);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTableManager.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTableManager.java
new file mode 100644
index 0000000..bdb5a29
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingTableManager.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.bindings.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+import javax.inject.Inject;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.TriggerSequence;
+
+/**
+ * manage tables of bindings that can be used to look up commands from keys.
+ */
+public class BindingTableManager {
+	private static final String BINDING_TABLE_PREFIX = "bindingTable:"; //$NON-NLS-1$
+
+	@Inject
+	private IEclipseContext eclipseContext;
+
+	private ContextSet definedTables = ContextSet.EMPTY;
+
+	private String[] activeSchemeIds;
+
+	public void addTable(BindingTable table) {
+		String contextId = getTableId(table.getId());
+		if (eclipseContext.containsKey(contextId)) {
+			return; // it's already there
+			// throw new IllegalArgumentException("Already contains table " +
+			// contextId); //$NON-NLS-1$
+		}
+		eclipseContext.set(contextId, table);
+		final List<Context> contexts = definedTables.getContexts();
+		if (!contexts.contains(table.getTableId())) {
+			// this is only valid because I'm throwing away the old
+			// definedTables contextSet
+			contexts.add(table.getTableId());
+			definedTables = createContextSet(contexts);
+		}
+	}
+
+	private String getTableId(String id) {
+		return BINDING_TABLE_PREFIX + id;
+	}
+
+	public void removeTable(BindingTable table) {
+		String contextId = getTableId(table.getId());
+		if (!eclipseContext.containsKey(contextId)) {
+			throw new IllegalArgumentException("Does not contains table " + contextId); //$NON-NLS-1$
+		}
+		eclipseContext.remove(contextId);
+		final List<Context> contexts = definedTables.getContexts();
+		if (contexts.contains(table.getTableId())) {
+			// this is only valid because I'm throwing away the old
+			// definedTables contextSet
+			contexts.remove(table.getTableId());
+			definedTables = createContextSet(contexts);
+		}
+	}
+
+	public BindingTable getTable(String id) {
+		return (BindingTable) eclipseContext.get(getTableId(id));
+	}
+
+	// we're just going through each binding table, and returning a
+	// flat list of bindings here
+	public Collection<Binding> getActiveBindings() {
+		ArrayList<Binding> bindings = new ArrayList<Binding>();
+		for (Context ctx : definedTables.getContexts()) {
+			BindingTable table = getTable(ctx.getId());
+			if (table != null) {
+				bindings.addAll(table.getBindings());
+			}
+		}
+		return bindings;
+	}
+
+	public ContextSet createContextSet(Collection<Context> contexts) {
+		return new ContextSet(contexts);
+	}
+
+	public Collection<Binding> getConflictsFor(ContextSet contextSet, TriggerSequence triggerSequence) {
+		Collection<Binding> matches = new ArrayList<Binding>();
+		for (Context ctx : contextSet.getContexts()) {
+			BindingTable table = getTable(ctx.getId());
+			if (table != null) {
+				final Collection<Binding> matchesFor = table.getConflictsFor(triggerSequence);
+				if (matchesFor != null) {
+					matches.addAll(matchesFor);
+				}
+			}
+		}
+		return matches.size() == 0 ? null : matches;
+	}
+
+	public Collection<Binding> getAllConflicts() {
+		Collection<Binding> conflictsList = new ArrayList<Binding>();
+		for (Context ctx : definedTables.getContexts()) {
+			BindingTable table = getTable(ctx.getId());
+			if (table != null) {
+				Collection<Binding> conflictsInTable = table.getConflicts();
+				if (conflictsInTable != null) {
+					conflictsList.addAll(conflictsInTable);
+				}
+			}
+		}
+		return conflictsList;
+	}
+
+	public Binding getPerfectMatch(ContextSet contextSet, TriggerSequence triggerSequence) {
+		Binding result = null;
+		Binding currentResult = null;
+		List<Context> contexts = contextSet.getContexts();
+		ListIterator<Context> it = contexts.listIterator(contexts.size());
+		while (it.hasPrevious()) {
+			Context c = it.previous();
+			BindingTable table = getTable(c.getId());
+			if (table != null) {
+				currentResult = table.getPerfectMatch(triggerSequence);
+			}
+			if (currentResult != null) {
+				if (isMostActiveScheme(currentResult)) {
+					return currentResult;
+				}
+				if (result == null) {
+					result = currentResult;
+				} else {
+					int rc = compareSchemes(result.getSchemeId(), currentResult.getSchemeId());
+					if (rc < 0) {
+						result = currentResult;
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @param currentResult
+	 * @return
+	 */
+	private boolean isMostActiveScheme(Binding currentResult) {
+		if (activeSchemeIds == null || activeSchemeIds.length < 2) {
+			return true;
+		}
+		final String mostActive = activeSchemeIds[0];
+		return mostActive == null ? false : mostActive.equals(currentResult.getSchemeId());
+	}
+
+	public Binding getBestSequenceFor(ContextSet contextSet, ParameterizedCommand parameterizedCommand) {
+		ArrayList<Binding> bindings = (ArrayList<Binding>) getSequencesFor(contextSet, parameterizedCommand);
+		if (bindings.size() == 0) {
+			return null;
+		}
+		return bindings.get(0);
+	}
+
+	public Collection<Binding> getSequencesFor(ContextSet contextSet, ParameterizedCommand parameterizedCommand) {
+		ArrayList<Binding> bindings = new ArrayList<Binding>();
+		List<Context> contexts = contextSet.getContexts();
+		ListIterator<Context> it = contexts.listIterator(contexts.size());
+		while (it.hasPrevious()) {
+			Context c = it.previous();
+			BindingTable table = getTable(c.getId());
+			if (table != null) {
+				Collection<Binding> sequences = table.getSequencesFor(parameterizedCommand);
+				if (sequences != null) {
+					bindings.addAll(sequences);
+				}
+			}
+		}
+		Collections.sort(bindings, BindingTable.BEST_SEQUENCE);
+		return bindings;
+	}
+
+	public Collection<Binding> getBindingsFor(ContextSet contextSet, ParameterizedCommand cmd) {
+		Collection<Binding> bindings = new ArrayList<Binding>();
+		for (Context ctx : contextSet.getContexts()) {
+			BindingTable table = getTable(ctx.getId());
+			if (table != null) {
+				Collection<Binding> matches = table.getSequencesFor(cmd);
+				if (matches != null) {
+					bindings.addAll(matches);
+				}
+			}
+		}
+		return bindings;
+	}
+
+	public boolean isPartialMatch(ContextSet contextSet, TriggerSequence sequence) {
+		List<Context> contexts = contextSet.getContexts();
+		ListIterator<Context> it = contexts.listIterator(contexts.size());
+		while (it.hasPrevious()) {
+			Context c = it.previous();
+			BindingTable table = getTable(c.getId());
+			if (table != null) {
+				if (table.isPartialMatch(sequence)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public Collection<Binding> getPartialMatches(ContextSet contextSet, TriggerSequence sequence) {
+		ArrayList<Binding> bindings = new ArrayList<Binding>();
+		List<Context> contexts = contextSet.getContexts();
+		ListIterator<Context> it = contexts.listIterator(contexts.size());
+		while (it.hasPrevious()) {
+			Context c = it.previous();
+			BindingTable table = getTable(c.getId());
+			if (table != null) {
+				Collection<Binding> partialMatches = table.getPartialMatches(sequence);
+				if (partialMatches != null) {
+					bindings.addAll(partialMatches);
+				}
+			}
+		}
+		return bindings;
+	}
+
+	/**
+	 * @param activeSchemeIds
+	 */
+	public void setActiveSchemes(String[] activeSchemeIds) {
+		this.activeSchemeIds = activeSchemeIds;
+		BindingTable.BEST_SEQUENCE.setActiveSchemes(activeSchemeIds);
+	}
+
+	/*
+	 * Copied from
+	 * org.eclipse.jface.bindings.BindingManager.compareSchemes(String, String)
+	 *
+	 * Returns an in based on scheme 1 < scheme 2
+	 */
+	private final int compareSchemes(final String schemeId1, final String schemeId2) {
+		if (activeSchemeIds == null) {
+			return 0;
+		}
+		if (!schemeId2.equals(schemeId1)) {
+			for (int i = 0; i < activeSchemeIds.length; i++) {
+				final String schemePointer = activeSchemeIds[i];
+				if (schemeId2.equals(schemePointer)) {
+					return 1;
+				} else if (schemeId1.equals(schemePointer)) {
+					return -1;
+				}
+			}
+		}
+		return 0;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/ContextSet.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/ContextSet.java
new file mode 100644
index 0000000..7b1d7c5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/ContextSet.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.bindings.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.core.commands.contexts.ContextManager;
+
+public class ContextSet {
+	public static ContextSet EMPTY = new ContextSet(Collections.EMPTY_LIST);
+
+	public static class CComp implements Comparator<Context> {
+		private ContextManager manager;
+
+		public CComp(ContextManager manager) {
+			this.manager = manager;
+		}
+
+		@Override
+		public int compare(Context o1, Context o2) {
+			if (o1.equals(o2)) {
+				return 0;
+			}
+			int l1 = getLevel(o1);
+			int l2 = getLevel(o2);
+			if (l1 != l2) {
+				return l1 - l2;
+			}
+			return o1.getId().compareTo(o2.getId());
+		}
+
+		private int getLevel(Context c) {
+			int l = 0;
+			try {
+				String parentId = c.getParentId();
+				while (parentId != null) {
+					l++;
+					Context context = manager.getContext(parentId);
+					parentId = context.getParentId();
+				}
+			} catch (NotDefinedException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			return l;
+		}
+	}
+
+	private static Comparator<Context> CONTEXT_COMP = null;
+
+	public static void setComparator(Comparator<Context> comp) {
+		CONTEXT_COMP = comp;
+	}
+
+	public static Comparator<Context> getComparator() {
+		return CONTEXT_COMP;
+	}
+
+	private List<Context> contexts;
+
+	public ContextSet(Collection<Context> c) {
+		contexts = new ArrayList<Context>(c);
+		Collections.sort(contexts, CONTEXT_COMP);
+	}
+
+	public List<Context> getContexts() {
+		return contexts;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (o == this) {
+			return true;
+		}
+		if (!(o instanceof ContextSet)) {
+			return false;
+		}
+		return contexts.equals(((ContextSet) o).contexts);
+	}
+
+	@Override
+	public int hashCode() {
+		return contexts.hashCode();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/Util.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/Util.java
new file mode 100644
index 0000000..f78d09b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/Util.java
@@ -0,0 +1,669 @@
+/*******************************************************************************
+ * Copyright (c) 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.bindings.internal;
+
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import org.eclipse.swt.SWT;
+
+/**
+ * <p>
+ * A static class providing utility methods to all of JFace.
+ * </p>
+ *
+ * @since 3.1
+ */
+public final class Util {
+
+	/**
+	 * A common zero-length string. It avoids needing write <code>NON-NLS</code>
+	 * next to code fragments. It's also a bit clearer to read.
+	 */
+	public static final String ZERO_LENGTH_STRING = ""; //$NON-NLS-1$
+
+	/**
+	 * Verifies that the given object is an instance of the given class.
+	 *
+	 * @param object
+	 *            The object to check; may be <code>null</code>.
+	 * @param c
+	 *            The class which the object should be; must not be
+	 *            <code>null</code>.
+	 */
+	public static final void assertInstance(final Object object, final Class<?> c) {
+		assertInstance(object, c, false);
+	}
+
+	/**
+	 * Verifies the given object is an instance of the given class. It is
+	 * possible to specify whether the object is permitted to be
+	 * <code>null</code>.
+	 *
+	 * @param object
+	 *            The object to check; may be <code>null</code>.
+	 * @param c
+	 *            The class which the object should be; must not be
+	 *            <code>null</code>.
+	 * @param allowNull
+	 *            Whether the object is allowed to be <code>null</code>.
+	 */
+	private static final void assertInstance(final Object object, final Class<?> c, final boolean allowNull) {
+		if (object == null && allowNull) {
+			return;
+		}
+
+		if (object == null || c == null) {
+			throw new NullPointerException();
+		} else if (!c.isInstance(object)) {
+			throw new IllegalArgumentException();
+		}
+	}
+
+	/**
+	 * Compares two boolean values. <code>false</code> is considered to be
+	 * "less than" <code>true</code>.
+	 *
+	 * @param left
+	 *            The left value to compare
+	 * @param right
+	 *            The right value to compare
+	 * @return <code>-1</code> if the left is <code>false</code> and the right
+	 *         is <code>true</code>. <code>1</code> if the opposite is true. If
+	 *         they are equal, then it returns <code>0</code>.
+	 */
+	public static final int compare(final boolean left, final boolean right) {
+		return left == false ? (right == true ? -1 : 0) : 1;
+	}
+
+	/**
+	 * Compares two integer values.
+	 *
+	 * @param left
+	 *            The left value to compare
+	 * @param right
+	 *            The right value to compare
+	 * @return <code>left - right</code>
+	 */
+	public static final int compare(final int left, final int right) {
+		return left - right;
+	}
+
+	/**
+	 * Compares to comparable objects -- defending against <code>null</code>.
+	 *
+	 * @param <T>
+	 *
+	 * @param left
+	 *            The left object to compare; may be <code>null</code>.
+	 * @param right
+	 *            The right object to compare; may be <code>null</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to
+	 *         be the least possible value.
+	 */
+	@SuppressWarnings("unchecked")
+	public static final <T> int compare(final Comparable<T> left, final Comparable<T> right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			return left.compareTo((T) right);
+		}
+	}
+
+	/**
+	 * Compares two arrays of comparable objects -- accounting for
+	 * <code>null</code>.
+	 *
+	 * @param left
+	 *            The left array to be compared; may be <code>null</code>.
+	 * @param right
+	 *            The right array to be compared; may be <code>null</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to
+	 *         be the least possible value. A shorter array is considered less
+	 *         than a longer array.
+	 */
+	public static final <T> int compare(final Comparable<T>[] left, final Comparable<T>[] right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			int l = left.length;
+			int r = right.length;
+
+			if (l != r) {
+				return l - r;
+			}
+
+			for (int i = 0; i < l; i++) {
+				int compareTo = compare(left[i], right[i]);
+
+				if (compareTo != 0) {
+					return compareTo;
+				}
+			}
+
+			return 0;
+		}
+	}
+
+	/**
+	 * Compares two lists -- account for <code>null</code>. The lists must
+	 * contain comparable objects.
+	 *
+	 * @param left
+	 *            The left list to compare; may be <code>null</code>. This list
+	 *            must only contain instances of <code>Comparable</code>.
+	 * @param right
+	 *            The right list to compare; may be <code>null</code>. This list
+	 *            must only contain instances of <code>Comparable</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to
+	 *         be the least possible value. A shorter list is considered less
+	 *         than a longer list.
+	 */
+	public static final <T> int compare(final List<Comparable<T>> left, final List<Comparable<T>> right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			int l = left.size();
+			int r = right.size();
+
+			if (l != r) {
+				return l - r;
+			}
+
+			for (int i = 0; i < l; i++) {
+				int compareTo = compare(left.get(i), right.get(i));
+
+				if (compareTo != 0) {
+					return compareTo;
+				}
+			}
+
+			return 0;
+		}
+	}
+
+	/**
+	 * Tests whether the first array ends with the second array.
+	 *
+	 * @param left
+	 *            The array to check (larger); may be <code>null</code>.
+	 * @param right
+	 *            The array that should be a subsequence (smaller); may be
+	 *            <code>null</code>.
+	 * @param equals
+	 *            Whether the two array are allowed to be equal.
+	 * @return <code>true</code> if the second array is a subsequence of the
+	 *         array list, and they share end elements.
+	 */
+	public static final boolean endsWith(final Object[] left, final Object[] right, final boolean equals) {
+		if (left == null || right == null) {
+			return false;
+		}
+
+		int l = left.length;
+		int r = right.length;
+
+		if (r > l || !equals && r == l) {
+			return false;
+		}
+
+		for (int i = 0; i < r; i++) {
+			if (!equals(left[l - i - 1], right[r - i - 1])) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Checks whether the two objects are <code>null</code> -- allowing for
+	 * <code>null</code>.
+	 *
+	 * @param left
+	 *            The left object to compare; may be <code>null</code>.
+	 * @param right
+	 *            The right object to compare; may be <code>null</code>.
+	 * @return <code>true</code> if the two objects are equivalent;
+	 *         <code>false</code> otherwise.
+	 */
+	public static final boolean equals(final Object left, final Object right) {
+		return left == null ? right == null : ((right != null) && left.equals(right));
+	}
+
+	/**
+	 * Tests whether two arrays of objects are equal to each other. The arrays
+	 * must not be <code>null</code>, but their elements may be
+	 * <code>null</code>.
+	 *
+	 * @param leftArray
+	 *            The left array to compare; may be <code>null</code>, and may
+	 *            be empty and may contain <code>null</code> elements.
+	 * @param rightArray
+	 *            The right array to compare; may be <code>null</code>, and may
+	 *            be empty and may contain <code>null</code> elements.
+	 * @return <code>true</code> if the arrays are equal length and the elements
+	 *         at the same position are equal; <code>false</code> otherwise.
+	 */
+	public static final boolean equals(final Object[] leftArray, final Object[] rightArray) {
+		if (leftArray == rightArray) {
+			return true;
+		}
+
+		if (leftArray == null) {
+			return (rightArray == null);
+		} else if (rightArray == null) {
+			return false;
+		}
+
+		if (leftArray.length != rightArray.length) {
+			return false;
+		}
+
+		for (int i = 0; i < leftArray.length; i++) {
+			final Object left = leftArray[i];
+			final Object right = rightArray[i];
+			final boolean equal = (left == null) ? (right == null) : (left.equals(right));
+			if (!equal) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Provides a hash code based on the given integer value.
+	 *
+	 * @param i
+	 *            The integer value
+	 * @return <code>i</code>
+	 */
+	public static final int hashCode(final int i) {
+		return i;
+	}
+
+	/**
+	 * Provides a hash code for the object -- defending against
+	 * <code>null</code>.
+	 *
+	 * @param object
+	 *            The object for which a hash code is required.
+	 * @return <code>object.hashCode</code> or <code>0</code> if
+	 *         <code>object</code> if <code>null</code>.
+	 */
+	public static final int hashCode(final Object object) {
+		return object != null ? object.hashCode() : 0;
+	}
+
+	/**
+	 * Computes the hash code for an array of objects, but with defense against
+	 * <code>null</code>.
+	 *
+	 * @param objects
+	 *            The array of objects for which a hash code is needed; may be
+	 *            <code>null</code>.
+	 * @return The hash code for <code>objects</code>; or <code>0</code> if
+	 *         <code>objects</code> is <code>null</code>.
+	 */
+	public static final int hashCode(final Object[] objects) {
+		if (objects == null) {
+			return 0;
+		}
+
+		int hashCode = 89;
+		for (int i = 0; i < objects.length; i++) {
+			final Object object = objects[i];
+			if (object != null) {
+				hashCode = hashCode * 31 + object.hashCode();
+			}
+		}
+
+		return hashCode;
+	}
+
+	/**
+	 * Checks whether the second array is a subsequence of the first array, and
+	 * that they share common starting elements.
+	 *
+	 * @param left
+	 *            The first array to compare (large); may be <code>null</code>.
+	 * @param right
+	 *            The second array to compare (small); may be <code>null</code>.
+	 * @param equals
+	 *            Whether it is allowed for the two arrays to be equivalent.
+	 * @return <code>true</code> if the first arrays starts with the second
+	 *         list; <code>false</code> otherwise.
+	 */
+	public static final boolean startsWith(final Object[] left, final Object[] right, final boolean equals) {
+		if (left == null || right == null) {
+			return false;
+		}
+
+		int l = left.length;
+		int r = right.length;
+
+		if (r > l || !equals && r == l) {
+			return false;
+		}
+
+		for (int i = 0; i < r; i++) {
+			if (!equals(left[i], right[i])) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Converts an array into a string representation that is suitable for
+	 * debugging.
+	 *
+	 * @param array
+	 *            The array to convert; may be <code>null</code>.
+	 * @return The string representation of the array; never <code>null</code>.
+	 */
+	public static final String toString(final Object[] array) {
+		if (array == null) {
+			return "null"; //$NON-NLS-1$
+		}
+
+		final StringBuffer buffer = new StringBuffer();
+		buffer.append('[');
+
+		final int length = array.length;
+		for (int i = 0; i < length; i++) {
+			if (i != 0) {
+				buffer.append(',');
+			}
+			final Object object = array[i];
+			final String element = String.valueOf(object);
+			buffer.append(element);
+		}
+		buffer.append(']');
+
+		return buffer.toString();
+	}
+
+	/**
+	 * Provides a translation of a particular key from the resource bundle.
+	 *
+	 * @param resourceBundle
+	 *            The key to look up in the resource bundle; should not be
+	 *            <code>null</code>.
+	 * @param key
+	 *            The key to look up in the resource bundle; should not be
+	 *            <code>null</code>.
+	 * @param defaultString
+	 *            The value to return if the resource cannot be found; may be
+	 *            <code>null</code>.
+	 * @return The value of the translated resource at <code>key</code>. If the
+	 *         key cannot be found, then it is simply the
+	 *         <code>defaultString</code>.
+	 */
+	public static final String translateString(final ResourceBundle resourceBundle, final String key,
+			final String defaultString) {
+		if (resourceBundle != null && key != null) {
+			try {
+				final String translatedString = resourceBundle.getString(key);
+
+				if (translatedString != null) {
+					return translatedString;
+				}
+			} catch (MissingResourceException eMissingResource) {
+				// Such is life. We'll return the key
+			}
+		}
+
+		return defaultString;
+	}
+
+	/**
+	 * Foundation replacement for String.replaceAll(*).
+	 *
+	 * @param src
+	 *            the starting string.
+	 * @param find
+	 *            the string to find.
+	 * @param replacement
+	 *            the string to replace.
+	 * @return The new string.
+	 * @since 3.4
+	 */
+	public static final String replaceAll(String src, String find, String replacement) {
+		final int len = src.length();
+		final int findLen = find.length();
+
+		int idx = src.indexOf(find);
+		if (idx < 0) {
+			return src;
+		}
+
+		StringBuffer buf = new StringBuffer();
+		int beginIndex = 0;
+		while (idx != -1 && idx < len) {
+			buf.append(src.substring(beginIndex, idx));
+			buf.append(replacement);
+
+			beginIndex = idx + findLen;
+			if (beginIndex < len) {
+				idx = src.indexOf(find, beginIndex);
+			} else {
+				idx = -1;
+			}
+		}
+		if (beginIndex < len) {
+			buf.append(src.substring(beginIndex, (idx == -1 ? len : idx)));
+		}
+		return buf.toString();
+	}
+
+	//
+	// Methods for working with the windowing system
+	//
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_WIN32 = "win32";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_MOTIF = "motif";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_GTK = "gtk";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_PHOTON = "photon";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_CARBON = "carbon";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_COCOA = "cocoa";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_WPF = "wpf";//$NON-NLS-1$
+
+	/**
+	 * Windowing system constant.
+	 *
+	 * @since 3.5
+	 */
+	public static final String WS_UNKNOWN = "unknown";//$NON-NLS-1$
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for windows platforms
+	 * @since 3.5
+	 */
+	public static final boolean isWindows() {
+		final String ws = SWT.getPlatform();
+		return WS_WIN32.equals(ws) || WS_WPF.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for mac platforms
+	 * @since 3.5
+	 */
+	public static final boolean isMac() {
+		final String ws = SWT.getPlatform();
+		return WS_CARBON.equals(ws) || WS_COCOA.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for linux platform
+	 * @since 3.5
+	 */
+	public static final boolean isLinux() {
+		final String ws = SWT.getPlatform();
+		return WS_GTK.equals(ws) || WS_MOTIF.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for gtk platforms
+	 * @since 3.5
+	 */
+	public static final boolean isGtk() {
+		final String ws = SWT.getPlatform();
+		return WS_GTK.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for motif platforms
+	 * @since 3.5
+	 */
+	public static final boolean isMotif() {
+		final String ws = SWT.getPlatform();
+		return WS_MOTIF.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for photon platforms
+	 * @since 3.5
+	 */
+	public static final boolean isPhoton() {
+		final String ws = SWT.getPlatform();
+		return WS_PHOTON.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for carbon platforms
+	 * @since 3.5
+	 */
+	public static final boolean isCarbon() {
+		final String ws = SWT.getPlatform();
+		return WS_CARBON.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for the cocoa platform.
+	 * @since 3.5
+	 */
+	public static final boolean isCocoa() {
+		final String ws = SWT.getPlatform();
+		return WS_COCOA.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for WPF
+	 * @since 3.5
+	 */
+	public static final boolean isWpf() {
+		final String ws = SWT.getPlatform();
+		return WS_WPF.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return <code>true</code> for win32
+	 * @since 3.5
+	 */
+	public static final boolean isWin32() {
+		final String ws = SWT.getPlatform();
+		return WS_WIN32.equals(ws);
+	}
+
+	/**
+	 * Common WS query helper method.
+	 *
+	 * @return the SWT windowing platform string.
+	 * @see SWT#getPlatform()
+	 * @since 3.5
+	 */
+	public static final String getWS() {
+		return SWT.getPlatform();
+	}
+
+	/**
+	 * This class should never be constructed.
+	 */
+	private Util() {
+		// Not allowed.
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/keys/CancelOnModifyListener.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/keys/CancelOnModifyListener.java
new file mode 100644
index 0000000..49c4d4b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/keys/CancelOnModifyListener.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 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.bindings.keys;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * A listener that removes the out-of-order listener if a modification occurs before reaching it.
+ * This is a workaround for Bug 53497.
+ * 
+ * @since 3.0
+ */
+final class CancelOnModifyListener implements Listener {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	/**
+	 * The listener to remove when this listener catches any event. This value should not be
+	 * <code>null</code>.
+	 */
+	private final Listener chainedListener;
+
+	/**
+	 * Constructs a new instance of <code>CancelOnModifyListener</code>
+	 * 
+	 * @param listener
+	 *            The listener which should be removed in the event of a modification event
+	 *            arriving; should not be <code>null</code>.
+	 */
+	CancelOnModifyListener(Listener listener) {
+		chainedListener = listener;
+	}
+
+	@Override
+	public void handleEvent(Event event) {
+		Widget widget = event.widget;
+		widget.removeListener(SWT.Modify, this);
+		widget.removeListener(SWT.KeyDown, chainedListener);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.classpath b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.classpath
new file mode 100644
index 0000000..bd3096f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-rap"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.project b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.project
new file mode 100644
index 0000000..2f4fe04
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.workbench.addons.swt</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.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..2be4073
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,419 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..8bd6e3c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,124 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*******************************************************************************\n * Copyright (c) ${year} IBM Corporation and others.\n * All rights reserved. This program and the accompanying materials\n * are made available under the terms of the Eclipse Public License v1.0\n * which accompanies this distribution, and is available at\n * http\://www.eclipse.org/legal/epl-v10.html\n *\n * Contributors\:\n *     IBM Corporation - initial API and implementation\n ******************************************************************************/\n</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=false
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e032b52
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/MANIFEST.MF
@@ -0,0 +1,32 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.ui.workbench.addons.swt;singleton:=true
+Bundle-Version: 1.2.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
+ org.eclipse.e4.core.contexts;bundle-version="0.9.0",
+ org.eclipse.e4.core.di;bundle-version="0.9.0",
+ org.eclipse.e4.ui.workbench;bundle-version="0.9.1",
+ org.eclipse.e4.core.services;bundle-version="0.9.1",
+ org.eclipse.osgi.services;bundle-version="[3.2.100,4.0.0)",
+ org.eclipse.e4.ui.workbench.renderers.swt;bundle-version="0.9.1",
+ org.eclipse.core.runtime;bundle-version="[3.7.0,4.0.0)",
+ org.eclipse.e4.ui.di;bundle-version="0.10.0",
+ org.eclipse.e4.ui.services;bundle-version="1.0.0",
+ org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",
+ org.eclipse.rap.rwt;bundle-version="2.3.0",
+ org.eclipse.rap.jface;bundle-version="2.3.0"
+Require-Capability: org.eclipse.rap
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.e4.ui.internal.workbench.swt,
+ org.eclipse.osgi.util;version="1.1.0"
+Export-Package: org.eclipse.e4.ui.workbench.addons.cleanupaddon;x-internal:=true,
+ org.eclipse.e4.ui.workbench.addons.dndaddon;x-internal:=true,
+ org.eclipse.e4.ui.workbench.addons.minmax;x-internal:=true,
+ org.eclipse.e4.ui.workbench.addons.splitteraddon;x-internal:=true,
+ org.eclipse.e4.ui.workbench.addons.swt;x-internal:=true
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/p2.inf b/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/about.html b/bundles/org.eclipse.e4.ui.workbench.addons.swt/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/build.properties b/bundles/org.eclipse.e4.ui.workbench.addons.swt/build.properties
new file mode 100644
index 0000000..a111faf
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/build.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# opyright (c) 2013, 2015 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
+###############################################################################
+source.. = src/,\
+           src-rap/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.properties,\
+               plugin.xml,\
+               icons/
+src.includes = icons/,\
+               about.html
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.ui.workbench.addons.swt/forceQualifierUpdate.txt
new file mode 100644
index 0000000..81470cd
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/forceQualifierUpdate.txt
@@ -0,0 +1,3 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
+Bug 429184 - [Metadata] comparator errors in most recent I-builds
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/etool16/fastview_restore.gif b/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/etool16/fastview_restore.gif
new file mode 100644
index 0000000..e0010df
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/etool16/fastview_restore.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/obj16/layout_co.gif b/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/obj16/layout_co.gif
new file mode 100644
index 0000000..c98cdd4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/icons/full/obj16/layout_co.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.properties b/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.properties
new file mode 100644
index 0000000..c43a3fe
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2010, 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
+###############################################################################
+pluginName = Eclipse e4 Workbench Add-ons
+providerName = Eclipse.org
+
+extension.addonsnippet.name = Addon Snippet
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.xml b/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.xml
new file mode 100644
index 0000000..4e5ddf6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/plugin.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         id="AddonSnippet"
+         name="%extension.addonsnippet.name"
+         point="org.eclipse.e4.workbench.model">
+      <processor
+            beforefragment="true"
+            class="org.eclipse.e4.ui.workbench.addons.swt.CleanupProcessor">
+      </processor>
+      <processor
+            beforefragment="true"
+            class="org.eclipse.e4.ui.workbench.addons.swt.MinMaxProcessor">
+      </processor>
+      <!--processor
+            beforefragment="true"
+            class="org.eclipse.e4.ui.workbench.addons.swt.DnDProcessor">
+      </processor-->
+      <processor
+            beforefragment="true"
+            class="org.eclipse.e4.ui.workbench.addons.swt.SplitterProcessor">
+      </processor>
+   </extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/pom.xml b/bundles/org.eclipse.e4.ui.workbench.addons.swt/pom.xml
new file mode 100644
index 0000000..ed2d0a3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.workbench.addons.swt</artifactId>
+  <version>1.2.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src-rap/org/eclipse/e4/ui/workbench/addons/minmax/TrimPaneLayout.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src-rap/org/eclipse/e4/ui/workbench/addons/minmax/TrimPaneLayout.java
new file mode 100644
index 0000000..3e7c367
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src-rap/org/eclipse/e4/ui/workbench/addons/minmax/TrimPaneLayout.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.addons.minmax;
+
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+
+/**
+ *
+ */
+public class TrimPaneLayout extends Layout {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private static int BORDER_WIDTH = 4;
+	private int fixedCorner;
+
+	public Rectangle hSizingRect;
+	public Rectangle vSizingRect;
+	public Rectangle cornerRect;
+	private Rectangle clientRect;
+	private boolean resizeInstalled = false;
+
+	// private static int NOT_SIZING = 0;
+	// private static int HORIZONTAL_SIZING = 1;
+	// private static int VERTICAL_SIZING = 2;
+	// private static int CORNER_SIZING = 3;
+
+	int trackState = SWT.NONE;
+	protected Point curPos;
+
+	// private MToolControl toolControl;
+
+	public TrimPaneLayout(MToolControl toolControl, int barSide) {
+		// this.toolControl = toolControl;
+		this.fixedCorner = barSide;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int,
+	 * boolean)
+	 */
+	@Override
+	protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+		return new Point(600, 400);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
+	 */
+	@Override
+	protected void layout(Composite composite, boolean flushCache) {
+		installResize(composite);
+
+		if (composite.getChildren().length != 1)
+			return;
+
+		if (fixedCorner == SWT.NONE)
+			return;
+
+		Rectangle bounds = composite.getBounds();
+
+		if (isFixed(SWT.TOP)) {
+			if (isFixed(SWT.RIGHT)) {
+				hSizingRect = new Rectangle(0, 0, BORDER_WIDTH, bounds.height - BORDER_WIDTH);
+				vSizingRect = new Rectangle(BORDER_WIDTH, bounds.height - BORDER_WIDTH,
+						bounds.width - BORDER_WIDTH, BORDER_WIDTH);
+				cornerRect = new Rectangle(0, bounds.height - BORDER_WIDTH, BORDER_WIDTH,
+						BORDER_WIDTH);
+				clientRect = new Rectangle(BORDER_WIDTH, 0, bounds.width - BORDER_WIDTH,
+						bounds.height - BORDER_WIDTH);
+			} else {
+				hSizingRect = new Rectangle(bounds.width - BORDER_WIDTH, 0, BORDER_WIDTH,
+						bounds.height - BORDER_WIDTH);
+				vSizingRect = new Rectangle(0, bounds.height - BORDER_WIDTH, bounds.width
+						- BORDER_WIDTH, BORDER_WIDTH);
+				cornerRect = new Rectangle(bounds.width - BORDER_WIDTH, bounds.height
+						- BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH);
+				clientRect = new Rectangle(0, 0, bounds.width - BORDER_WIDTH, bounds.height
+						- BORDER_WIDTH);
+			}
+		} else if (isFixed(SWT.BOTTOM)) {
+			if (isFixed(SWT.RIGHT)) {
+				hSizingRect = new Rectangle(0, BORDER_WIDTH, BORDER_WIDTH, bounds.height
+						- BORDER_WIDTH);
+				vSizingRect = new Rectangle(BORDER_WIDTH, 0, bounds.width - BORDER_WIDTH,
+						BORDER_WIDTH);
+				cornerRect = new Rectangle(0, 0, BORDER_WIDTH, BORDER_WIDTH);
+				clientRect = new Rectangle(BORDER_WIDTH, BORDER_WIDTH, bounds.width - BORDER_WIDTH,
+						bounds.height - BORDER_WIDTH);
+			} else {
+				hSizingRect = new Rectangle(bounds.width - BORDER_WIDTH, BORDER_WIDTH,
+						BORDER_WIDTH, bounds.height - BORDER_WIDTH);
+				vSizingRect = new Rectangle(0, 0, bounds.width - BORDER_WIDTH, BORDER_WIDTH);
+				cornerRect = new Rectangle(bounds.width - BORDER_WIDTH, 0, BORDER_WIDTH,
+						BORDER_WIDTH);
+				clientRect = new Rectangle(0, BORDER_WIDTH, bounds.width - BORDER_WIDTH,
+						bounds.height - BORDER_WIDTH);
+			}
+		}
+		Control child = composite.getChildren()[0];
+		child.setBounds(clientRect);
+	}
+
+	private void installResize(final Composite composite) {
+		if (resizeInstalled)
+			return;
+		// FIXME RAP Needs native support on client
+		// composite.addMouseMoveListener(new MouseMoveListener() {
+		// /**
+		// *
+		// */
+		// private static final long serialVersionUID = 1L;
+		//
+		// @Override
+		// public void mouseMove(MouseEvent e) {
+		// Point p = e.display.getCursorLocation();
+		// if (trackState == NOT_SIZING) {
+		// setCursor(composite, new Point(e.x, e.y));
+		// } else if (trackState == HORIZONTAL_SIZING) {
+		// dragHorizontal(composite, p);
+		// } else if (trackState == VERTICAL_SIZING) {
+		// dragVertical(composite, p);
+		// } else if (trackState == CORNER_SIZING) {
+		// dragCorner(composite, p);
+		// }
+		// }
+		// });
+		//
+		// composite.addMouseListener(new MouseListener() {
+		//
+		// /**
+		// *
+		// */
+		// private static final long serialVersionUID = 1L;
+		//
+		// @Override
+		// public void mouseUp(MouseEvent e) {
+		// composite.setCapture(false);
+		//
+		// // Persist the current size
+		// Point size = composite.getSize();
+		// toolControl.getPersistedState()
+		// .put(TrimStack.STATE_XSIZE, Integer.toString(size.x));
+		// toolControl.getPersistedState()
+		// .put(TrimStack.STATE_YSIZE, Integer.toString(size.y));
+		//
+		// trackState = NOT_SIZING;
+		// }
+		//
+		// @Override
+		// public void mouseDown(MouseEvent e) {
+		// Point p = new Point(e.x, e.y);
+		// if (hSizingRect.contains(p)) {
+		// curPos = e.display.getCursorLocation();
+		// trackState = HORIZONTAL_SIZING;
+		// composite.setCapture(true);
+		// } else if (vSizingRect.contains(p)) {
+		// curPos = e.display.getCursorLocation();
+		// trackState = VERTICAL_SIZING;
+		// composite.setCapture(true);
+		// } else if (cornerRect.contains(p)) {
+		// curPos = e.display.getCursorLocation();
+		// trackState = CORNER_SIZING;
+		// composite.setCapture(true);
+		// }
+		// }
+		//
+		// @Override
+		// public void mouseDoubleClick(MouseEvent e) {
+		// }
+		// });
+		//
+		// composite.addMouseTrackListener(new MouseTrackListener() {
+		// /**
+		// *
+		// */
+		// private static final long serialVersionUID = 1L;
+		//
+		// @Override
+		// public void mouseHover(MouseEvent e) {
+		// }
+		//
+		// @Override
+		// public void mouseExit(MouseEvent e) {
+		// Composite comp = (Composite) e.widget;
+		// comp.setCursor(null);
+		// }
+		//
+		// @Override
+		// public void mouseEnter(MouseEvent e) {
+		// }
+		// });
+		//
+		// resizeInstalled = true;
+	}
+
+	/**
+	 * @param p
+	 */
+	protected void setCursor(Composite composite, Point p) {
+		if (hSizingRect.contains(p)) {
+			composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE));
+		} else if (vSizingRect.contains(p)) {
+			composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZENS));
+		} else if (cornerRect.contains(p)) {
+			if (isFixed(SWT.TOP)) {
+				if (isFixed(SWT.RIGHT))
+					composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZESW));
+				else
+					composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZESE));
+			} else if (isFixed(SWT.BOTTOM)) {
+				if (isFixed(SWT.RIGHT))
+					composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZESE));
+				else
+					composite.setCursor(composite.getDisplay().getSystemCursor(SWT.CURSOR_SIZESW));
+			}
+		} else {
+			composite.setCursor(null);
+		}
+	}
+
+	protected void dragCorner(Composite composite, Point p) {
+		int dx = p.x - curPos.x;
+		int dy = p.y - curPos.y;
+		Rectangle bounds = composite.getBounds();
+
+		if (isFixed(SWT.RIGHT)) {
+			bounds.x += dx;
+			bounds.width -= dx;
+		} else {
+			bounds.width += dx;
+		}
+
+		if (isFixed(SWT.BOTTOM)) {
+			bounds.y += dy;
+			bounds.height -= dy;
+		} else {
+			bounds.height += dy;
+		}
+
+		composite.setBounds(bounds);
+		composite.getDisplay().update();
+
+		curPos = p;
+	}
+
+	protected void dragVertical(Composite composite, Point p) {
+		int dy = p.y - curPos.y;
+		Rectangle bounds = composite.getBounds();
+		if (isFixed(SWT.BOTTOM)) {
+			bounds.y += dy;
+			bounds.height -= dy;
+		} else {
+			bounds.height += dy;
+		}
+
+		composite.setBounds(bounds);
+		composite.getDisplay().update();
+
+		curPos = p;
+	}
+
+	protected void dragHorizontal(Composite composite, Point p) {
+		int dx = p.x - curPos.x;
+		Rectangle bounds = composite.getBounds();
+		if (isFixed(SWT.RIGHT)) {
+			bounds.x += dx;
+			bounds.width -= dx;
+		} else {
+			bounds.width += dx;
+		}
+
+		composite.setBounds(bounds);
+		composite.getDisplay().update();
+
+		curPos = p;
+	}
+
+	private boolean isFixed(int swtSide) {
+		return (fixedCorner & swtSide) != 0;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java
new file mode 100644
index 0000000..29ba353
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/cleanupaddon/CleanupAddon.java
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.workbench.addons.cleanupaddon;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.renderers.swt.SashLayout;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.service.event.Event;
+
+public class CleanupAddon {
+	@Inject
+	IEventBroker eventBroker;
+
+	@Inject
+	EModelService modelService;
+
+	@Inject
+	MApplication app;
+
+	@Inject
+	@Optional
+	private void subscribeTopicChildren(
+			@UIEventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
+		Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (UIEvents.isREMOVE(event)) {
+			final MElementContainer<?> container = (MElementContainer<?>) changedObj;
+			MUIElement containerParent = container.getParent();
+
+			// Determine the elements that should *not* ever be auto-destroyed
+			if (container instanceof MApplication || container instanceof MPerspectiveStack
+					|| container instanceof MMenuElement || container instanceof MTrimBar
+					|| container instanceof MToolBar || container instanceof MArea
+					|| container.getTags().contains(IPresentationEngine.NO_AUTO_COLLAPSE)) {
+				return;
+			}
+
+			if (container instanceof MWindow && containerParent instanceof MApplication) {
+				return;
+			}
+
+			Display display = Display.getCurrent();
+
+			// Stall the removal to handle cases where the container is only transiently empty
+			if (display != null) {
+				Display.getCurrent().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						// Remove it from the display if no visible children
+						int tbrCount = modelService.toBeRenderedCount(container);
+
+						// Cache the value since setting the TBR may change the result
+						boolean lastStack = isLastEditorStack(container);
+						if (tbrCount == 0 && !lastStack) {
+							container.setToBeRendered(false);
+						}
+
+						// Remove it from the model if it has no children at all
+						MElementContainer<?> lclContainer = container;
+						if (lclContainer.getChildren().size() == 0) {
+							MElementContainer<MUIElement> parent = container.getParent();
+							if (parent != null && !lastStack) {
+								container.setToBeRendered(false);
+								parent.getChildren().remove(container);
+							} else if (container instanceof MWindow) {
+								// Must be a Detached Window
+								MUIElement eParent = (MUIElement) ((EObject) container)
+										.eContainer();
+								if (eParent instanceof MPerspective) {
+									((MPerspective) eParent).getWindows().remove(container);
+								} else if (eParent instanceof MWindow) {
+									((MWindow) eParent).getWindows().remove(container);
+								}
+							}
+						} else if (container.getChildren().size() == 1
+								&& container instanceof MPartSashContainer) {
+							// if a sash container has only one element then remove it and move
+							// its child up to where it used to be
+							MUIElement theChild = container.getChildren().get(0);
+							MElementContainer<MUIElement> parentContainer = container.getParent();
+							if (parentContainer != null) {
+								int index = parentContainer.getChildren().indexOf(container);
+
+								// Magic check, are we unwrapping a sash container
+								if (theChild instanceof MPartSashContainer) {
+									if (container.getWidget() instanceof Composite) {
+										Composite theComp = (Composite) container.getWidget();
+										Object tmp = theChild.getWidget();
+										theChild.setWidget(theComp);
+										theComp.setLayout(new SashLayout(theComp, theChild));
+										theComp.setData(AbstractPartRenderer.OWNING_ME, theChild);
+										container.setWidget(tmp);
+									}
+								}
+
+								theChild.setContainerData(container.getContainerData());
+								container.getChildren().remove(theChild);
+								parentContainer.getChildren().add(index, theChild);
+								container.setToBeRendered(false);
+								parentContainer.getChildren().remove(container);
+							}
+						}
+					}
+				});
+			}
+		}
+	}
+
+	/**
+	 * Returns true if and only if the given element should make itself visible
+	 * when its first child becomes visible and make itself invisible whenever
+	 * its last child becomes invisible. Defaults to false for unknown element
+	 * types
+	 */
+	private static boolean shouldReactToChildVisibilityChanges(MUIElement theElement) {
+		// TODO: It may be possible to remove the instanceof checks and just use
+		// IPresentationEngine.HIDDEN_EXPLICITLY. However, that would require
+		// explicitly setting IPresentationEngine.HIDDEN_EXPLICITLY on every
+		// object where we want to keep it hidden even if it has a visible child
+		// (such as the main toolbar).
+		return (theElement instanceof MPartSashContainer || theElement instanceof MPartStack
+				|| theElement instanceof MCompositePart)
+				&& !theElement.getTags().contains(IPresentationEngine.HIDDEN_EXPLICITLY);
+	}
+
+	@Inject
+	@Optional
+	private void subscribeVisibilityChanged(
+			@UIEventTopic(UIEvents.UIElement.TOPIC_VISIBLE) Event event) {
+		MUIElement changedObj = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (changedObj instanceof MTrimBar || ((Object) changedObj.getParent()) instanceof MToolBar)
+			return;
+
+		if (changedObj.getWidget() instanceof Shell) {
+			((Shell) changedObj.getWidget()).setVisible(changedObj.isVisible());
+		} else if (changedObj.getWidget() instanceof Rectangle) {
+			MElementContainer<MUIElement> parent = changedObj.getParent();
+			if (!shouldReactToChildVisibilityChanges(parent)) {
+				return;
+			}
+
+			if (changedObj.isVisible()) {
+				// Make all the parents visible
+				if (!parent.isVisible())
+					parent.setVisible(true);
+			} else {
+				// If there are no more 'visible' children then make the parent go away too
+				boolean makeInvisible = true;
+				for (MUIElement kid : parent.getChildren()) {
+					if (kid.isToBeRendered() && kid.isVisible()) {
+						makeInvisible = false;
+						break;
+					}
+				}
+				if (makeInvisible)
+					parent.setVisible(false);
+			}
+		} else if (changedObj.getWidget() instanceof Control) {
+			Control ctrl = (Control) changedObj.getWidget();
+			MElementContainer<MUIElement> parent = changedObj.getParent();
+			if (parent == null || ((Object) parent) instanceof MToolBar) {
+				return;
+			}
+
+			if (changedObj.isVisible()) {
+				if (parent.getRenderer() != null) {
+					Object myParent = ((AbstractPartRenderer) parent.getRenderer())
+							.getUIContainer(changedObj);
+					if (myParent instanceof Composite) {
+						Composite parentComp = (Composite) myParent;
+						ctrl.setParent(parentComp);
+
+						Control prevControl = null;
+						for (MUIElement childME : parent.getChildren()) {
+							if (childME == changedObj)
+								break;
+							if (childME.getWidget() instanceof Control && childME.isVisible()) {
+								prevControl = (Control) childME.getWidget();
+							}
+						}
+						if (prevControl != null)
+							ctrl.moveBelow(prevControl);
+						else
+							ctrl.moveAbove(null);
+						ctrl.getShell().layout(new Control[] { ctrl }, SWT.DEFER);
+					}
+
+					if (!shouldReactToChildVisibilityChanges(parent)) {
+						return;
+					}
+
+					// Check if the parent is visible
+					if (!parent.isVisible())
+						parent.setVisible(true);
+				}
+			} else {
+				Shell limbo = (Shell) app.getContext().get("limbo");
+
+				// Reparent the control to 'limbo'
+				Composite curParent = ctrl.getParent();
+				ctrl.setParent(limbo);
+				curParent.layout(true);
+				if (curParent.getShell() != curParent)
+					curParent.getShell().layout(new Control[] { curParent }, SWT.DEFER);
+
+				// Always leave Window's in the presentation
+				if ((Object) parent instanceof MWindow)
+					return;
+
+				// If there are no more 'visible' children then make the parent go away too
+				boolean makeParentInvisible = true;
+				for (MUIElement kid : parent.getChildren()) {
+					if (kid.isToBeRendered() && kid.isVisible()) {
+						makeParentInvisible = false;
+						break;
+					}
+				}
+
+				if (!shouldReactToChildVisibilityChanges(parent)) {
+					return;
+				}
+
+				// Special check: If a perspective goes invisibe we need to make its
+				// PerspectiveStack invisible as well...see bug 369528
+				if (makeParentInvisible)
+					parent.setVisible(false);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeRenderingChanged(
+			@UIEventTopic(UIEvents.UIElement.TOPIC_TOBERENDERED) Event event) {
+			MUIElement changedObj = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+			MElementContainer<MUIElement> container = null;
+			if (changedObj.getCurSharedRef() != null)
+				container = changedObj.getCurSharedRef().getParent();
+			else
+				container = changedObj.getParent();
+
+			// this can happen for shared parts that aren't attached to any placeholders
+			if (container == null) {
+				return;
+			}
+
+			// never hide top-level windows
+			MUIElement containerElement = container;
+			if (containerElement instanceof MWindow && containerElement.getParent() != null) {
+				return;
+			}
+
+			// These elements should neither be shown nor hidden based on their containment state
+			if (isLastEditorStack(containerElement) || containerElement instanceof MPerspective
+					|| containerElement instanceof MPerspectiveStack)
+				return;
+
+			Boolean toBeRendered = (Boolean) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+			if (toBeRendered) {
+				// Bring the container back if one of its children goes visible
+				if (!container.isToBeRendered())
+					container.setToBeRendered(true);
+				if (!container.isVisible()
+						&& !container.getTags().contains(IPresentationEngine.MINIMIZED))
+					container.setVisible(true);
+			} else {
+				// Never hide the container marked as no_close
+				if (container.getTags().contains(IPresentationEngine.NO_AUTO_COLLAPSE)) {
+					return;
+				}
+
+				int visCount = modelService.countRenderableChildren(container);
+
+				// Remove stacks with no visible children from the display (but not the
+				// model)
+				final MElementContainer<MUIElement> theContainer = container;
+				if (visCount == 0) {
+					Display.getCurrent().asyncExec(new Runnable() {
+						@Override
+						public void run() {
+							int visCount = modelService.countRenderableChildren(theContainer);
+							if (!isLastEditorStack(theContainer) && visCount == 0)
+								theContainer.setToBeRendered(false);
+						}
+					});
+				} else {
+					// if there are rendered elements but none are 'visible' we should
+					// make the container invisible as well
+					boolean makeInvisible = true;
+
+					// OK, we have rendered children, are they 'visible' ?
+					for (MUIElement kid : container.getChildren()) {
+						if (!kid.isToBeRendered())
+							continue;
+						if (kid.isVisible()) {
+							makeInvisible = false;
+							break;
+						}
+					}
+
+					if (makeInvisible) {
+						container.setVisible(false);
+					}
+				}
+			}
+	}
+
+	boolean isLastEditorStack(MUIElement element) {
+		return modelService.isLastEditorStack(element);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/DnDAddon.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/DnDAddon.java
new file mode 100644
index 0000000..3ba4f02
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/DnDAddon.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.addons.dndaddon;
+
+/**
+ *
+ */
+public class DnDAddon {
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/README.txt b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/README.txt
new file mode 100644
index 0000000..9e0cdba
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/dndaddon/README.txt
@@ -0,0 +1 @@
+DND is currently not supported
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/Messages.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/Messages.java
new file mode 100644
index 0000000..0384ee5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/Messages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.workbench.addons.minmax;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ */
+public class Messages extends NLS {
+
+	public static String TrimStack_EmptyStackTooltip;
+	public static String TrimStack_SharedAreaTooltip;
+	public static String TrimStack_CloseText;
+	public static String TrimStack_DefaultOrientationItem;
+	public static String TrimStack_RestoreText;
+	public static String TrimStack_Horizontal;
+	public static String TrimStack_OrientationMenu;
+	public static String TrimStack_Vertical;
+	public static String TrimStack_Show_In_Original_Location;
+
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.workbench.addons.minmax.messages";//$NON-NLS-1$
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/MinMaxAddon.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/MinMaxAddon.java
new file mode 100644
index 0000000..a5df2ef
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/MinMaxAddon.java
@@ -0,0 +1,1026 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014, 2015 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 331690
+ *     Dirk Fauth (dirk.fauth@googlemail.com) - Bug 459285
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.addons.minmax;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.AnimationEngine;
+import org.eclipse.e4.ui.internal.workbench.swt.FaderAnimationFeedback;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabFolder2Adapter;
+import org.eclipse.swt.custom.CTabFolderEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.service.event.Event;
+
+/**
+ * Workbench addon that provides methods to minimize, maximize and restore parts in the window
+ */
+public class MinMaxAddon {
+
+	/**
+	 * The identifier for the shared area in the Eclipse Platform. This value should be identical to
+	 * the value defined in org.eclipse.ui.IPageLayout.ID_EDITOR_AREA.
+	 */
+	private static final String ID_EDITOR_AREA = "org.eclipse.ui.editorss"; //$NON-NLS-1$
+
+	private static final String GLOBAL_CACHE_ID = "Global"; //$NON-NLS-1$
+
+	static String ID_SUFFIX = "(minimized)"; //$NON-NLS-1$
+
+	// tags representing the min/max state (h
+	private static String MINIMIZED = IPresentationEngine.MINIMIZED;
+	private static String MAXIMIZED = IPresentationEngine.MAXIMIZED;
+	private static String MINIMIZED_BY_ZOOM = IPresentationEngine.MINIMIZED_BY_ZOOM;
+
+	@Inject
+	IEventBroker eventBroker;
+
+	@Inject
+	EModelService modelService;
+
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	private EPartService partService;
+
+	// Allow 'local' changes to the tags
+	private boolean ignoreTagChanges = false;
+
+	@Inject
+	MAddon minMaxAddon;
+
+	private CTabFolder2Adapter CTFButtonListener = new CTabFolder2Adapter() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		private MUIElement getElementToChange(CTabFolderEvent event) {
+			CTabFolder ctf = (CTabFolder) event.widget;
+			MUIElement element = (MUIElement) ctf.getData(AbstractPartRenderer.OWNING_ME);
+			if (element instanceof MArea)
+				return element.getCurSharedRef();
+
+			MUIElement parentElement = element.getParent();
+			while (parentElement != null && !(parentElement instanceof MArea))
+				parentElement = parentElement.getParent();
+
+			return parentElement != null ? parentElement.getCurSharedRef() : element;
+		}
+
+		@Override
+		public void maximize(CTabFolderEvent event) {
+			setState(getElementToChange(event), MAXIMIZED);
+		}
+
+		@Override
+		public void minimize(CTabFolderEvent event) {
+			setState(getElementToChange(event), MINIMIZED);
+		}
+
+		@Override
+		public void restore(CTabFolderEvent event) {
+			setState(getElementToChange(event), null);
+		}
+	};
+
+	private MouseListener CTFDblClickListener = new MouseListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void mouseUp(MouseEvent e) {
+		}
+
+		@Override
+		public void mouseDown(MouseEvent e) {
+			// HACK! If this is an empty stack treat it as though it was the editor area
+			// and tear down any open trim stacks (see bug 384814)
+			CTabFolder ctf = (CTabFolder) e.widget;
+			MUIElement element = (MUIElement) ctf.getData(AbstractPartRenderer.OWNING_ME);
+			if (element instanceof MPartStack && ctf.getItemCount() == 0) {
+				MWindow window = modelService.getTopLevelWindowFor(element);
+				if (window != null) {
+					List<MToolControl> tcList = modelService.findElements(window, null,
+							MToolControl.class, null);
+					for (MToolControl tc : tcList) {
+						if (tc.getObject() instanceof TrimStack) {
+							TrimStack ts = (TrimStack) tc.getObject();
+							ts.showStack(false);
+						}
+					}
+				}
+			}
+		}
+
+		private MUIElement getElementToChange(MouseEvent event) {
+			CTabFolder ctf = (CTabFolder) event.widget;
+			MUIElement element = (MUIElement) ctf.getData(AbstractPartRenderer.OWNING_ME);
+			if (element instanceof MArea) {
+				// set the state on the placeholder
+				return element.getCurSharedRef();
+			}
+
+			MUIElement parentElement = element.getParent();
+			while (parentElement != null && !(parentElement instanceof MArea))
+				parentElement = parentElement.getParent();
+
+			return parentElement != null ? parentElement.getCurSharedRef() : element;
+		}
+
+		@Override
+		public void mouseDoubleClick(MouseEvent e) {
+			// only maximize if the primary mouse button was used
+			if (e.button == 1) {
+				CTabFolder ctf = (CTabFolder) e.widget;
+				if (!ctf.getMaximizeVisible())
+					return;
+
+				// Only fire if we're in the 'tab' area
+				if (e.y > ctf.getTabHeight())
+					return;
+
+				MUIElement elementToChange = getElementToChange(e);
+				if (!elementToChange.getTags().contains(MAXIMIZED)) {
+					setState(elementToChange, MAXIMIZED);
+				} else {
+					setState(elementToChange, null);
+				}
+			}
+		}
+	};
+
+	private void setState(MUIElement element, String state) {
+		if (MINIMIZED.equals(state)) {
+			element.getTags().remove(MAXIMIZED);
+			element.getTags().add(MINIMIZED);
+		} else if (MAXIMIZED.equals(state)) {
+			element.getTags().remove(MINIMIZED);
+			element.getTags().add(MAXIMIZED);
+		} else {
+			element.getTags().remove(MINIMIZED);
+			element.getTags().remove(MAXIMIZED);
+		}
+
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicWidget(@UIEventTopic(UIEvents.UIElement.TOPIC_WIDGET) Event event) {
+		final MUIElement changedElement = (MUIElement) event.getProperty(EventTags.ELEMENT);
+		if (!(changedElement instanceof MPartStack) && !(changedElement instanceof MArea))
+			return;
+
+		final CTabFolder ctf = getCTFFor(changedElement);
+		if (ctf == null)
+			return;
+
+		MUIElement stateElement = changedElement;
+		if (changedElement instanceof MPartStack) {
+			MPartStack stack = (MPartStack) changedElement;
+			MArea area = getAreaFor(stack);
+			if (area != null && !(area.getWidget() instanceof CTabFolder))
+				stateElement = area.getCurSharedRef();
+		} else if (changedElement instanceof MArea)
+			stateElement = changedElement.getCurSharedRef();
+
+		adjustCTFButtons(stateElement);
+
+		ctf.removeCTabFolder2Listener(CTFButtonListener); // Prevent multiple instances
+		ctf.addCTabFolder2Listener(CTFButtonListener);
+
+		ctf.removeMouseListener(CTFDblClickListener); // Prevent multiple instances
+		ctf.addMouseListener(CTFDblClickListener);
+	}
+
+	/**
+	 * Handles removals from the perspective
+	 *
+	 * @param event
+	 */
+
+	@Inject
+	@Optional
+	private void subscribeTopicChildren(
+			@UIEventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
+		final MUIElement changedElement = (MUIElement) event.getProperty(EventTags.ELEMENT);
+		MWindow window = modelService.getTopLevelWindowFor(changedElement);
+
+		// this method is intended to update the minimized stacks in a trim
+		// if the removed element is no perspective and the top level window
+		// is not a trimmed window, we don't need to do anything here
+		if (!(changedElement instanceof MPerspectiveStack) || window == null || !(window instanceof MTrimmedWindow)) {
+			return;
+		}
+
+		if (UIEvents.isREMOVE(event)) {
+			for (Object removedElement : UIEvents.asIterable(event, UIEvents.EventTags.OLD_VALUE)) {
+				MUIElement removed = (MUIElement) removedElement;
+				String perspectiveId = removed.getElementId();
+
+				MTrimBar bar = modelService.getTrim((MTrimmedWindow) window, SideValue.TOP);
+
+				// gather up any minimized stacks for this perspective...
+				List<MToolControl> toRemove = new ArrayList<MToolControl>();
+				for (MUIElement child : bar.getChildren()) {
+					String trimElementId = child.getElementId();
+					if (child instanceof MToolControl && trimElementId.contains(perspectiveId)) {
+						toRemove.add((MToolControl) child);
+					}
+				}
+
+				// ...and remove them
+				for (MToolControl minStack : toRemove) {
+					minStack.setToBeRendered(false);
+					bar.getChildren().remove(minStack);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Handles changes of the perspective
+	 *
+	 * @param event
+	 */
+
+	@Inject
+	@Optional
+	private void subscribeTopicSelectedElement(
+			@UIEventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
+		final MUIElement changedElement = (MUIElement) event.getProperty(EventTags.ELEMENT);
+		if (!(changedElement instanceof MPerspectiveStack))
+			return;
+
+		MPerspectiveStack ps = (MPerspectiveStack) changedElement;
+		MWindow window = modelService.getTopLevelWindowFor(ps);
+		List<MToolControl> tcList = modelService.findElements(window, null, MToolControl.class,
+				null);
+
+		final MPerspective curPersp = ps.getSelectedElement();
+		if (curPersp != null) {
+			List<String> tags = new ArrayList<String>();
+			tags.add(IPresentationEngine.MINIMIZED);
+
+			List<MUIElement> minimizedElements = modelService.findElements(curPersp, null,
+					MUIElement.class, tags);
+			// Show any minimized stack from the current perspective
+			String perspId = '(' + curPersp.getElementId() + ')';
+			for (MUIElement ele : minimizedElements) {
+				String fullId = ele.getElementId() + perspId;
+
+				for (MToolControl tc : tcList) {
+					if (fullId.equals(tc.getElementId())) {
+						tc.setToBeRendered(true);
+					}
+				}
+			}
+
+			// Find the editor 'area'
+			MPlaceholder eaPlaceholder = (MPlaceholder) modelService.find(ID_EDITOR_AREA, curPersp);
+			adjustCTFButtons(eaPlaceholder);
+		}
+
+		// Hide any minimized stacks from the old perspective
+		if (event.getProperty(EventTags.OLD_VALUE) instanceof MPerspective) {
+			MPerspective oldPersp = (MPerspective) event.getProperty(EventTags.OLD_VALUE);
+			String perspId = '(' + oldPersp.getElementId() + ')';
+			for (MToolControl tc : tcList) {
+				if (tc.getObject() instanceof TrimStack && tc.getElementId().contains(perspId)) {
+					TrimStack ts = (TrimStack) tc.getObject();
+					ts.showStack(false);
+					tc.setToBeRendered(false);
+				}
+			}
+		}
+
+		final Shell winShell = (Shell) window.getWidget();
+		winShell.getDisplay().asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				if (!winShell.isDisposed()) {
+					winShell.layout(true, true);
+				}
+			}
+		});
+	}
+
+	/**
+	 * Handles changes in tags
+	 *
+	 * @param event
+	 */
+
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
+		if (ignoreTagChanges)
+			return;
+
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MUIElement))
+			return;
+
+		final MUIElement changedElement = (MUIElement) changedObj;
+
+		if (UIEvents.isADD(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, MINIMIZED)) {
+				minimize(changedElement);
+			} else if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, MAXIMIZED)) {
+				maximize(changedElement);
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, MINIMIZED)) {
+				restore(changedElement);
+			} else if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, MAXIMIZED)) {
+				unzoom(changedElement);
+			}
+		}
+	}
+
+	/**
+	 * Handles changes in the id of the element If a perspective ID changes fix
+	 * any TrimStacks that reference the old id to point at the new id.
+	 *
+	 * This keeps trim stacks attached to the correct perspective when a
+	 * perspective is saved with a new name.
+	 *
+	 * @param event
+	 */
+
+	@Inject
+	@Optional
+	private void subscribeTopicElementId(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_ELEMENTID) Event event) {
+		Object changedObject = event.getProperty(EventTags.ELEMENT);
+
+		// Only care about MPerspective id changes
+		if (!(changedObject instanceof MPerspective))
+			return;
+
+		MPerspective perspective = (MPerspective) changedObject;
+
+		String newID = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+		String oldID = (String) event.getProperty(UIEvents.EventTags.OLD_VALUE);
+
+		// pattern is trimStackID(perspectiveID)
+		newID = '(' + newID + ')';
+		oldID = '(' + oldID + ')';
+
+		// Search the trim for the window containing the perspective
+		MWindow perspWin = modelService.getTopLevelWindowFor(perspective);
+		if (perspWin == null)
+			return;
+
+		List<MToolControl> trimStacks = modelService.findElements(perspWin, null,
+				MToolControl.class, null);
+		for (MToolControl trimStack : trimStacks) {
+			// Only care about MToolControls that are TrimStacks
+			if (TrimStack.CONTRIBUTION_URI.equals(trimStack.getContributionURI()))
+				trimStack.setElementId(trimStack.getElementId().replace(oldID, newID));
+		}
+	}
+
+	/**
+	 * Handles the event that the perspective is saved
+	 *
+	 * @param event
+	 */
+
+	@Inject
+	@Optional
+	private void subscribeTopicPerspSaved(
+			@UIEventTopic(UIEvents.UILifeCycle.PERSPECTIVE_SAVED) Event event) {
+		final MPerspective savedPersp = (MPerspective) event.getProperty(EventTags.ELEMENT);
+		String cache = getTrimCache(savedPersp);
+		minMaxAddon.getPersistedState().put(savedPersp.getElementId(), cache);
+	}
+
+	private String getTrimCache(MPerspective savedPersp) {
+		MWindow topWin = modelService.getTopLevelWindowFor(savedPersp);
+		String perspIdStr = '(' + savedPersp.getElementId() + ')';
+
+		String cache = getWinCache(topWin, perspIdStr);
+		for (MWindow dw : savedPersp.getWindows()) {
+			cache += getWinCache(dw, perspIdStr);
+		}
+
+		return cache;
+	}
+
+	private String getWinCache(MWindow win, String perspIdStr) {
+		String winStr = ""; //$NON-NLS-1$
+
+		List<MPartStack> stackList = modelService.findElements(win, null, MPartStack.class, null);
+		for (MPartStack stack : stackList) {
+			winStr += getStackTrimLoc(stack, perspIdStr);
+		}
+		return winStr;
+	}
+
+	private String getStackTrimLoc(MPartStack stack, String perspIdStr) {
+		MWindow stackWin = modelService.getTopLevelWindowFor(stack);// getContainingWindow(stack);
+		MUIElement tcElement = modelService.find(stack.getElementId() + perspIdStr, stackWin);
+		if (tcElement == null)
+			return ""; //$NON-NLS-1$
+
+		MTrimBar bar = (MTrimBar) ((MUIElement) tcElement.getParent());
+		int sideVal = bar.getSide().getValue();
+		int index = bar.getChildren().indexOf(tcElement);
+		return stack.getElementId() + ' ' + sideVal + ' ' + index + "#"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Handles the event that the perspective is reset
+	 *
+	 * @param event
+	 */
+	@Inject
+	@Optional
+	private void subscribeTopicPerspReset(@UIEventTopic(UIEvents.UILifeCycle.PERSPECTIVE_RESET) Event event) {
+		final MPerspective resetPersp = (MPerspective) event.getProperty(EventTags.ELEMENT);
+
+		// Find any minimized stacks and show their trim
+		List<MUIElement> minimizedElements = modelService.findElements(resetPersp, null, MUIElement.class,
+				Arrays.asList(IPresentationEngine.MINIMIZED));
+		for (MUIElement element : minimizedElements) {
+			createTrim(element);
+		}
+	}
+
+	/**
+	 * Handles the event that the perspective is opened
+	 *
+	 * @param event
+	 */
+	@Inject
+	@Optional
+	private void subscribeTopicPerspOpened(
+			@UIEventTopic(UIEvents.UILifeCycle.PERSPECTIVE_OPENED) Event event) {
+		final MPerspective openedPersp = (MPerspective) event.getProperty(EventTags.ELEMENT);
+
+		// Find any minimized stacks and show their trim
+		List<MUIElement> minimizedElements = modelService.findElements(openedPersp, null,
+				MUIElement.class, Arrays.asList(IPresentationEngine.MINIMIZED));
+		for (MUIElement element : minimizedElements) {
+			createTrim(element);
+		}
+	}
+
+	private MArea getAreaFor(MPartStack stack) {
+		MUIElement parent = stack.getParent();
+		while (parent != null) {
+			if (parent instanceof MArea)
+				return (MArea) parent;
+			parent = parent.getParent();
+		}
+		return null;
+	}
+
+	private void setCTFButtons(CTabFolder ctf, MUIElement stateElement, boolean hideButtons) {
+		if (hideButtons) {
+			ctf.setMinimizeVisible(false);
+			ctf.setMaximizeVisible(false);
+		} else {
+			if (stateElement.getTags().contains(MINIMIZED)) {
+				ctf.setMinimizeVisible(false);
+				ctf.setMaximizeVisible(true);
+				ctf.setMaximized(true);
+			} else if (stateElement.getTags().contains(MAXIMIZED)) {
+				ctf.setMinimizeVisible(true);
+				ctf.setMaximizeVisible(true);
+				ctf.setMaximized(true);
+			} else {
+				ctf.setMinimizeVisible(true);
+				ctf.setMaximizeVisible(true);
+				ctf.setMinimized(false);
+				ctf.setMaximized(false);
+				ctf.layout();
+			}
+		}
+	}
+
+	/**
+	 * Set the state of the min / max buttons on the CTF based on the model
+	 * element's state. The input is expected to be the element that contains
+	 * the min/max state info which should either be an MPartStack or an
+	 * MPlaceholder for the shared area.
+	 *
+	 * @param element
+	 *            The element to test
+	 */
+	private void adjustCTFButtons(MUIElement element) {
+		if (!(element instanceof MPartStack) && !(element instanceof MPlaceholder))
+			return;
+
+		CTabFolder ctf = getCTFFor(element);
+		if (ctf == null)
+			return;
+
+		if (element instanceof MPlaceholder) {
+			setCTFButtons(ctf, element, false);
+		} else {
+			MArea area = getAreaFor((MPartStack) element);
+			if (area == null) {
+				setCTFButtons(ctf, element, false);
+			}
+		}
+	}
+
+	private CTabFolder getCTFFor(MUIElement element) {
+		if (element instanceof MArea) {
+			if (element.getWidget() instanceof CTabFolder)
+				return (CTabFolder) element.getWidget();
+			List<MPartStack> stacks = modelService.findElements(element, null, MPartStack.class,
+					null);
+			for (MPartStack stack : stacks) {
+				if (stack.getWidget() instanceof CTabFolder)
+					return (CTabFolder) stack.getWidget();
+			}
+		} else if (element.getWidget() instanceof CTabFolder)
+			return (CTabFolder) element.getWidget();
+		else if (element instanceof MPlaceholder) {
+			MPlaceholder ph = (MPlaceholder) element;
+			if (ph.getRef() instanceof MArea) {
+				return getCTFFor(ph.getRef());
+			}
+		}
+		return null;
+	}
+
+	boolean isEmptyPerspectiveStack(MUIElement element) {
+		if (!(element instanceof MPerspectiveStack))
+			return false;
+		MPerspectiveStack ps = (MPerspectiveStack) element;
+		return ps.getChildren().size() == 0;
+	}
+
+	void minimize(MUIElement element) {
+		// Can't minimize a non-rendered element
+		if (!element.isToBeRendered())
+			return;
+
+		if (isEmptyPerspectiveStack(element)) {
+			element.setVisible(false);
+			return;
+		}
+
+		createTrim(element);
+		element.setVisible(false);
+		adjustCTFButtons(element);
+		// Activate a part other than the trimStack so that if the tool item is pressed
+		// immediately it will still open the stack.
+		partService.requestActivation();
+	}
+
+	void restore(MUIElement element) {
+		MWindow window = modelService.getTopLevelWindowFor(element);
+		String trimId = element.getElementId() + getMinimizedElementSuffix(element);
+		MToolControl trimStack = (MToolControl) modelService.find(trimId, window);
+		if (trimStack == null || trimStack.getObject() == null) {
+			if (element instanceof MPerspectiveStack) {
+				element.setVisible(true);
+			}
+			return;
+		}
+
+		TrimStack ts = (TrimStack) trimStack.getObject();
+		ts.restoreStack();
+
+		adjustCTFButtons(element);
+
+		List<String> maximizeTag = new ArrayList<String>();
+		maximizeTag.add(IPresentationEngine.MAXIMIZED);
+		List<MUIElement> curMax = modelService.findElements(window, null, MUIElement.class,
+				maximizeTag, EModelService.PRESENTATION);
+		if (curMax.size() > 0) {
+			MUIElement maxElement = curMax.get(0);
+			List<MUIElement> elementsLeftToRestore = getElementsToRestore(maxElement);
+
+			// Are any stacks still minimized ?
+			boolean unMax = true;
+			for (MUIElement toRestore : elementsLeftToRestore) {
+				if (!toRestore.isVisible())
+					unMax = false;
+			}
+			if (unMax) {
+				maxElement.getTags().remove(IPresentationEngine.MAXIMIZED);
+			}
+		}
+	}
+
+	void maximize(final MUIElement element) {
+		if (!element.isToBeRendered())
+			return;
+
+		List<MUIElement> elementsToMinimize = getElementsToMinimize(element);
+		Shell hostShell = (Shell) modelService.getTopLevelWindowFor(element).getWidget();
+		MWindow win = getWindowFor(element);
+
+		FaderAnimationFeedback fader = new FaderAnimationFeedback(hostShell);
+		AnimationEngine engine = new AnimationEngine(win.getContext(), fader, 300);
+		engine.schedule();
+
+		// Restore any currently maximized element
+		restoreMaximizedElement(element, win);
+
+		for (MUIElement toMinimize : elementsToMinimize) {
+			toMinimize.getTags().add(MINIMIZED);
+			toMinimize.getTags().add(MINIMIZED_BY_ZOOM);
+		}
+
+		adjustCTFButtons(element);
+	}
+
+	/**
+	 * @param element
+	 * @return The list of elements that need to be minimized during a maximize
+	 */
+	private List<MUIElement> getElementsToMinimize(MUIElement element) {
+		MWindow win = getWindowFor(element);
+		MPerspective persp = modelService.getActivePerspective(win);
+
+		List<MUIElement> elementsToMinimize = new ArrayList<MUIElement>();
+		int loc = modelService.getElementLocation(element);
+		if ((loc & EModelService.OUTSIDE_PERSPECTIVE) != 0) {
+			// Minimize all other global stacks
+			List<MPartStack> globalStacks = modelService.findElements(win, null, MPartStack.class,
+					null, EModelService.OUTSIDE_PERSPECTIVE);
+			for (MPartStack gStack : globalStacks) {
+				if (gStack == element || !gStack.isToBeRendered())
+					continue;
+
+				if (gStack.getWidget() != null && !gStack.getTags().contains(MINIMIZED)) {
+					elementsToMinimize.add(gStack);
+				}
+			}
+
+			// Minimize the Perspective Stack
+			MUIElement perspStack = null;
+			if (persp == null) {
+				// special case for windows with no perspectives (eg bug 372614:
+				// intro part with no perspectives). We know we're outside
+				// of the perspective stack, so find it top-down
+				List<MPerspectiveStack> pStacks = modelService.findElements(win, null,
+						MPerspectiveStack.class, null);
+				perspStack = (pStacks.size() > 0) ? pStacks.get(0) : null;
+			} else {
+				perspStack = persp.getParent();
+			}
+			if (perspStack != null) {
+				if (perspStack.getElementId() == null || perspStack.getElementId().length() == 0)
+					perspStack.setElementId("PerspectiveStack"); //$NON-NLS-1$
+
+				elementsToMinimize.add(perspStack);
+			}
+		} else {
+			List<MPartStack> stacks = modelService.findElements(persp == null ? win : persp, null,
+					MPartStack.class, null, EModelService.PRESENTATION);
+			for (MPartStack theStack : stacks) {
+				if (theStack == element || !theStack.isToBeRendered())
+					continue;
+
+				// Exclude stacks in DW's
+				if (getWindowFor(theStack) != win)
+					continue;
+
+				loc = modelService.getElementLocation(theStack);
+				if (loc != EModelService.IN_SHARED_AREA && theStack.getWidget() != null
+						&& theStack.isVisible() && !theStack.getTags().contains(MINIMIZED)) {
+					elementsToMinimize.add(theStack);
+				}
+			}
+
+			// Find any 'standalone' views *not* in a stack
+			List<String> standaloneTag = new ArrayList<String>();
+			standaloneTag.add(IPresentationEngine.STANDALONE);
+			List<MPlaceholder> standaloneViews = modelService.findElements(persp == null ? win
+					: persp, null, MPlaceholder.class, standaloneTag, EModelService.PRESENTATION);
+			for (MPlaceholder part : standaloneViews) {
+				if (!part.isToBeRendered())
+					continue;
+				elementsToMinimize.add(part);
+			}
+
+			// Find the editor 'area'
+			if (persp != null) {
+				MPlaceholder eaPlaceholder = (MPlaceholder) modelService
+						.find(ID_EDITOR_AREA, persp);
+				if (element != eaPlaceholder && eaPlaceholder != null
+						&& eaPlaceholder.getWidget() != null && eaPlaceholder.isVisible()) {
+					elementsToMinimize.add(eaPlaceholder);
+				}
+			}
+		}
+
+		return elementsToMinimize;
+	}
+
+	/**
+	 * Restore any currently maximized element (except the one we're in the
+	 * process of maximizing
+	 *
+	 * @param element
+	 * @param win
+	 */
+	private void restoreMaximizedElement(final MUIElement element, MWindow win) {
+		MPerspective elePersp = modelService.getPerspectiveFor(element);
+		List<String> maxTag = new ArrayList<String>();
+		maxTag.add(MAXIMIZED);
+		List<MUIElement> curMax = modelService.findElements(win, null, MUIElement.class, maxTag);
+		if (curMax.size() > 0) {
+			for (MUIElement maxElement : curMax) {
+				// Only unmax elements in this window
+				if (getWindowFor(maxElement) != win)
+					continue;
+
+				MPerspective maxPersp = modelService.getPerspectiveFor(maxElement);
+				if (maxPersp != elePersp)
+					continue;
+				if (maxElement == element)
+					continue;
+				ignoreTagChanges = true;
+				try {
+					maxElement.getTags().remove(MAXIMIZED);
+				} finally {
+					ignoreTagChanges = false;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Return the MWindow containing this element (if any). This may either be a
+	 * 'top level' window -or- a detached window. This allows the min.max code
+	 * to only affect elements in the window containing the element.
+	 *
+	 * @param element
+	 *            The element to check
+	 *
+	 * @return the window containing the element.
+	 */
+	private MWindow getWindowFor(MUIElement element) {
+		MUIElement parent = element.getParent();
+
+		// We rely here on the fact that a DW's 'getParent' will return
+		// null since it's not in the 'children' hierarchy
+		while (parent != null && !(parent instanceof MWindow))
+			parent = parent.getParent();
+
+		// A detached window will end up with getParent() == null
+		return (MWindow) parent;
+	}
+
+	void unzoom(final MUIElement element) {
+		MWindow win = getWindowFor(element);
+
+		Shell hostShell = (Shell) win.getWidget();
+		FaderAnimationFeedback fader = new FaderAnimationFeedback(hostShell);
+		AnimationEngine engine = new AnimationEngine(win.getContext(), fader, 300);
+		engine.schedule();
+
+		List<MUIElement> elementsToRestore = getElementsToRestore(element);
+		for (MUIElement toRestore : elementsToRestore) {
+			toRestore.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM);
+			toRestore.getTags().remove(IPresentationEngine.MINIMIZED);
+		}
+
+		adjustCTFButtons(element);
+
+		// There are more views available to be active...
+		partService.requestActivation();
+	}
+
+	/**
+	 * @param element
+	 * @return The list of elements that need to be restored by an unzoom
+	 */
+	private List<MUIElement> getElementsToRestore(MUIElement element) {
+		MWindow win = getWindowFor(element);
+		MPerspective persp = modelService.getActivePerspective(win);
+
+		List<MUIElement> elementsToRestore = new ArrayList<MUIElement>();
+
+		List<String> minTag = new ArrayList<String>();
+		minTag.add(IPresentationEngine.MINIMIZED_BY_ZOOM);
+
+		// Restore any minimized stacks
+		boolean outsidePerspectives = (modelService.getElementLocation(element) & EModelService.OUTSIDE_PERSPECTIVE) != 0;
+		List<MPartStack> stacks = modelService.findElements(win, null, MPartStack.class, minTag,
+				EModelService.PRESENTATION);
+		for (MPartStack theStack : stacks) {
+			if (theStack.getWidget() != null) {
+				// Make sure we don't restore perspective-based stacks if we're
+				// unzoooming an element outside the perspectives
+				if (outsidePerspectives) {
+					int stackLoc = modelService.getElementLocation(theStack);
+					if ((stackLoc & EModelService.OUTSIDE_PERSPECTIVE) == 0)
+						continue;
+				}
+
+				// Make sure we're only working on *our* window
+				if (getWindowFor(theStack) == win) {
+					elementsToRestore.add(theStack);
+				}
+			}
+		}
+
+		// Restore any minimized standalone views
+		List<MPlaceholder> views = modelService.findElements(win, null, MPlaceholder.class, minTag,
+				EModelService.PRESENTATION);
+		for (MPlaceholder ph : views) {
+			if (ph.getWidget() != null && getWindowFor(ph) == win) {
+				elementsToRestore.add(ph);
+			}
+		}
+
+		// Find the editor 'area'
+		MPlaceholder eaPlaceholder = (MPlaceholder) modelService.find(ID_EDITOR_AREA,
+				persp == null ? win : persp);
+		if (element != eaPlaceholder && eaPlaceholder != null
+				&& eaPlaceholder.getTags().contains(MINIMIZED_BY_ZOOM)) {
+			elementsToRestore.add(eaPlaceholder);
+		}
+
+		// Find the Perspective Stack
+		int loc = modelService.getElementLocation(element);
+		if ((loc & EModelService.OUTSIDE_PERSPECTIVE) != 0) {
+			List<MPerspectiveStack> psList = modelService.findElements(win, null,
+					MPerspectiveStack.class, null);
+			if (psList.size() == 1) {
+				MPerspectiveStack perspStack = psList.get(0);
+				if (element != perspStack && perspStack != null
+						&& perspStack.getTags().contains(MINIMIZED_BY_ZOOM)) {
+					elementsToRestore.add(perspStack);
+				}
+			}
+		}
+
+		return elementsToRestore;
+	}
+
+	private void createTrim(MUIElement element) {
+		MWindow win = getWindowFor(element);
+		if (!(win instanceof MTrimmedWindow)) {
+			return;
+		}
+
+		MTrimmedWindow window = (MTrimmedWindow) win;
+		Shell winShell = (Shell) window.getWidget();
+
+		// Is there already a TrimControl there ?
+		String trimId = element.getElementId() + getMinimizedElementSuffix(element);
+		MToolControl trimStack = (MToolControl) modelService.find(trimId, window);
+
+		if (trimStack == null) {
+			trimStack = MenuFactoryImpl.eINSTANCE.createToolControl();
+			trimStack.setElementId(trimId);
+			trimStack.setContributionURI(TrimStack.CONTRIBUTION_URI);
+			trimStack.getTags().add("TrimStack"); //$NON-NLS-1$
+
+			// Check if we have a cached location
+			MTrimBar bar = getBarForElement(element, window);
+			int index = getCachedIndex(element);
+			if (index == -1 || index >= bar.getChildren().size())
+				bar.getChildren().add(trimStack);
+			else
+				bar.getChildren().add(index, trimStack);
+
+			bar.setVisible(true);
+
+			// get the parent trim bar, see bug 320756
+			if (bar.getWidget() == null) {
+				// ask it to be rendered
+				bar.setToBeRendered(true);
+
+				// create the widget
+				context.get(IPresentationEngine.class)
+						.createGui(bar, winShell, window.getContext());
+			}
+		} else {
+			// get the parent trim bar, see bug 320756
+			MUIElement parent = trimStack.getParent();
+			parent.setVisible(true);
+			if (parent.getWidget() == null) {
+				// ask it to be rendered
+				parent.setToBeRendered(true);
+				// create the widget
+				context.get(IPresentationEngine.class).createGui(parent, winShell,
+						window.getContext());
+			}
+			trimStack.setToBeRendered(true);
+		}
+	}
+
+	private String getCachedInfo(MUIElement element) {
+		String cacheId = GLOBAL_CACHE_ID;
+		MPerspective persp = modelService.getPerspectiveFor(element);
+		if (persp != null)
+			cacheId = persp.getElementId();
+		String cacheInfo = minMaxAddon.getPersistedState().get(cacheId);
+
+		return cacheInfo;
+	}
+
+	private int getCachedIndex(MUIElement element) {
+		String cache = getCachedInfo(element);
+		if (cache == null)
+			return -1;
+
+		String[] stacks = cache.split("#"); //$NON-NLS-1$
+		for (String stackInfo : stacks) {
+			String[] vals = stackInfo.split(" "); //$NON-NLS-1$
+			if (vals[0].equals(element.getElementId())) {
+				return Integer.parseInt(vals[2]);
+			}
+		}
+		return -1;
+	}
+
+	private SideValue getCachedBar(MUIElement element) {
+		String cache = getCachedInfo(element);
+		if (cache == null)
+			return null;
+
+		String[] stacks = cache.split("#"); //$NON-NLS-1$
+		for (String stackInfo : stacks) {
+			String[] vals = stackInfo.split(" "); //$NON-NLS-1$
+			if (vals[0].equals(element.getElementId())) {
+				int sideVal = Integer.parseInt(vals[1]);
+				return SideValue.get(sideVal);
+			}
+		}
+		return null;
+	}
+
+	private MTrimBar getBarForElement(MUIElement element, MTrimmedWindow window) {
+		SideValue side = getCachedBar(element);
+		if (side == null) {
+			Shell winShell = (Shell) window.getWidget();
+			Rectangle winBounds = winShell.getBounds();
+			int winCenterX = winBounds.width / 2;
+			Control stackCtrl = (Control) element.getWidget();
+			Rectangle stackBounds = stackCtrl.getBounds();
+			stackBounds = winShell.getDisplay().map(stackCtrl, winShell, stackBounds);
+			int stackCenterX = stackBounds.x + (stackBounds.width / 2);
+			side = stackCenterX < winCenterX ? SideValue.LEFT : SideValue.RIGHT;
+		}
+		MTrimBar bar = modelService.getTrim(window, side);
+
+		return bar;
+	}
+
+	private String getMinimizedElementSuffix(MUIElement element) {
+		String id = ID_SUFFIX;
+		MPerspective persp = modelService.getPerspectiveFor(element);
+		if (persp != null) {
+			id = '(' + persp.getElementId() + ')';
+		}
+		return id;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java
new file mode 100644
index 0000000..5b53b23
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/TrimStack.java
@@ -0,0 +1,1305 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014, 2015 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@vogella.com - Bug 454712
+ *     dirk.fauth@googlemail.com - Bug 446095
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench.addons.minmax;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSRenderingUtils;
+import org.eclipse.e4.ui.internal.workbench.swt.ShellActivationListener;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MGenericStack;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.renderers.swt.TrimmedPartLayout;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.osgi.service.event.EventHandler;
+
+
+/**
+ * Class for representing window trim containing minimized views and shared areas
+ */
+public class TrimStack {
+
+	/**
+	 * Contribution URI for this class
+	 */
+	public static String CONTRIBUTION_URI = "bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.minmax.TrimStack"; //$NON-NLS-1$
+
+	private static final String LAYOUT_ICON_URI = "platform:/plugin/org.eclipse.e4.ui.workbench.addons.swt/icons/full/obj16/layout_co.gif"; //$NON-NLS-1$
+
+	private static final String RESTORE_ICON_URI = "platform:/plugin/org.eclipse.e4.ui.workbench.addons.swt/icons/full/etool16/fastview_restore.gif"; //$NON-NLS-1$
+
+	public static final String USE_OVERLAYS_KEY = "UseOverlays"; //$NON-NLS-1$
+
+	static final String STATE_XSIZE = "XSize"; //$NON-NLS-1$
+
+	static final String STATE_YSIZE = "YSize"; //$NON-NLS-1$
+
+	public static final String MINIMIZED_AND_SHOWING = "MinimizedAndShowing"; //$NON-NLS-1$
+
+	private Image layoutImage;
+
+	private Image restoreImage;
+
+	private ToolBar trimStackTB;
+
+	/**
+	 * The context menu for this trim stack's items.
+	 */
+	private Menu trimStackMenu;
+
+	private boolean cachedUseOverlays = true;
+	private boolean isShowing = false;
+	private MUIElement minimizedElement;
+	// private Composite clientAreaComposite;
+	private Composite hostPane;
+
+	@Inject
+	@Named("org.eclipse.e4.ui.workbench.IResourceUtilities")
+	private IResourceUtilities<ImageDescriptor> resUtils;
+
+	/**
+	 * A map of created images from a part's icon URI path.
+	 */
+	private Map<String, Image> imageMap = new HashMap<String, Image>();
+
+	ControlListener caResizeListener = new ControlListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void controlResized(ControlEvent e) {
+			if (hostPane != null && hostPane.isVisible())
+				setPaneLocation();
+		}
+
+		@Override
+		public void controlMoved(ControlEvent e) {
+		}
+	};
+
+	// Listens to ESC and closes the active fast view
+	private Listener escapeListener = new Listener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void handleEvent(Event event) {
+			if (event.character == SWT.ESC) {
+				showStack(false);
+				partService.requestActivation();
+			}
+		}
+	};
+
+	@Inject
+	EModelService modelService;
+
+	@Inject
+	EPartService partService;
+
+	@Inject
+	MWindow window;
+
+	@Inject
+	MToolControl toolControl;
+
+	@Inject
+	protected IEventBroker eventBroker;
+
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) org.osgi.service.event.Event event) {
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MToolControl))
+			return;
+
+		final MToolControl changedElement = (MToolControl) changedObj;
+		if (changedElement.getObject() != this)
+			return;
+
+		if (UIEvents.isREMOVE(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, MINIMIZED_AND_SHOWING)) {
+				showStack(false);
+			}
+		}
+	}
+
+	private Image getOverrideImage(MUIElement element) {
+		Image result = null;
+
+		Object imageObject = element.getTransientData().get(
+				IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY);
+		if (imageObject != null && imageObject instanceof Image
+				&& !((Image) imageObject).isDisposed())
+			result = (Image) imageObject;
+		return result;
+	}
+
+	private String getOverrideTitleToolTip(MUIElement element) {
+		String result = null;
+
+		Object stringObject = element.getTransientData().get(
+				IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY);
+		if (stringObject != null && stringObject instanceof String)
+			result = (String) stringObject;
+
+		if (result == null || result.length() == 0)
+			return null;
+
+		if (element instanceof MUILabel) {
+			String label = ((MUILabel)element).getLocalizedLabel();
+			if (label != null && label.length() > 0) {
+				result = label + ' ' + '(' + result + ')';
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * This is the new way to handle UIEvents (as opposed to subscring and unsubscribing them with
+	 * the event broker.
+	 *
+	 * The method is described in detail at http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void handleTransientDataEvents(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TRANSIENTDATA) org.osgi.service.event.Event event) {
+		// Prevent exceptions on shutdown
+		if (trimStackTB == null || trimStackTB.isDisposed() || minimizedElement.getWidget() == null)
+			return;
+
+		Object changedElement = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(changedElement instanceof MUIElement)) {
+			return;
+		}
+
+		String key;
+		if (UIEvents.isREMOVE(event)) {
+			key = ((Entry<String, Object>) event.getProperty(UIEvents.EventTags.OLD_VALUE))
+					.getKey();
+		} else {
+			key = ((Entry<String, Object>) event.getProperty(UIEvents.EventTags.NEW_VALUE))
+					.getKey();
+		}
+
+		if (key.equals(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY)) {
+			ToolItem toolItem = getChangedToolItem((MUIElement) changedElement);
+			if (toolItem != null)
+				toolItem.setImage(getImage((MUILabel) toolItem.getData()));
+		} else if (key.equals(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY)) {
+			ToolItem toolItem = getChangedToolItem((MUIElement) changedElement);
+			if (toolItem != null)
+				toolItem.setToolTipText(getLabelText((MUILabel) toolItem.getData()));
+		}
+	}
+
+	private ToolItem getChangedToolItem(MUIElement changedElement) {
+		ToolItem[] toolItems = trimStackTB.getItems();
+		for (ToolItem toolItem : toolItems) {
+			if (changedElement.equals(toolItem.getData())) {
+				return toolItem;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	private EventHandler closeHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			if (!isShowing)
+				return;
+
+			// The only time we don't close is if I've selected my tab.
+			MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+
+			// Perspective changed, close the visible stacks
+			if (changedElement instanceof MPerspectiveStack) {
+				showStack(false);
+				return;
+			}
+
+			if (changedElement instanceof MCompositePart) {
+				MPart innerPart = getLeafPart(changedElement);
+				if (innerPart != null) {
+					fixToolItemSelection();
+					return;
+				}
+			}
+
+			if (changedElement == getLeafPart(minimizedElement)) {
+				fixToolItemSelection();
+				return;
+			}
+
+			showStack(false);
+		}
+	};
+
+	// Close any open stacks before shutting down
+	private EventHandler shutdownHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			showStack(false);
+		}
+	};
+
+	private void fixToolItemSelection() {
+		if (trimStackTB == null || trimStackTB.isDisposed())
+			return;
+
+		if (!isShowing) {
+			// Not open...no selection
+			for (ToolItem item : trimStackTB.getItems()) {
+				item.setSelection(false);
+			}
+		} else {
+			if (isEditorStack() || minimizedElement instanceof MPlaceholder) {
+				trimStackTB.getItem(1).setSelection(true);
+			} else if (isPerspectiveStack()) {
+				MPerspectiveStack pStack = (MPerspectiveStack) minimizedElement;
+				MUIElement selElement = pStack.getSelectedElement();
+				for (ToolItem item : trimStackTB.getItems()) {
+					item.setSelection(item.getData() == selElement);
+				}
+			} else {
+				MPartStack partStack = (MPartStack) minimizedElement;
+				MUIElement selElement = partStack.getSelectedElement();
+				if (selElement instanceof MPlaceholder)
+					selElement = ((MPlaceholder) selElement).getRef();
+
+				for (ToolItem item : trimStackTB.getItems()) {
+					boolean isSel = item.getData() == selElement;
+					item.setSelection(isSel);
+				}
+			}
+		}
+	}
+
+	private boolean isEditorStack() {
+		if (!(minimizedElement instanceof MPlaceholder))
+			return false;
+
+		MPlaceholder ph = (MPlaceholder) minimizedElement;
+		return ph.getRef() instanceof MArea;
+	}
+
+	private boolean isPerspectiveStack() {
+		return minimizedElement instanceof MPerspectiveStack;
+	}
+
+	private MPart getLeafPart(MUIElement element) {
+		if (element instanceof MPlaceholder)
+			return getLeafPart(((MPlaceholder) element).getRef());
+
+		if (element instanceof MElementContainer<?>)
+			return getLeafPart(((MElementContainer<?>) element).getSelectedElement());
+
+		if (element instanceof MPart)
+			return (MPart) element;
+
+		return null;
+	}
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	private EventHandler openHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			if (isShowing)
+				return;
+
+			MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+
+			// Open if shared area
+			if (getLeafPart(minimizedElement) == changedElement
+					&& !(minimizedElement instanceof MPerspectiveStack)) {
+				showStack(true);
+				return;
+			}
+
+			MUIElement selectedElement = null;
+
+			if (minimizedElement instanceof MPlaceholder) {
+				selectedElement = ((MPlaceholder) minimizedElement).getRef();
+			} else if (minimizedElement instanceof MPartStack) {
+				selectedElement = ((MPartStack) minimizedElement).getSelectedElement();
+			}
+
+			if (selectedElement == null)
+				return;
+
+			if (selectedElement instanceof MPlaceholder)
+				selectedElement = ((MPlaceholder) selectedElement).getRef();
+
+			if (changedElement != selectedElement)
+				return;
+
+			showStack(true);
+		}
+	};
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	private EventHandler toBeRenderedHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			if (minimizedElement == null || trimStackTB == null)
+				return;
+
+			MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+
+			// if our stack is going away, so should we
+			if (changedElement == minimizedElement && !minimizedElement.isToBeRendered()) {
+				restoreStack();
+				return;
+			}
+
+			// if one of the kids changes state, re-scrape the CTF
+			MUIElement parentElement = changedElement.getParent();
+			if (parentElement == minimizedElement) {
+				trimStackTB.getDisplay().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						updateTrimStackItems();
+					}
+				});
+			}
+		}
+	};
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	private EventHandler childrenHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			if (minimizedElement == null || trimStackTB == null)
+				return;
+
+			Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+
+			// if a child has been added or removed, re-scape the CTF
+			if (changedObj == minimizedElement) {
+				trimStackTB.getDisplay().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						updateTrimStackItems();
+					}
+				});
+			}
+		}
+	};
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	private EventHandler widgetHandler = new EventHandler() {
+		@Override
+		public void handleEvent(org.osgi.service.event.Event event) {
+			Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+			if (changedObj != minimizedElement)
+				return;
+
+			if (minimizedElement.getWidget() != null) {
+				trimStackTB.getDisplay().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						updateTrimStackItems();
+					}
+				});
+			}
+		}
+	};
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	// Listener attached to every ToolItem in a TrimStack. Responsible for activating the
+	// appropriate part.
+	private SelectionListener toolItemSelectionListener = new SelectionListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void widgetSelected(SelectionEvent e) {
+			ToolItem toolItem = (ToolItem) e.widget;
+			MUIElement uiElement = (MUIElement) toolItem.getData();
+
+			// Clicking on the already showing item ? NOTE: the selection will already have been
+			// turned off by the time the event arrives
+			if (!toolItem.getSelection()) {
+				partService.requestActivation();
+				showStack(false);
+				return;
+			}
+
+			if (uiElement instanceof MPart) {
+				partService.activate((MPart) uiElement);
+			} else if (uiElement instanceof MPerspective) {
+				uiElement.getParent().setSelectedElement(uiElement);
+			}
+			showStack(true);
+		}
+
+		@Override
+		public void widgetDefaultSelected(SelectionEvent e) {
+			widgetSelected(e);
+		}
+	};
+
+	// private MTrimBar bar;
+
+	private int fixedSides;
+
+	private Composite originalParent;
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	@PostConstruct
+	void addListeners() {
+		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, childrenHandler);
+		eventBroker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED, toBeRenderedHandler);
+		eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, widgetHandler);
+		eventBroker.subscribe(UIEvents.UILifeCycle.BRINGTOTOP, openHandler);
+		eventBroker.subscribe(UIEvents.UILifeCycle.ACTIVATE, closeHandler);
+		eventBroker.subscribe(UIEvents.UILifeCycle.APP_SHUTDOWN_STARTED, shutdownHandler);
+	}
+
+	private Composite getCAComposite() {
+		if (trimStackTB == null)
+			return null;
+
+		// Get the shell's client area composite
+		Shell theShell = trimStackTB.getShell();
+		if (theShell.getLayout() instanceof TrimmedPartLayout) {
+			TrimmedPartLayout tpl = (TrimmedPartLayout) theShell.getLayout();
+			if (!tpl.clientArea.isDisposed())
+				return tpl.clientArea;
+		}
+		return null;
+	}
+
+	/**
+	 * This is the old way to subscribe to UIEvents. You should consider using the new way as shown
+	 * by handleTransientDataEvents() and described in the article at
+	 * http://wiki.eclipse.org/Eclipse4/RCP/Event_Model
+	 */
+	@PreDestroy
+	void removeListeners() {
+		eventBroker.unsubscribe(toBeRenderedHandler);
+		eventBroker.unsubscribe(childrenHandler);
+		eventBroker.unsubscribe(widgetHandler);
+		eventBroker.unsubscribe(openHandler);
+		eventBroker.unsubscribe(closeHandler);
+	}
+
+	@PostConstruct
+	void createWidget(Composite parent, MToolControl me, CSSRenderingUtils cssUtils) {
+		if (minimizedElement == null) {
+			minimizedElement = findElement();
+		}
+
+		MUIElement meParent = me.getParent();
+		int orientation = SWT.HORIZONTAL;
+		if (meParent instanceof MTrimBar) {
+			MTrimBar bar = (MTrimBar) meParent;
+			if (bar.getSide() == SideValue.RIGHT || bar.getSide() == SideValue.LEFT)
+				orientation = SWT.VERTICAL;
+		}
+		trimStackTB = new ToolBar(parent, orientation | SWT.FLAT | SWT.WRAP);
+		trimStackTB.addDisposeListener(new DisposeListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				showStack(false);
+
+				trimStackTB = null;
+				trimStackMenu = null;
+			}
+		});
+
+		trimStackTB.addListener(SWT.MenuDetect, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				// Clear any existing menus
+				while (trimStackMenu.getItemCount() > 0)
+					trimStackMenu.getItem(0).dispose();
+
+				// Only open the menu if a tool item is selected
+				Point point = trimStackTB.getDisplay().map(null, trimStackTB,
+						new Point(event.x, event.y));
+				ToolItem selectedToolItem = trimStackTB.getItem(point);
+				if (selectedToolItem == null) {
+					return;
+				}
+
+				// Are we hovering over a valid tool item (vs restore button)
+				Object data = selectedToolItem.getData();
+				if (data instanceof MPart) {
+					// A part on a stack or editor area
+					createPartMenu((MPart) data);
+				} else if (data instanceof MPerspective) {
+					// A perspective in a perspective stack (for now we just support restore)
+					createEmtpyEditorAreaMenu();
+				} else if (isEditorStack()) {
+					// An empty editor area
+					createEmtpyEditorAreaMenu();
+				} else {
+					createUseOverlaysMenu();
+				}
+			}
+		});
+
+		trimStackMenu = new Menu(trimStackTB);
+		trimStackTB.setMenu(trimStackMenu);
+
+		ToolItem restoreBtn = new ToolItem(trimStackTB, SWT.PUSH);
+		restoreBtn.setToolTipText(Messages.TrimStack_RestoreText);
+		restoreBtn.setImage(getRestoreImage());
+		restoreBtn.addSelectionListener(new SelectionAdapter() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				minimizedElement.getTags().remove(IPresentationEngine.MINIMIZED);
+			}
+		});
+
+		updateTrimStackItems();
+	}
+
+	/**
+	 * Creates a restore menu item that removes the minimized tag from the {@link #minimizedElement}
+	 */
+	private void createEmtpyEditorAreaMenu() {
+		MenuItem restoreItem = new MenuItem(trimStackMenu, SWT.NONE);
+		restoreItem.setText(Messages.TrimStack_RestoreText);
+		restoreItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				minimizedElement.getTags().remove(IPresentationEngine.MINIMIZED);
+			}
+		});
+	}
+
+	/**
+	 * Creates a restore menu item that removes the minimized tag from the {@link #minimizedElement}
+	 */
+	private void createUseOverlaysMenu() {
+		MenuItem useOverlaysItem = new MenuItem(trimStackMenu, SWT.CHECK);
+		useOverlaysItem.setText(Messages.TrimStack_Show_In_Original_Location);
+		useOverlaysItem.setSelection(!useOverlays());
+		useOverlaysItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				if (toolControl != null) {
+					toolControl.getPersistedState().put(USE_OVERLAYS_KEY,
+							Boolean.toString(!useOverlays()));
+				}
+			}
+		});
+	}
+
+	/**
+	 * Creates a series of menu items when a part is selected. The orientation submenu changes the
+	 * layout tags on the {@link #minimizedElement}. The restore item will remove the minimized tag.
+	 * The close item is not available on the editor stack, but will ask the part service to hide
+	 * the part.
+	 *
+	 * @param selectedPart
+	 *            the part from the data of the selected tool item
+	 */
+	private void createPartMenu(final MPart selectedPart) {
+		MenuItem orientationItem = new MenuItem(trimStackMenu, SWT.CASCADE);
+		orientationItem.setText(Messages.TrimStack_OrientationMenu);
+		Menu orientationMenu = new Menu(orientationItem);
+		orientationItem.setMenu(orientationMenu);
+
+		MenuItem defaultItem = new MenuItem(orientationMenu, SWT.RADIO);
+		defaultItem.setText(Messages.TrimStack_DefaultOrientationItem);
+		defaultItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				boolean doRefresh = minimizedElement.getTags().remove(
+						IPresentationEngine.ORIENTATION_HORIZONTAL);
+				doRefresh |= minimizedElement.getTags().remove(
+						IPresentationEngine.ORIENTATION_VERTICAL);
+				if (isShowing && doRefresh) {
+					setPaneLocation();
+				}
+			}
+		});
+
+		MenuItem horizontalItem = new MenuItem(orientationMenu, SWT.RADIO);
+		horizontalItem.setText(Messages.TrimStack_Horizontal);
+		horizontalItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				if (!minimizedElement.getTags()
+						.contains(IPresentationEngine.ORIENTATION_HORIZONTAL)) {
+					minimizedElement.getTags().remove(IPresentationEngine.ORIENTATION_VERTICAL);
+					minimizedElement.getTags().add(IPresentationEngine.ORIENTATION_HORIZONTAL);
+					if (isShowing) {
+						setPaneLocation();
+					}
+				}
+			}
+		});
+
+		MenuItem verticalItem = new MenuItem(orientationMenu, SWT.RADIO);
+		verticalItem.setText(Messages.TrimStack_Vertical);
+		verticalItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				if (!minimizedElement.getTags().contains(IPresentationEngine.ORIENTATION_VERTICAL)) {
+					minimizedElement.getTags().remove(IPresentationEngine.ORIENTATION_HORIZONTAL);
+					minimizedElement.getTags().add(IPresentationEngine.ORIENTATION_VERTICAL);
+					if (isShowing) {
+						setPaneLocation();
+					}
+				}
+			}
+		});
+
+		// Set initial orientation selection
+		if (minimizedElement.getTags().contains(IPresentationEngine.ORIENTATION_HORIZONTAL)) {
+			horizontalItem.setSelection(true);
+		} else if (minimizedElement.getTags().contains(IPresentationEngine.ORIENTATION_VERTICAL)) {
+			verticalItem.setSelection(true);
+		} else {
+			defaultItem.setSelection(true);
+		}
+
+		MenuItem restoreItem = new MenuItem(trimStackMenu, SWT.NONE);
+		restoreItem.setText(Messages.TrimStack_RestoreText);
+		restoreItem.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(Event event) {
+				minimizedElement.getTags().remove(IPresentationEngine.MINIMIZED);
+				partService.activate(selectedPart);
+			}
+		});
+
+		// Do not allow the shared editor area to be closed
+		if (!isEditorStack()) {
+			MenuItem closeItem = new MenuItem(trimStackMenu, SWT.NONE);
+			closeItem.setText(Messages.TrimStack_CloseText);
+			closeItem.addListener(SWT.Selection, new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(Event event) {
+					partService.hidePart(selectedPart);
+				}
+			});
+		}
+	}
+
+	@PreDestroy
+	void destroy() {
+		for (Image image : imageMap.values()) {
+			image.dispose();
+		}
+
+		if (layoutImage != null) {
+			layoutImage.dispose();
+			layoutImage = null;
+		}
+
+		if (restoreImage != null) {
+			restoreImage.dispose();
+			restoreImage = null;
+		}
+	}
+
+	public MUIElement getMinimizedElement() {
+		return minimizedElement;
+	}
+
+	private MUIElement findElement() {
+		MUIElement result;
+		List<MPerspectiveStack> ps = modelService.findElements(window, null,
+				MPerspectiveStack.class, null);
+		if (ps.size() == 0) {
+			String toolControlId = toolControl.getElementId();
+			int index = toolControlId.indexOf('(');
+			String stackId = toolControlId.substring(0, index);
+			result = modelService.find(stackId, window);
+		} else {
+			String toolControlId = toolControl.getElementId();
+			int index = toolControlId.indexOf('(');
+			String stackId = toolControlId.substring(0, index);
+			String perspId = toolControlId.substring(index + 1, toolControlId.length() - 1);
+
+			MPerspective persp = null;
+			List<MPerspective> perspectives = modelService.findElements(ps.get(0), perspId, MPerspective.class, null);
+			if (perspectives != null && !perspectives.isEmpty()) {
+				persp = perspectives.get(0);
+			}
+
+			if (persp != null) {
+				result = modelService.find(stackId, persp);
+			} else {
+				result = modelService.find(stackId, window);
+			}
+		}
+
+		return result;
+	}
+
+	private String getLabelText(MUILabel label) {
+		// Use override text if available
+		if (label instanceof MUIElement) {
+			String text = getOverrideTitleToolTip((MUIElement) label);
+			if (text != null && text.length() > 0)
+				return text;
+		}
+
+		String string = label.getLocalizedLabel();
+		return string == null ? "" : string; //$NON-NLS-1$
+	}
+
+	private Image getImage(MUILabel element) {
+		// Use override image if available
+		if (element instanceof MUIElement) {
+			Image image = getOverrideImage((MUIElement) element);
+			if (image != null)
+				return image;
+		}
+
+		String iconURI = element.getIconURI();
+		if (iconURI != null && iconURI.length() > 0) {
+			Image image = imageMap.get(iconURI);
+			if (image == null) {
+				image = resUtils.imageDescriptorFromURI(URI.createURI(iconURI)).createImage();
+				imageMap.put(iconURI, image);
+			}
+			return image;
+		}
+
+		return null;
+	}
+
+	private MUILabel getLabelElement(MUIElement element) {
+		if (element instanceof MPlaceholder)
+			element = ((MPlaceholder) element).getRef();
+
+		return (MUILabel) (element instanceof MUILabel ? element : null);
+	}
+
+	private void updateTrimStackItems() {
+		// Prevent exceptions on shutdown
+		if (trimStackTB == null || trimStackTB.isDisposed() || minimizedElement.getWidget() == null)
+			return;
+
+		// Remove any current items except the 'restore' button
+		while (trimStackTB.getItemCount() > 1) {
+			trimStackTB.getItem(trimStackTB.getItemCount() - 1).dispose();
+		}
+
+		if (isEditorStack() && trimStackTB.getItemCount() == 1) {
+			ToolItem ti = new ToolItem(trimStackTB, SWT.CHECK);
+			ti.setToolTipText(Messages.TrimStack_SharedAreaTooltip);
+			ti.setImage(getLayoutImage());
+			ti.addSelectionListener(toolItemSelectionListener);
+		} else if (minimizedElement instanceof MPlaceholder) {
+			MPlaceholder ph = (MPlaceholder) minimizedElement;
+			if (ph.getRef() instanceof MPart) {
+				MPart part = (MPart) ph.getRef();
+				ToolItem ti = new ToolItem(trimStackTB, SWT.CHECK);
+				ti.setData(part);
+				ti.setImage(getImage(part));
+				ti.setToolTipText(getLabelText(part));
+				ti.addSelectionListener(toolItemSelectionListener);
+			}
+		} else if (minimizedElement instanceof MGenericStack<?>) {
+			// Handle *both* PartStacks and PerspectiveStacks here...
+			MGenericStack<?> theStack = (MGenericStack<?>) minimizedElement;
+
+			// check to see if this stack has any valid elements
+			boolean hasRenderedElements = false;
+			for (MUIElement stackElement : theStack.getChildren()) {
+				if (stackElement.isToBeRendered()) {
+					hasRenderedElements = true;
+					break;
+				}
+			}
+
+			if (hasRenderedElements) {
+				for (MUIElement stackElement : theStack.getChildren()) {
+					if (!stackElement.isToBeRendered()) {
+						continue;
+					}
+
+					MUILabel labelElement = getLabelElement(stackElement);
+					ToolItem newItem = new ToolItem(trimStackTB, SWT.CHECK);
+					newItem.setData(labelElement);
+					newItem.setImage(getImage(labelElement));
+					newItem.setToolTipText(getLabelText(labelElement));
+					newItem.addSelectionListener(toolItemSelectionListener);
+				}
+			} else if (theStack.getTags().contains(IPresentationEngine.NO_AUTO_COLLAPSE)) {
+				// OK to be empty and still minimized
+				ToolItem ti = new ToolItem(trimStackTB, SWT.CHECK);
+				ti.setToolTipText(Messages.TrimStack_EmptyStackTooltip);
+				ti.setImage(getLayoutImage());
+				ti.addSelectionListener(toolItemSelectionListener);
+			} else {
+				// doesn't have any children that's showing, place it back in the presentation
+				restoreStack();
+				return;
+			}
+		}
+
+		trimStackTB.pack();
+		trimStackTB.getShell().layout(new Control[] { trimStackTB }, SWT.DEFER);
+	}
+
+	void restoreStack() {
+		showStack(false);
+
+		minimizedElement.setVisible(true);
+		minimizedElement.getTags().remove(IPresentationEngine.MINIMIZED);
+
+		// Activate the part that is being brought up...
+		if (minimizedElement instanceof MPartStack) {
+			MPartStack theStack = (MPartStack) minimizedElement;
+			MStackElement curSel = theStack.getSelectedElement();
+			Control ctrl = (Control) minimizedElement.getWidget();
+
+			// Hack for elems that are lazy initialized
+			if (ctrl instanceof CTabFolder && ((CTabFolder) ctrl).getSelection() == null) {
+				theStack.setSelectedElement(null);
+				theStack.setSelectedElement(curSel);
+			}
+		}
+
+		toolControl.setToBeRendered(false);
+
+		if (hostPane != null && !hostPane.isDisposed())
+			hostPane.dispose();
+		hostPane = null;
+	}
+
+	/**
+	 * Sets whether this stack should be visible or hidden
+	 *
+	 * @param show
+	 *            whether the stack should be visible
+	 */
+	public void showStack(boolean show) {
+		Control ctrl = (Control) minimizedElement.getWidget();
+		CTabFolder ctf = ctrl instanceof CTabFolder ? (CTabFolder) ctrl : null;
+
+		Composite clientAreaComposite = getCAComposite();
+		if (clientAreaComposite == null || clientAreaComposite.isDisposed())
+			return;
+
+		if (show && !isShowing) {
+			if (useOverlays()) {
+				hostPane = getHostPane();
+				originalParent = ctrl.getParent();
+				ctrl.setParent(hostPane);
+
+				// Hack ! Force a resize of the CTF to make sure the hosted
+				// view is the correct size...see bug 434062 for details
+				if (ctf != null) {
+					Rectangle bb = ctf.getBounds();
+					bb.width--;
+					ctf.setBounds(bb);
+				}
+
+				clientAreaComposite.addControlListener(caResizeListener);
+
+				// Set the initial location
+				setPaneLocation();
+
+				hostPane.addListener(SWT.Traverse, escapeListener);
+
+				hostPane.layout(true);
+				hostPane.moveAbove(null);
+				hostPane.setVisible(true);
+
+				// Cache the value to ensure that a stack is hidden using the same mode it was
+				// opened in
+				cachedUseOverlays = true;
+			} else {
+				minimizedElement.setVisible(true);
+				ctrl.addListener(SWT.Traverse, escapeListener);
+
+				// Cache the value to ensure that a stack is hidden using the same mode it was
+				// opened in
+				cachedUseOverlays = false;
+			}
+
+			isShowing = true;
+			toolControl.getTags().add(MINIMIZED_AND_SHOWING);
+
+			// Activate the part that is being brought up...
+			if (minimizedElement instanceof MPartStack) {
+				MPartStack theStack = (MPartStack) minimizedElement;
+				MStackElement curSel = theStack.getSelectedElement();
+
+				// Hack for elems that are lazy initialized
+				if (ctf != null && ctf.getSelection() == null) {
+					theStack.setSelectedElement(null);
+					theStack.setSelectedElement(curSel);
+				}
+
+				if (curSel instanceof MPart) {
+					partService.activate((MPart) curSel);
+				} else if (curSel instanceof MPlaceholder) {
+					MPlaceholder ph = (MPlaceholder) curSel;
+					if (ph.getRef() instanceof MPart) {
+						partService.activate((MPart) ph.getRef());
+					}
+				}
+			} else if (isEditorStack()) {
+				MArea area = (MArea) ((MPlaceholder) minimizedElement).getRef();
+
+				// See if we can find an element to activate...
+				MPart partToActivate = null;
+				MUIElement selectedElement = area.getSelectedElement();
+				while (partToActivate == null && selectedElement != null) {
+					if (selectedElement instanceof MPart) {
+						partToActivate = (MPart) selectedElement;
+					} else if (selectedElement instanceof MPlaceholder) {
+						MPlaceholder ph = (MPlaceholder) selectedElement;
+						if (ph.getRef() instanceof MPart) {
+							partToActivate = (MPart) ph.getRef();
+						} else {
+							selectedElement = null;
+						}
+					} else if (selectedElement instanceof MElementContainer<?>) {
+						MElementContainer<?> container = (MElementContainer<?>) selectedElement;
+						selectedElement = container.getSelectedElement();
+					}
+				}
+
+				// If we haven't found one then use the first
+				if (partToActivate == null) {
+					List<MPart> parts = modelService.findElements(area, null, MPart.class, null);
+					for (MPart part : parts) {
+						if (partService.isPartVisible(part)) {
+							partToActivate = part;
+							break;
+						}
+					}
+				}
+
+				if (partToActivate != null) {
+					partService.activate(partToActivate);
+				}
+			} else if (minimizedElement instanceof MPlaceholder) {
+				MPlaceholder ph = (MPlaceholder) minimizedElement;
+				if (ph.getRef() instanceof MPart) {
+					MPart part = (MPart) ph.getRef();
+					partService.activate(part);
+				}
+			}
+
+			fixToolItemSelection();
+		} else if (!show && isShowing) {
+			if (cachedUseOverlays) {
+				// Check to ensure that the client area is non-null since the
+				// trimstack may be currently hosted in the limbo shell
+				if (clientAreaComposite != null) {
+					clientAreaComposite.removeControlListener(caResizeListener);
+				}
+
+				ctrl.setParent(originalParent);
+
+				hostPane.dispose();
+				hostPane = null;
+			} else {
+				if (ctrl != null && !ctrl.isDisposed())
+					ctrl.removeListener(SWT.Traverse, escapeListener);
+				minimizedElement.setVisible(false);
+			}
+
+			isShowing = false;
+			toolControl.getTags().remove(MINIMIZED_AND_SHOWING);
+
+			fixToolItemSelection();
+		}
+	}
+
+	/**
+	 * @return 'true' iff the minimized stack should overlay the current presentation, 'false' means
+	 *         to temporarily restore the stack into the current presentation.
+	 */
+	private boolean useOverlays() {
+		if (toolControl == null)
+			return true;
+
+		String useOverlays = toolControl.getPersistedState().get(USE_OVERLAYS_KEY);
+		if (useOverlays == null)
+			useOverlays = "true"; //$NON-NLS-1$
+		return Boolean.parseBoolean(useOverlays);
+	}
+
+	private void setPaneLocation() {
+		Composite clientAreaComposite = getCAComposite();
+		if (clientAreaComposite == null || clientAreaComposite.isDisposed())
+			return;
+
+		Rectangle caRect = clientAreaComposite.getBounds();
+
+		// NOTE: always starts in the persisted (or default) size
+		Point paneSize = hostPane.getSize();
+
+		// Ensure it's not clipped
+		if (paneSize.x > caRect.width)
+			paneSize.x = caRect.width;
+		if (paneSize.y > caRect.height)
+			paneSize.y = caRect.height;
+
+		if (minimizedElement.getTags().contains(IPresentationEngine.ORIENTATION_HORIZONTAL))
+			paneSize.x = caRect.width;
+		if (minimizedElement.getTags().contains(IPresentationEngine.ORIENTATION_VERTICAL))
+			paneSize.y = caRect.height;
+
+		Point loc = new Point(0, 0);
+		if (isFixed(SWT.LEFT))
+			loc.x = caRect.x;
+		else
+			loc.x = (caRect.x + caRect.width) - paneSize.x;
+
+		if (isFixed(SWT.TOP))
+			loc.y = caRect.y;
+		else
+			loc.y = (caRect.y + caRect.height) - paneSize.y;
+
+		hostPane.setSize(paneSize);
+		hostPane.setLocation(loc);
+	}
+
+	private void setHostSize() {
+		if (hostPane == null || hostPane.isDisposed())
+			return;
+
+		int xSize = 600;
+		String xSizeStr = toolControl.getPersistedState().get(STATE_XSIZE);
+		if (xSizeStr != null)
+			xSize = Integer.parseInt(xSizeStr);
+		int ySize = 400;
+		String ySizeStr = toolControl.getPersistedState().get(STATE_YSIZE);
+		if (ySizeStr != null)
+			ySize = Integer.parseInt(ySizeStr);
+		hostPane.setSize(xSize, ySize);
+	}
+
+	private Composite getHostPane() {
+		// Create one
+		hostPane = new Composite(trimStackTB.getShell(), SWT.NONE);
+		hostPane.setData(ShellActivationListener.DIALOG_IGNORE_KEY, Boolean.TRUE);
+
+		hostPane.addDisposeListener(new DisposeListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				hostPane = null;
+			}
+		});
+
+		setHostSize();
+
+		// Set a special layout that allows resizing
+		fixedSides = getFixedSides();
+		hostPane.setLayout(new TrimPaneLayout(toolControl, fixedSides));
+
+		return hostPane;
+	}
+
+	private int getFixedSides() {
+		MUIElement tcParent = toolControl.getParent();
+		if (!(tcParent instanceof MTrimBar))
+			return 0;
+		MTrimBar bar = (MTrimBar) tcParent;
+		Composite trimComp = (Composite) bar.getWidget();
+		Rectangle trimBounds = trimComp.getBounds();
+		Point trimCenter = new Point(trimBounds.width / 2, trimBounds.height / 2); // adjusted to
+																					// (0,0)
+
+		Control trimCtrl = (Control) toolControl.getWidget();
+		Rectangle ctrlBounds = trimCtrl.getBounds();
+		Point ctrlCenter = new Point(ctrlBounds.x + (ctrlBounds.width / 2), ctrlBounds.y
+				+ (ctrlBounds.height / 2));
+
+		if (bar.getSide() == SideValue.LEFT) {
+			int verticalValue = ctrlCenter.y < trimCenter.y ? SWT.TOP : SWT.BOTTOM;
+			return SWT.LEFT | verticalValue;
+		} else if (bar.getSide() == SideValue.RIGHT) {
+			int verticalValue = ctrlCenter.y < trimCenter.y ? SWT.TOP : SWT.BOTTOM;
+			return SWT.RIGHT | verticalValue;
+		} else if (bar.getSide() == SideValue.TOP) {
+			int horizontalValue = ctrlCenter.x < trimCenter.x ? SWT.LEFT : SWT.RIGHT;
+			return SWT.TOP | horizontalValue;
+		} else if (bar.getSide() == SideValue.BOTTOM) {
+			int horizontalValue = ctrlCenter.x < trimCenter.x ? SWT.LEFT : SWT.RIGHT;
+			return SWT.BOTTOM | horizontalValue;
+		}
+
+		return SWT.BOTTOM | SWT.RIGHT;
+	}
+
+	private Image getLayoutImage() {
+		if (layoutImage == null) {
+			layoutImage = resUtils.imageDescriptorFromURI(URI.createURI(LAYOUT_ICON_URI))
+					.createImage();
+		}
+		return layoutImage;
+	}
+
+	private Image getRestoreImage() {
+		if (restoreImage == null) {
+			restoreImage = resUtils.imageDescriptorFromURI(URI.createURI(RESTORE_ICON_URI))
+					.createImage();
+		}
+		return restoreImage;
+	}
+
+	private boolean isFixed(int swtSide) {
+		return (fixedSides & swtSide) != 0;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/messages.properties b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/messages.properties
new file mode 100644
index 0000000..560e318
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/minmax/messages.properties
@@ -0,0 +1,20 @@
+################################################################################
+# Copyright (c) 2011, 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
+################################################################################
+
+TrimStack_EmptyStackTooltip = Empty Stack
+TrimStack_SharedAreaTooltip = Shared Area
+TrimStack_CloseText = &Close
+TrimStack_DefaultOrientationItem=&Default
+TrimStack_RestoreText = &Restore
+TrimStack_Horizontal = &Horizontal
+TrimStack_OrientationMenu=&Orientation
+TrimStack_Vertical = &Vertical
+TrimStack_Show_In_Original_Location = &Show in the Original Location
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitHost.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitHost.java
new file mode 100644
index 0000000..2c18f40
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitHost.java
@@ -0,0 +1,135 @@
+/*******************************************************************************

+ * Copyright (c) 2013, 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.workbench.addons.splitteraddon;

+

+import java.lang.annotation.Annotation;

+import java.util.List;

+import javax.inject.Inject;

+import org.eclipse.e4.core.contexts.ContextInjectionFactory;

+import org.eclipse.e4.core.di.annotations.Optional;

+import org.eclipse.e4.ui.di.Focus;

+import org.eclipse.e4.ui.di.Persist;

+import org.eclipse.e4.ui.di.PersistState;

+import org.eclipse.e4.ui.di.UIEventTopic;

+import org.eclipse.e4.ui.model.application.ui.MElementContainer;

+import org.eclipse.e4.ui.model.application.ui.MUIElement;

+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;

+import org.eclipse.e4.ui.model.application.ui.basic.MPart;

+import org.eclipse.e4.ui.workbench.UIEvents;

+import org.eclipse.e4.ui.workbench.modeling.EModelService;

+import org.eclipse.e4.ui.workbench.modeling.EPartService;

+import org.eclipse.swt.widgets.Control;

+import org.osgi.service.event.Event;

+

+/**

+ * Support containment of split internal parts.

+ */

+public class SplitHost {

+	@Inject

+	EModelService ms;

+	@Inject

+	EPartService ps;

+	@Inject

+	MCompositePart myPart;

+

+	List<MPart> getSubParts() {

+		List<MPart> childParts = ms.findElements(myPart, null, MPart.class, null);

+		return childParts;

+	}

+

+	MPart findInnerActive(MCompositePart outer) {

+		MPart innerActive = null;

+		MUIElement curParent = outer;

+		while (innerActive == null && curParent != null) {

+			if (curParent instanceof MElementContainer<?>) {

+				MElementContainer<?> container = (MElementContainer<?>) curParent;

+				if (container.getSelectedElement() instanceof MPart) {

+					innerActive = (MPart) container.getSelectedElement();

+				} else if (container.getSelectedElement() instanceof MElementContainer<?>) {

+					curParent = container.getSelectedElement();

+				} else {

+					curParent = null;

+				}

+			}

+		}

+

+		return innerActive;

+	}

+

+	@Inject

+	@Optional

+	void tbrHandler(@UIEventTopic(UIEvents.Dirtyable.TOPIC_DIRTY) Event eventData) {

+		MUIElement changedElement = (MUIElement) eventData.getProperty(UIEvents.EventTags.ELEMENT);

+

+		if (!isOneOfMyParts(changedElement))

+			return;

+

+		boolean isDirty = false;

+		List<MPart> kids = getSubParts();

+		kids.remove(0);

+		for (MPart subPart : kids) {

+			isDirty |= subPart.isDirty();

+		}

+		myPart.setDirty(isDirty);

+	}

+

+	private boolean isOneOfMyParts(MUIElement changedElement) {

+		MElementContainer<MUIElement> parent = changedElement.getParent();

+		Object parentObj = parent;

+		while (parent != null && parentObj != myPart) {

+			parent = parent.getParent();

+			parentObj = parent;

+		}

+

+		return parentObj == myPart;

+	}

+

+	void callingAllParts(Class<? extends Annotation> clz) {

+		List<MPart> parts = ms.findElements(myPart, null, MPart.class, null);

+		for (MPart part : parts) {

+			if (part == myPart)

+				continue;

+

+			Control ctrl = (Control) part.getWidget();

+			if (part.getObject() != null && ctrl != null && !ctrl.isDisposed())

+				ContextInjectionFactory.invoke(part.getObject(), clz, part.getContext(), null);

+		}

+	}

+

+	@Persist

+	void persist() {

+		callingAllParts(Persist.class);

+	}

+

+	@PersistState

+	void persistState() {

+		callingAllParts(PersistState.class);

+	}

+

+	@Focus

+	void setFocus() {

+		MPart ap = findInnerActive(myPart);

+		if (ap == null)

+			return;

+

+		Control ctrl = (Control) ap.getWidget();

+		if (ap.getObject() != null && ctrl != null && !ctrl.isDisposed())

+			ContextInjectionFactory.invoke(ap.getObject(), Focus.class, ap.getContext(), null);

+	}

+

+	// @PostConstruct

+	// void createWidget(Composite parent) {

+	// System.out.println("New Split Host");

+	// Composite newComp = new Composite(parent, SWT.NONE);

+	// newComp.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN));

+	// newComp.setLayout(new FillLayout());

+	// }

+}

diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitterAddon.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitterAddon.java
new file mode 100644
index 0000000..3c44060
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/splitteraddon/SplitterAddon.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.workbench.addons.splitteraddon;
+
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.osgi.service.event.Event;
+
+/**
+ * Listens for the IPresentationEngine's SPLIT_HORIZONTAL and SPLIT_VERTICAL tags being applied to
+ * an MPart and takes the appropriate steps to split / unsplit the part
+ */
+public class SplitterAddon {
+	@Inject
+	EModelService ms;
+
+	@Inject
+	EPartService ps;
+
+	/**
+	 * Handles changes in tags
+	 *
+	 * @param event
+	 */
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MPart))
+			return;
+
+		MPart part = (MPart) changedObj;
+
+		if (UIEvents.isADD(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE,
+					IPresentationEngine.SPLIT_HORIZONTAL)) {
+				splitPart(part, true);
+			} else if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE,
+					IPresentationEngine.SPLIT_VERTICAL)) {
+				splitPart(part, false);
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			MCompositePart compPart = SplitterAddon.findContainingCompositePart(part);
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE,
+					IPresentationEngine.SPLIT_HORIZONTAL)) {
+				unsplitPart(compPart);
+			} else if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE,
+					IPresentationEngine.SPLIT_VERTICAL)) {
+				unsplitPart(compPart);
+			}
+		}
+	}
+
+	/**
+	 * Finds the CompositePart containing the given part (if any)
+	 *
+	 * @param part
+	 * @return The MCompositePart or 'null' if none is found
+	 */
+	public static MCompositePart findContainingCompositePart(MPart part) {
+		if (part == null)
+			return null;
+
+		MUIElement curParent = part.getParent();
+		while (curParent != null && !(curParent instanceof MCompositePart))
+			curParent = curParent.getParent();
+
+		return (MCompositePart) curParent;
+	}
+
+	private void unsplitPart(MCompositePart compositePart) {
+		if (compositePart == null)
+			return;
+
+		List<MPart> innerElements = ms.findElements(compositePart, null, MPart.class, null);
+		if (innerElements.size() < 3)
+			return;
+
+		MPart originalEditor = innerElements.get(1); // '0' is the composite part
+
+		// Close the cloned editor *before* removing it from the model
+		MPart clonedEditor = innerElements.get(2);
+		clonedEditor.setToBeRendered(false);
+
+		MElementContainer<MUIElement> compParent = compositePart.getParent();
+		int index = compParent.getChildren().indexOf(compositePart);
+		compParent.getChildren().remove(compositePart);
+		originalEditor.getParent().getChildren().remove(originalEditor);
+		compParent.getChildren().add(index, originalEditor);
+
+		if (ps.getActivePart() == originalEditor)
+			ps.activate(null);
+		ps.activate(originalEditor);
+	}
+
+	private MCompositePart createCompositePart(MPart originalPart) {
+		MCompositePart compPart = ms.createModelElement(MCompositePart.class);
+		compPart.setElementId("Split Host(" + originalPart.getLabel() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+		compPart.setLabel(originalPart.getLabel());
+		compPart.setTooltip(originalPart.getTooltip());
+		compPart.setIconURI(originalPart.getIconURI());
+		compPart.setCloseable(true);
+		compPart.setContributionURI("bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.splitteraddon.SplitHost"); //$NON-NLS-1$
+
+		// Always remove the composite part from the model
+		compPart.getTags().add(EPartService.REMOVE_ON_HIDE_TAG);
+
+		return compPart;
+	}
+
+	void splitPart(MPart partToSplit, boolean horizontal) {
+		MElementContainer<MUIElement> parent = partToSplit.getParent();
+		int index = parent.getChildren().indexOf(partToSplit);
+
+		MPart editorClone = (MPart) ms.cloneElement(partToSplit, null);
+
+		MCompositePart compPart = createCompositePart(partToSplit);
+
+		// Add the new composite part to the model
+		compPart.getChildren().add(editorClone);
+		compPart.setSelectedElement(editorClone);
+		parent.getChildren().add(index, compPart);
+		parent.setSelectedElement(compPart);
+
+		// Now, add the original part into the composite
+		int orientation = horizontal ? EModelService.ABOVE : EModelService.LEFT_OF;
+		ms.insert(partToSplit, editorClone, orientation, 0.5f);
+
+		ps.activate(partToSplit);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/CleanupProcessor.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/CleanupProcessor.java
new file mode 100644
index 0000000..6e99b50
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/CleanupProcessor.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 429421
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.addons.swt;
+
+import java.util.List;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+/**
+ * Model processors which adds the cleanup add-on to the application model
+ */
+public class CleanupProcessor {
+	@Execute
+	void addCleanupAddon(MApplication app, EModelService modelService) {
+		List<MAddon> addons = app.getAddons();
+
+		// prevent multiple copies
+		for (MAddon addon : addons) {
+			if (addon.getContributionURI()
+					.contains("ui.workbench.addons.cleanupaddon.CleanupAddon")) //$NON-NLS-1$
+				return;
+		}
+
+		// adds the add-on to the application model
+		MAddon cleanupAddon = modelService.createModelElement(MAddon.class);
+		cleanupAddon.setElementId("CleanupAddon"); //$NON-NLS-1$
+		cleanupAddon
+				.setContributionURI("bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.cleanupaddon.CleanupAddon"); //$NON-NLS-1$
+		app.getAddons().add(cleanupAddon);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/DnDProcessor.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/DnDProcessor.java
new file mode 100644
index 0000000..03f27af
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/DnDProcessor.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 429421
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.addons.swt;
+
+import java.util.List;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+/**
+ * Model processors which adds the DnD add-on to the application model
+ */
+public class DnDProcessor {
+	@Execute
+	void addDnDAddon(MApplication app, EModelService modelService) {
+		List<MAddon> addons = app.getAddons();
+
+		// prevent multiple copies
+		for (MAddon addon : addons) {
+			if (addon.getContributionURI().contains("ui.workbench.addons.dndaddon.DnDAddon")) //$NON-NLS-1$
+				return;
+		}
+
+		// adds the add-on to the application model
+		MAddon dndAddon = modelService.createModelElement(MAddon.class);
+		dndAddon.setElementId("DnDAddon"); //$NON-NLS-1$
+		dndAddon.setContributionURI("bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.dndaddon.DnDAddon"); //$NON-NLS-1$
+		app.getAddons().add(dndAddon);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/MinMaxProcessor.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/MinMaxProcessor.java
new file mode 100644
index 0000000..339d265
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/MinMaxProcessor.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 429421
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.addons.swt;
+
+import java.util.List;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+/**
+ * Model processors which adds the MinMax add-on to the application model
+ */
+public class MinMaxProcessor {
+	@Execute
+	void addMinMaxAddon(MApplication app, EModelService modelService) {
+		List<MAddon> addons = app.getAddons();
+
+		// prevent multiple copies
+		for (MAddon addon : addons) {
+			if (addon.getContributionURI().contains("ui.workbench.addons.minmax.MinMaxAddon")) //$NON-NLS-1$
+				return;
+		}
+
+		// add the add-on to the application model
+		MAddon minMaxAddon = modelService.createModelElement(MAddon.class);
+		minMaxAddon.setElementId("MinMaxAddon"); //$NON-NLS-1$
+		minMaxAddon
+				.setContributionURI("bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.minmax.MinMaxAddon"); //$NON-NLS-1$
+		app.getAddons().add(minMaxAddon);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/SplitterProcessor.java b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/SplitterProcessor.java
new file mode 100644
index 0000000..c0f6a24
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.addons.swt/src/org/eclipse/e4/ui/workbench/addons/swt/SplitterProcessor.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 429421
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.addons.swt;
+
+import java.util.List;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+/**
+ * Model processors which adds the Splitter add-on to the application model
+ */
+
+public class SplitterProcessor {
+	@Execute
+	void addSplitterAddon(MApplication app, EModelService modelService) {
+		List<MAddon> addons = app.getAddons();
+
+		// prevent multiple copies
+		for (MAddon addon : addons) {
+			if (addon.getContributionURI().contains(
+					"ui.workbench.addons.splitteraddon.SplitterAddon")) //$NON-NLS-1$
+				return;
+		}
+
+		// adds the add-on to the application model
+		MAddon splitterAddon = modelService.createModelElement(MAddon.class);
+		splitterAddon.setElementId("SplitterAddon"); //$NON-NLS-1$
+		splitterAddon
+				.setContributionURI("bundleclass://org.eclipse.e4.ui.workbench.addons.swt/org.eclipse.e4.ui.workbench.addons.splitteraddon.SplitterAddon"); //$NON-NLS-1$
+		app.getAddons().add(splitterAddon);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.classpath b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.classpath
new file mode 100644
index 0000000..e8ea977
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.project b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.project
new file mode 100644
index 0000000..0f9d498
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.workbench.renderers.swt</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.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..137c694
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,418 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..87b7a26
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,124 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*******************************************************************************\r\n * Copyright (c) ${year} IBM Corporation and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n *\r\n * Contributors\:\r\n *     IBM Corporation - initial API and implementation\r\n ******************************************************************************/\r\n</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=true
+sp_cleanup.remove_unused_imports=true
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..cbbdef3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/MANIFEST.MF
@@ -0,0 +1,36 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.ui.workbench.renderers.swt;singleton:=true
+Bundle-Version: 0.13.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.e4.ui.workbench;bundle-version="0.9.0",
+ org.eclipse.e4.core.services;bundle-version="0.9.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.0.0",
+ org.eclipse.e4.core.di;bundle-version="1.1.0",
+ org.eclipse.e4.ui.services;bundle-version="0.9.0",
+ org.eclipse.e4.ui.workbench.swt;bundle-version="0.9.0",
+ org.eclipse.e4.ui.model.workbench;bundle-version="0.9.0",
+ org.eclipse.osgi.services;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.e4.core.commands;bundle-version="0.9.0",
+ org.eclipse.e4.ui.bindings;bundle-version="0.9.0",
+ org.eclipse.equinox.common;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.4.200,4.0.0)",
+ org.eclipse.osgi;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.e4.ui.di;bundle-version="0.9.0",
+ org.eclipse.emf.ecore;bundle-version="2.7.0",
+ org.eclipse.rap.rwt,
+ org.eclipse.core.commands,
+ org.eclipse.rap.jface,
+ org.eclipse.e4.core.di.extensions;bundle-version="0.12.0",
+ org.eclipse.equinox.preferences;bundle-version="3.5.200"
+Require-Capability: org.eclipse.rap
+Export-Package: org.eclipse.e4.ui.internal.workbench.renderers.swt;x-friends:="org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.workbench.renderers.swt;x-friends:="org.eclipse.e4.ui.workbench.addons.swt,org.eclipse.ui.workbench"
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0",
+ org.w3c.dom.css;version="2.0.0"
+Bundle-Activator: org.eclipse.e4.ui.internal.workbench.renderers.swt.SWTRenderersActivator
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/p2.inf b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/about.html b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/build.properties b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/build.properties
new file mode 100644
index 0000000..591b4b8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/build.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2013, 2015 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
+###############################################################################
+source.. = src/,\
+           src-rap/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.properties,\
+               icons/
+src.includes = about.html
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/forceQualifierUpdate.txt
new file mode 100644
index 0000000..d01ddc1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/forceQualifierUpdate.txt
@@ -0,0 +1,4 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
+Bug 407961 - Comparator log shows special problem that will require "touches"
+
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/ovr16/pinned_ovr.gif b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/ovr16/pinned_ovr.gif
new file mode 100644
index 0000000..2f3b201
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/ovr16/pinned_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/viewMenu.png b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/viewMenu.png
new file mode 100644
index 0000000..439b26c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/icons/viewMenu.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/plugin.properties b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/plugin.properties
new file mode 100644
index 0000000..db2c749
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 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
+###############################################################################
+pluginName = Eclipse e4 Workbench SWT Renderer
+providerName = Eclipse.org
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/pom.xml b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/pom.xml
new file mode 100644
index 0000000..7d83788
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.workbench.renderers.swt</artifactId>
+  <version>0.13.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/AbstractTableInformationControl.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/AbstractTableInformationControl.java
new file mode 100644
index 0000000..89cc744
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/AbstractTableInformationControl.java
@@ -0,0 +1,597 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2015 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.internal.workbench.renderers.swt;
+
+import org.eclipse.e4.ui.workbench.swt.internal.copy.SearchPattern;
+import org.eclipse.e4.ui.workbench.swt.internal.copy.WorkbenchSWTMessages;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+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.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @since 3.0
+ */
+public abstract class AbstractTableInformationControl {
+
+	/**
+	 * The NamePatternFilter selects the elements which match the given string
+	 * patterns.
+	 */
+	protected class NamePatternFilter extends ViewerFilter {
+
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public boolean select(Viewer viewer, Object parentElement,
+				Object element) {
+			SearchPattern matcher = getMatcher();
+			if (matcher == null || !(viewer instanceof TableViewer)) {
+				return true;
+			}
+			TableViewer tableViewer = (TableViewer) viewer;
+
+			String matchName = ((ILabelProvider) tableViewer.getLabelProvider())
+					.getText(element);
+
+			if (matchName == null) {
+				return false;
+			}
+			// A dirty editor's label will start with dirty prefix, this prefix
+			// should not be taken in consideration when matching with a pattern
+			if (matchName.startsWith("*")) { //$NON-NLS-1$
+				matchName = matchName.substring(1);
+			}
+			return matcher.matches(matchName);
+		}
+	}
+
+	/** The control's shell */
+	private Shell fShell;
+
+	/** The composite */
+	private Composite fComposite;
+
+	/** The control's text widget */
+	private Text fFilterText;
+
+	/** The control's table widget */
+	private TableViewer fTableViewer;
+
+	/** The current search pattern */
+	private SearchPattern fSearchPattern;
+
+	/**
+	 * Creates an information control with the given shell as parent. The given
+	 * styles are applied to the shell and the table widget.
+	 *
+	 * @param parent
+	 *            the parent shell
+	 * @param shellStyle
+	 *            the additional styles for the shell
+	 * @param controlStyle
+	 *            the additional styles for the control
+	 */
+	public AbstractTableInformationControl(Shell parent, int shellStyle,
+			int controlStyle) {
+		fShell = new Shell(parent, shellStyle);
+		fShell.setLayout(new FillLayout());
+
+		// Composite for filter text and viewer
+		fComposite = new Composite(fShell, SWT.RESIZE);
+		GridLayout layout = new GridLayout(1, false);
+		fComposite.setLayout(layout);
+		createFilterText(fComposite);
+
+		fTableViewer = createTableViewer(fComposite, controlStyle);
+
+		final Table table = fTableViewer.getTable();
+		table.addKeyListener(new KeyListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void keyPressed(KeyEvent e) {
+				switch (e.keyCode) {
+				case SWT.ESC:
+					dispose();
+					break;
+				case SWT.DEL:
+					removeSelectedItems();
+					e.character = SWT.NONE;
+					e.doit = false;
+					break;
+				case SWT.ARROW_UP:
+					if (table.getSelectionIndex() == 0) {
+						// on the first item, going up should grant focus to
+						// text field
+						fFilterText.setFocus();
+					}
+					break;
+				case SWT.ARROW_DOWN:
+					if (table.getSelectionIndex() == table.getItemCount() - 1) {
+						// on the last item, going down should grant focus to
+						// the text field
+						fFilterText.setFocus();
+					}
+					break;
+				}
+			}
+
+			@Override
+			public void keyReleased(KeyEvent e) {
+				// do nothing
+			}
+		});
+
+		table.addSelectionListener(new SelectionListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				// do nothing;
+			}
+
+			@Override
+			public void widgetDefaultSelected(SelectionEvent e) {
+				gotoSelectedElement();
+			}
+		});
+
+		/*
+		 * Bug in GTK, see SWT bug: 62405 Editor drop down performance slow on
+		 * Linux-GTK on mouse move. Rather then removing the support altogether
+		 * this feature has been worked around for GTK only as we expect that
+		 * newer versions of GTK will no longer exhibit this quality and we will
+		 * be able to have the desired support running on all platforms. See
+		 * comment https://bugs.eclipse.org/bugs/show_bug.cgi?id=62405#c22 TODO:
+		 * remove this code once bug 62405 is fixed for the mainstream GTK
+		 * version
+		 */
+		// final int ignoreEventCount = Util.isGtk() ? 4 : 1;
+		// FIXME RAP does not support mouse move
+//
+//		table.addMouseMoveListener(new MouseMoveListener() {
+//			/**
+//			 *
+//			 */
+//			private static final long serialVersionUID = 1L;
+//			TableItem fLastItem = null;
+//			int lastY = 0;
+//			int itemHeightdiv4 = table.getItemHeight() / 4;
+//			int tableHeight = table.getBounds().height;
+//			Point tableLoc = table.toDisplay(0, 0);
+//			int divCount = 0;
+//
+//			@Override
+//			public void mouseMove(MouseEvent e) {
+//				if (divCount == ignoreEventCount) {
+//					divCount = 0;
+//				}
+//				if (table.equals(e.getSource()) & ++divCount == ignoreEventCount) {
+//					Object o = table.getItem(new Point(e.x, e.y));
+//					if (fLastItem == null ^ o == null) {
+//						table.setCursor(o == null ? null : table.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+//					}
+//					if (o instanceof TableItem && lastY != e.y) {
+//						lastY = e.y;
+//						if (!o.equals(fLastItem)) {
+//							fLastItem = (TableItem) o;
+//							table.setSelection(new TableItem[] { fLastItem });
+//						} else if (e.y < itemHeightdiv4) {
+//							// Scroll up
+//							Item item = fTableViewer.scrollUp(e.x + tableLoc.x, e.y + tableLoc.y);
+//							if (item instanceof TableItem) {
+//								fLastItem = (TableItem) item;
+//								table.setSelection(new TableItem[] { fLastItem });
+//							}
+//						} else if (e.y > tableHeight - itemHeightdiv4) {
+//							// Scroll down
+//							Item item = fTableViewer.scrollDown(e.x + tableLoc.x, e.y + tableLoc.y);
+//							if (item instanceof TableItem) {
+//								fLastItem = (TableItem) item;
+//								table.setSelection(new TableItem[] { fLastItem });
+//							}
+//						}
+//					} else if (o == null) {
+//						fLastItem = null;
+//					}
+//				}
+//			}
+//		});
+
+		table.addMouseListener(new MouseAdapter() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void mouseUp(MouseEvent e) {
+				if (table.getSelectionCount() < 1) {
+					return;
+				}
+
+				if (e.button == 1) {
+					if (table.equals(e.getSource())) {
+						Object o = table.getItem(new Point(e.x, e.y));
+						TableItem selection = table.getSelection()[0];
+						if (selection.equals(o)) {
+							gotoSelectedElement();
+						}
+					}
+				}
+				if (e.button == 3) {
+					TableItem tItem = fTableViewer.getTable().getItem(
+							new Point(e.x, e.y));
+					if (tItem != null) {
+						Menu menu = new Menu(fTableViewer.getTable());
+						MenuItem mItem = new MenuItem(menu, SWT.NONE);
+						mItem.setText(SWTRenderersMessages.menuClose);
+						mItem.addSelectionListener(new SelectionAdapter() {
+							/**
+							 *
+							 */
+							private static final long serialVersionUID = 1L;
+
+							@Override
+							public void widgetSelected(
+									SelectionEvent selectionEvent) {
+								removeSelectedItems();
+							}
+						});
+						menu.setVisible(true);
+					}
+				}
+			}
+		});
+		// FIXME RAP does not support the constants below
+//		fShell.addTraverseListener(new TraverseListener() {
+//			/**
+//			 *
+//			 */
+//			private static final long serialVersionUID = 1L;
+//
+//			@Override
+//			public void keyTraversed(TraverseEvent e) {
+//				switch (e.detail) {
+//				case SWT.TRAVERSE_PAGE_NEXT:
+//					e.detail = SWT.TRAVERSE_NONE;
+//					e.doit = true; {
+//					int n = table.getItemCount();
+//					if (n == 0)
+//						return;
+//
+//					int i = table.getSelectionIndex() + 1;
+//					if (i >= n)
+//						i = 0;
+//					table.setSelection(i);
+//				}
+//					break;
+//
+//				case SWT.TRAVERSE_PAGE_PREVIOUS:
+//					e.detail = SWT.TRAVERSE_NONE;
+//					e.doit = true; {
+//					int n = table.getItemCount();
+//					if (n == 0)
+//						return;
+//
+//					int i = table.getSelectionIndex() - 1;
+//					if (i < 0)
+//						i = n - 1;
+//					table.setSelection(i);
+//				}
+//					break;
+//				}
+//			}
+//		});
+
+		setInfoSystemColor();
+		installFilter();
+	}
+
+	/**
+	 * Removes the selected items from the list and closes their corresponding
+	 * tabs Selects the next item in the list or disposes it if its presentation
+	 * is disposed
+	 */
+	protected void removeSelectedItems() {
+		int selInd = fTableViewer.getTable().getSelectionIndex();
+		if (deleteSelectedElements()) {
+			return;
+		}
+		fTableViewer.refresh();
+		if (selInd >= fTableViewer.getTable().getItemCount()) {
+			selInd = fTableViewer.getTable().getItemCount() - 1;
+		}
+		if (selInd >= 0) {
+			fTableViewer.getTable().setSelection(selInd);
+		}
+	}
+
+	protected abstract TableViewer createTableViewer(Composite parent, int style);
+
+	public TableViewer getTableViewer() {
+		return fTableViewer;
+	}
+
+	protected Text createFilterText(Composite parent) {
+		fFilterText = new Text(parent, SWT.NONE);
+
+		GridData data = new GridData();
+		GC gc = new GC(parent);
+		gc.setFont(parent.getFont());
+		FontMetrics fontMetrics = gc.getFontMetrics();
+		gc.dispose();
+
+		data.heightHint = org.eclipse.jface.dialogs.Dialog
+				.convertHeightInCharsToPixels(fontMetrics, 1);
+		data.horizontalAlignment = GridData.FILL;
+		data.verticalAlignment = GridData.BEGINNING;
+		fFilterText.setLayoutData(data);
+
+		fFilterText.addKeyListener(new KeyListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void keyPressed(KeyEvent e) {
+				switch (e.keyCode) {
+				case SWT.CR:
+				case SWT.KEYPAD_CR:
+					gotoSelectedElement();
+					break;
+				case SWT.ARROW_DOWN:
+					fTableViewer.getTable().setFocus();
+					fTableViewer.getTable().setSelection(0);
+					break;
+				case SWT.ARROW_UP:
+					fTableViewer.getTable().setFocus();
+					fTableViewer.getTable().setSelection(
+							fTableViewer.getTable().getItemCount() - 1);
+					break;
+				case SWT.ESC:
+					dispose();
+					break;
+				}
+			}
+
+			@Override
+			public void keyReleased(KeyEvent e) {
+				// do nothing
+			}
+		});
+
+		// Horizontal separator line
+		Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+		separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		return fFilterText;
+	}
+
+	private void setInfoSystemColor() {
+		Display display = fShell.getDisplay();
+		setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+		setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+	}
+
+	private void installFilter() {
+		fFilterText.setMessage(WorkbenchSWTMessages.FilteredTree_FilterMessage);
+		fFilterText.setText(""); //$NON-NLS-1$
+
+		fFilterText.addModifyListener(new ModifyListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void modifyText(ModifyEvent e) {
+				String text = ((Text) e.widget).getText();
+				setMatcherString(text);
+			}
+		});
+	}
+
+	/**
+	 * The string matcher has been modified. The default implementation
+	 * refreshes the view and selects the first matched element
+	 */
+	private void stringMatcherUpdated() {
+		// refresh viewer to refilter
+		fTableViewer.getControl().setRedraw(false);
+		fTableViewer.refresh();
+		selectFirstMatch();
+		fTableViewer.getControl().setRedraw(true);
+	}
+
+	/**
+	 * Sets the patterns to filter out for the receiver.
+	 * <p>
+	 * The following characters have special meaning: ? => any character * =>
+	 * any string
+	 * </p>
+	 */
+	private void setMatcherString(String pattern) {
+		if (pattern.length() == 0) {
+			fSearchPattern = null;
+		} else {
+			SearchPattern patternMatcher = new SearchPattern();
+			patternMatcher.setPattern(pattern);
+			fSearchPattern = patternMatcher;
+		}
+		stringMatcherUpdated();
+	}
+
+	private SearchPattern getMatcher() {
+		return fSearchPattern;
+	}
+
+	/**
+	 * Implementers can modify
+	 */
+	protected Object getSelectedElement() {
+		return ((IStructuredSelection) fTableViewer.getSelection())
+				.getFirstElement();
+	}
+
+	protected abstract void gotoSelectedElement();
+
+	/**
+	 * Delete all selected elements.
+	 *
+	 * @return <code>true</code> if there are no elements left after deletion.
+	 */
+	protected abstract boolean deleteSelectedElements();
+
+	/**
+	 * Selects the first element in the table which matches the current filter
+	 * pattern.
+	 */
+	protected void selectFirstMatch() {
+		Table table = fTableViewer.getTable();
+		Object element = findElement(table.getItems());
+		if (element != null) {
+			fTableViewer.setSelection(new StructuredSelection(element), true);
+		} else {
+			fTableViewer.setSelection(StructuredSelection.EMPTY);
+		}
+	}
+
+	private Object findElement(TableItem[] items) {
+		ILabelProvider labelProvider = (ILabelProvider) fTableViewer
+				.getLabelProvider();
+		for (int i = 0; i < items.length; i++) {
+			Object element = items[i].getData();
+			if (fSearchPattern == null) {
+				return element;
+			}
+
+			if (element != null) {
+				String label = labelProvider.getText(element);
+				if (label == null) {
+					return null;
+				}
+				// remove the dirty prefix from the editor's label
+				if (label.startsWith("*")) { //$NON-NLS-1$
+					label = label.substring(1);
+				}
+				if (fSearchPattern.matches(label)) {
+					return element;
+				}
+			}
+		}
+		return null;
+	}
+
+	public void setVisible(boolean visible) {
+		fShell.setVisible(visible);
+	}
+
+	public void dispose() {
+		if (fShell != null) {
+			if (!fShell.isDisposed()) {
+				fShell.dispose();
+			}
+			fShell = null;
+			fTableViewer = null;
+			fComposite = null;
+			fFilterText = null;
+		}
+	}
+
+	public Point computeSizeHint() {
+		// Resize the table's height accordingly to the new input
+		Table viewerTable = fTableViewer.getTable();
+		Point tableSize = viewerTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		int tableMaxHeight = fComposite.getDisplay().getBounds().height / 2;
+		// removes padding if necessary
+		int tableHeight = (tableSize.y <= tableMaxHeight) ? tableSize.y
+				- viewerTable.getItemHeight() - viewerTable.getItemHeight() / 2
+				: tableMaxHeight;
+		((GridData) viewerTable.getLayoutData()).heightHint = tableHeight;
+		Point fCompSize = fComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		fComposite.setSize(fCompSize);
+		return fCompSize;
+	}
+
+	public void setLocation(Point location) {
+		Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
+		Point textLocation = fComposite.getLocation();
+		location.x += trim.x - textLocation.x;
+		location.y += trim.y - textLocation.y;
+		fShell.setLocation(location);
+	}
+
+	public void setSize(int width, int height) {
+		fShell.setSize(width, height);
+	}
+
+	public Shell getShell() {
+		return fShell;
+	}
+
+	private void setForegroundColor(Color foreground) {
+		fTableViewer.getTable().setForeground(foreground);
+		fFilterText.setForeground(foreground);
+		fComposite.setForeground(foreground);
+	}
+
+	private void setBackgroundColor(Color background) {
+		fTableViewer.getTable().setBackground(background);
+		fFilterText.setBackground(background);
+		fComposite.setBackground(background);
+	}
+
+	public void setFocus() {
+		fShell.forceFocus();
+		fFilterText.setFocus();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/BasicPartList.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/BasicPartList.java
new file mode 100644
index 0000000..da28f38
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/BasicPartList.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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.internal.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+
+public class BasicPartList extends AbstractTableInformationControl {
+
+	private class BasicStackListLabelProvider extends ColumnLabelProvider {
+
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+		private Font boldFont;
+
+		public BasicStackListLabelProvider() {
+			Font font = Display.getDefault().getSystemFont();
+			FontData[] fontDatas = font.getFontData();
+			for (FontData fontData : fontDatas) {
+				fontData.setStyle(fontData.getStyle() | SWT.BOLD);
+			}
+			boldFont = new Font(Display.getDefault(), fontDatas);
+		}
+
+		@Override
+		public Font getFont(Object element) {
+			if (element instanceof MPart) {
+				MPart part = (MPart) element;
+				CTabItem item = renderer.findItemForPart(part);
+				if (item != null && !item.isShowing()) {
+					return boldFont;
+				}
+			}
+			return super.getFont(element);
+		}
+
+		@Override
+		public String getText(Object element) {
+			if (element instanceof MDirtyable
+					&& ((MDirtyable) element).isDirty()) {
+				return "*" + ((MUILabel) element).getLocalizedLabel(); //$NON-NLS-1$
+			}
+			return ((MUILabel) element).getLocalizedLabel();
+		}
+
+		@Override
+		public Image getImage(Object element) {
+			return renderer.getImage((MUILabel) element);
+		}
+
+		@Override
+		public String getToolTipText(Object element) {
+			return ((MUILabel) element).getLocalizedTooltip();
+		}
+
+		@Override
+		public boolean useNativeToolTip(Object object) {
+			return true;
+		}
+
+		@Override
+		public void dispose() {
+			boldFont.dispose();
+		}
+	}
+
+	private MElementContainer<?> input;
+
+	private EPartService partService;
+
+	private StackRenderer renderer;
+
+	// private ISaveHandler saveHandler;
+
+	public BasicPartList(Shell parent, int shellStyle, int treeStyler,
+			EPartService partService, MElementContainer<?> input,
+ StackRenderer renderer, boolean mru) {
+		super(parent, shellStyle, treeStyler);
+		this.partService = partService;
+		this.input = input;
+		this.renderer = renderer;
+		// this.saveHandler = saveHandler;
+		if (mru && getTableViewer() != null) {
+			getTableViewer().setComparator(new ViewerComparator() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public int category(Object element) {
+					if (element instanceof MPart) {
+						MPart part = (MPart) element;
+						CTabItem item = BasicPartList.this.renderer.findItemForPart(part);
+						if (item != null && !item.isShowing()) {
+							return -1;
+						}
+					}
+					return 0;
+				}
+			});
+		}
+	}
+
+	@Override
+	protected TableViewer createTableViewer(Composite parent, int style) {
+		Table table = new Table(parent, SWT.SINGLE | (style & ~SWT.MULTI));
+		table.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false,
+				false));
+		TableViewer tableViewer = new TableViewer(table);
+		tableViewer.addFilter(new NamePatternFilter());
+		tableViewer.setContentProvider(ArrayContentProvider.getInstance());
+		tableViewer.setLabelProvider(new BasicStackListLabelProvider());
+
+		ColumnViewerToolTipSupport.enableFor(tableViewer);
+		return tableViewer;
+	}
+
+	private List<Object> getInput() {
+		List<Object> list = new ArrayList<Object>();
+		for (MUIElement element : input.getChildren()) {
+			if (element instanceof MPlaceholder) {
+				if (!element.isToBeRendered() || !element.isVisible()) {
+					continue;
+				}
+
+				element = ((MPlaceholder) element).getRef();
+			}
+
+			if (element.isToBeRendered() && element.isVisible()
+					&& element instanceof MPart) {
+				list.add(element);
+			}
+		}
+		return list;
+	}
+
+	public void setInput() {
+		getTableViewer().setInput(getInput());
+		selectFirstMatch();
+	}
+
+	@Override
+	protected void gotoSelectedElement() {
+		Object selectedElement = getSelectedElement();
+
+		// close the shell
+		dispose();
+
+		if (selectedElement instanceof MPart) {
+			partService.activate((MPart) selectedElement);
+		}
+	}
+
+	@Override
+	protected boolean deleteSelectedElements() {
+		Object selectedElement = getSelectedElement();
+		if (selectedElement != null) {
+			if (partService.savePart((MPart) selectedElement, true))
+				partService.hidePart((MPart) selectedElement);
+
+			if (getShell() == null) {
+				// Bug 421170: Contract says to return true if there are no
+				// elements left. In this case, there is no shell left because
+				// we popped a save dialog and auto-closed the list. Ergo, there
+				// are no elements left.
+				return true;
+			}
+			if (getInput().isEmpty()) {
+				getShell().dispose();
+				return true;
+			}
+
+			// Remove part from viewer model
+			@SuppressWarnings("unchecked")
+			List<Object> viewerInput = (List<Object>) getTableViewer()
+					.getInput();
+			viewerInput.remove(selectedElement);
+
+		}
+		return false;
+
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/IUpdateService.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/IUpdateService.java
new file mode 100644
index 0000000..5246c58
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/IUpdateService.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.renderers.swt;
+
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+
+/**
+ * A bridging interface with the 3.x ICommandService for registering element
+ * item update callbacks.
+ * <p>
+ * See bug 366568.
+ * </p>
+ */
+public interface IUpdateService {
+
+	public Runnable registerElementForUpdate(
+			ParameterizedCommand parameterizedCommand, MItem item);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersActivator.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersActivator.java
new file mode 100644
index 0000000..addc42a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersActivator.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench.renderers.swt;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Bundle activator
+ */
+public class SWTRenderersActivator implements BundleActivator {
+
+	/**
+	 * The bundle associated this plug-in
+	 */
+	private static BundleContext bundleContext;
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	@Override
+	public void start(BundleContext context) throws Exception {
+		bundleContext = context;
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		bundleContext = null;
+	}
+
+	static BundleContext getContext() {
+		return bundleContext;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersMessages.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersMessages.java
new file mode 100644
index 0000000..110fb4b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/SWTRenderersMessages.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ *     Simon Scholz <scholzsimon@arcor.de - Bug 429729
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.renderers.swt;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * SWTRenderers message catalog
+ */
+public class SWTRenderersMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.internal.workbench.renderers.swt.messages"; //$NON-NLS-1$
+
+	public static String choosePartsToSaveTitle;
+	public static String choosePartsToSave;
+
+	public static String menuClose;
+	public static String menuCloseOthers;
+	public static String menuCloseAll;
+	public static String menuCloseRight;
+	public static String menuCloseLeft;
+
+	public static String viewMenu;
+
+	public static String tabScrollingLeft;
+	public static String tabScrollingRight;
+
+	static {
+		// load message values from bundle file
+		reloadMessages();
+	}
+
+	public static void reloadMessages() {
+		NLS.initializeMessages(BUNDLE_NAME, SWTRenderersMessages.class);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/messages.properties b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/messages.properties
new file mode 100644
index 0000000..1c59155
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/internal/workbench/renderers/swt/messages.properties
@@ -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
+#     Simon Scholz <scholzsimon@arcor.de - Bug 429729
+###############################################################################
+### SWT Renderers plugin messages
+
+choosePartsToSaveTitle=Save Parts
+choosePartsToSave=Select the parts to save:
+menuClose = &Close
+menuCloseOthers = Close &Others
+menuCloseAll = Close &All
+menuCloseRight = Close Tabs to the &Right
+menuCloseLeft = Close Tabs to the &Left
+
+viewMenu = View Menu
+
+tabScrollingLeft = Scroll list left
+tabScrollingRight = Scroll list right
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/AreaRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/AreaRenderer.java
new file mode 100644
index 0000000..5fd0a1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/AreaRenderer.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.UIEvents.UIElement;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Create a contribute part.
+ */
+public class AreaRenderer extends SWTPartRenderer {
+
+	@Inject
+	private IEventBroker eventBroker;
+
+	private EventHandler itemUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MArea
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MArea))
+				return;
+
+			MArea areaModel = (MArea) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			CTabFolder ctf = (CTabFolder) areaModel.getWidget();
+			CTabItem areaItem = ctf.getItem(0);
+
+			// No widget == nothing to update
+			if (areaItem == null)
+				return;
+
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			if (UIEvents.UILabel.LABEL.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+				areaItem.setText(areaModel.getLocalizedLabel());
+			} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+				areaItem.setImage(getImage(areaModel));
+			} else if (UIEvents.UILabel.TOOLTIP.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
+				areaItem.setToolTipText(areaModel.getLocalizedTooltip());
+			}
+		}
+	};
+
+	private EventHandler widgetListener = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			final MUIElement changedElement = (MUIElement) event
+					.getProperty(EventTags.ELEMENT);
+			if (!(changedElement instanceof MPartStack))
+				return;
+
+			MArea areaModel = findArea(changedElement);
+			if (areaModel != null)
+				synchCTFState(areaModel);
+		}
+
+		private MArea findArea(MUIElement element) {
+			MUIElement parent = element.getParent();
+			while (parent != null) {
+				if (parent instanceof MArea)
+					return (MArea) parent;
+				parent = parent.getParent();
+			}
+			return null;
+		}
+	};
+
+	@PostConstruct
+	void init() {
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
+		eventBroker.subscribe(UIElement.TOPIC_WIDGET, widgetListener);
+	}
+
+	@PreDestroy
+	void contextDisposed() {
+		eventBroker.unsubscribe(itemUpdater);
+		eventBroker.unsubscribe(widgetListener);
+	}
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MArea) || !(parent instanceof Composite))
+			return null;
+
+		Composite parentComp = (Composite) parent;
+
+		Composite areaComp = new Composite(parentComp, SWT.NONE);
+		areaComp.setLayout(new FillLayout());
+
+		return areaComp;
+	}
+
+	private void ensureCTF(MArea areaModel) {
+		if (areaModel.getWidget() instanceof CTabFolder)
+			return;
+
+		Composite curComp = (Composite) areaModel.getWidget();
+		Composite parentComp = curComp.getParent();
+		CTabFolder ctf = new CTabFolder(parentComp, SWT.BORDER | SWT.SINGLE);
+
+		// Find the stack in the area that used to have the min/max state
+		List<MPartStack> stacks = modelService.findElements(areaModel, null,
+				MPartStack.class, null);
+		MPartStack curStack = null;
+		for (MPartStack stack : stacks) {
+			if (stack.isToBeRendered()
+					&& stack.getWidget() instanceof CTabFolder) {
+				CTabFolder stackCTF = (CTabFolder) stack.getWidget();
+				if (stackCTF.getMinimizeVisible()
+						|| stackCTF.getMaximizeVisible()) {
+					curStack = stack;
+					break;
+				}
+			}
+		}
+
+		// ...and copy over its min/max state
+		if (curStack != null) {
+			CTabFolder curCTF = (CTabFolder) curStack.getWidget();
+			ctf.setMinimizeVisible(curCTF.getMinimizeVisible());
+			ctf.setMaximizeVisible(curCTF.getMaximizeVisible());
+			ctf.setMinimized(curCTF.getMinimized());
+			ctf.setMaximized(curCTF.getMaximized());
+
+			curCTF.setMinimizeVisible(false);
+			curCTF.setMaximizeVisible(false);
+		}
+
+		CTabItem cti = new CTabItem(ctf, SWT.NONE);
+		if (areaModel.getLabel() != null)
+			cti.setText(areaModel.getLocalizedLabel());
+		if (areaModel.getTooltip() != null)
+			cti.setToolTipText(areaModel.getLocalizedTooltip());
+		if (areaModel.getIconURI() != null)
+			cti.setImage(getImage(areaModel));
+
+		curComp.setParent(ctf);
+		cti.setControl(curComp);
+		ctf.setSelection(cti);
+
+		curComp.setData(AbstractPartRenderer.OWNING_ME, null);
+		bindWidget(areaModel, ctf);
+		ctf.getParent().layout(null, SWT.ALL | SWT.DEFER | SWT.CHANGED);
+	}
+
+	private void ensureComposite(MArea areaModel) {
+		if (areaModel.getWidget() instanceof CTabFolder) {
+			CTabFolder ctf = (CTabFolder) areaModel.getWidget();
+			CTabItem cti = ctf.getItem(0);
+			Composite innerComp = (Composite) cti.getControl();
+			innerComp.setParent(ctf.getParent());
+			cti.setControl(null);
+
+			// OK now copy over the min/max state of the area stack to the
+			// remaining part stack
+			List<MPartStack> stacks = modelService.findElements(areaModel,
+					null, MPartStack.class, null);
+			for (MPartStack stack : stacks) {
+				if (stack.isToBeRendered()
+						&& stack.getWidget() instanceof CTabFolder) {
+					CTabFolder stackCTF = (CTabFolder) stack.getWidget();
+					stackCTF.setMinimizeVisible(ctf.getMinimizeVisible());
+					stackCTF.setMaximizeVisible(ctf.getMaximizeVisible());
+					stackCTF.setMinimized(ctf.getMinimized());
+					stackCTF.setMaximized(ctf.getMaximized());
+				}
+			}
+
+			ctf.setData(AbstractPartRenderer.OWNING_ME, null);
+			ctf.dispose();
+
+			bindWidget(areaModel, innerComp);
+			innerComp.setVisible(true);
+			innerComp.getParent().layout(true, true);
+		}
+	}
+
+	private void synchCTFState(MArea areaModel) {
+		List<MPartStack> stacks = modelService.findElements(areaModel, null,
+				MPartStack.class, null);
+		int count = 0;
+		for (MPartStack stack : stacks) {
+			if (stack.isToBeRendered())
+				count++;
+		}
+
+		// If there's more than one stack visible we use a CTF
+		if (count > 1)
+			ensureCTF(areaModel);
+		else
+			ensureComposite(areaModel);
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement element) {
+		MUIElement parentElement = element.getParent();
+
+		if (!(parentElement instanceof MArea))
+			return null;
+
+		MArea areaModel = (MArea) parentElement;
+		synchCTFState(areaModel);
+
+		if (areaModel.getWidget() instanceof CTabFolder) {
+			CTabFolder ctf = (CTabFolder) areaModel.getWidget();
+			return ctf.getItem(0).getControl();
+		}
+
+		return parentElement.getWidget();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CSSEngineHelper.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CSSEngineHelper.java
new file mode 100644
index 0000000..6eaecf0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CSSEngineHelper.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.swt.widgets.Control;
+import org.w3c.dom.css.CSSPrimitiveValue;
+import org.w3c.dom.css.CSSStyleDeclaration;
+import org.w3c.dom.css.CSSValue;
+
+/**
+ * Helper class for retrieving CSS values for a particular control so it can be
+ * used by renderers.
+ */
+public class CSSEngineHelper {
+	private IEclipseContext context;
+	private Control control;
+	private IStylingEngine engine;
+	private CSSStyleDeclaration style;
+
+	/**
+	 * Create a CSSEngineHelper that can retrieve engine values for a particular
+	 * control.
+	 *
+	 * @param context
+	 * @param control
+	 */
+	public CSSEngineHelper(IEclipseContext context, Control control) {
+		this.context = context;
+		this.control = control;
+		initialize();
+	}
+
+	private void initialize() {
+		this.engine = context.get(IStylingEngine.class);
+		if (engine != null) {
+			style = engine.getStyle(control);
+		}
+	}
+
+	/**
+	 * Return the margin bottom as specified in the stylesheet for this control,
+	 * or the defaultValue if none is specified.
+	 *
+	 * @param defaultValue
+	 * @return the margin in pixels
+	 */
+	public int getMarginBottom(int defaultValue) {
+		if (style == null)
+			return defaultValue;
+		return getPxValue(
+				style.getPropertyCSSValue("margin-bottom"), defaultValue); //$NON-NLS-1$
+	}
+
+	/**
+	 * Return the margin top as specified in the stylesheet for this control, or
+	 * the defaultValue if none is specified.
+	 *
+	 * @param defaultValue
+	 * @return the margin in pixels
+	 */
+	public int getMarginTop(int defaultValue) {
+		if (style == null)
+			return defaultValue;
+		return getPxValue(style.getPropertyCSSValue("margin-top"), defaultValue); //$NON-NLS-1$
+	}
+
+	/**
+	 * Return the margin left as specified in the stylesheet for this control,
+	 * or the defaultValue if none is specified.
+	 *
+	 * @param defaultValue
+	 * @return the margin in pixels
+	 */
+	public int getMarginLeft(int defaultValue) {
+		if (style == null)
+			return defaultValue;
+		return getPxValue(
+				style.getPropertyCSSValue("margin-left"), defaultValue); //$NON-NLS-1$
+	}
+
+	/**
+	 * Return the margin right as specified in the stylesheet for this control,
+	 * or the defaultValue if none is specified.
+	 *
+	 * @param defaultValue
+	 * @return the margin in pixels
+	 */
+	public int getMarginRight(int defaultValue) {
+		if (style == null)
+			return defaultValue;
+		return getPxValue(
+				style.getPropertyCSSValue("margin-right"), defaultValue); //$NON-NLS-1$
+	}
+
+	private int getPxValue(CSSValue value, int defaultValue) {
+		if (value != null
+				&& (value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE)
+				&& (((CSSPrimitiveValue) value).getPrimitiveType() == CSSPrimitiveValue.CSS_PX)) {
+			return (int) ((CSSPrimitiveValue) value)
+					.getFloatValue(CSSPrimitiveValue.CSS_PX);
+		}
+		return defaultValue;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java
new file mode 100644
index 0000000..4644896
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CTabRendering.java
@@ -0,0 +1,668 @@
+/*******************************************************************************
+ * 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.workbench.renderers.swt;
+
+import org.eclipse.swt.graphics.Color;
+
+//FIXME RAP Modified
+@SuppressWarnings("restriction")
+public class CTabRendering /*
+							 * extends CTabFolderRenderer implements
+							 * ICTabRendering
+							 */{
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setSelectedTabFill(
+	 * org.eclipse.swt.graphics.Color)
+	 */
+	public void setSelectedTabFill(Color color) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setTabOutline(org.eclipse
+	 * .swt.graphics.Color)
+	 */
+	public void setTabOutline(Color color) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setInnerKeyline(org
+	 * .eclipse.swt.graphics.Color)
+	 */
+	public void setInnerKeyline(Color color) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setOuterKeyline(org
+	 * .eclipse.swt.graphics.Color)
+	 */
+	public void setOuterKeyline(Color color) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setShadowColor(org.
+	 * eclipse.swt.graphics.Color)
+	 */
+	public void setShadowColor(Color color) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setActiveToolbarGradient
+	 * (org.eclipse.swt.graphics.Color[], int[])
+	 */
+	public void setActiveToolbarGradient(Color[] color, int[] percents) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setInactiveToolbarGradient
+	 * (org.eclipse.swt.graphics.Color[], int[])
+	 */
+	public void setInactiveToolbarGradient(Color[] color, int[] percents) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setCornerRadius(int)
+	 */
+	public void setCornerRadius(int radius) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.e4.ui.internal.css.swt.ICTabRendering#setShadowVisible(boolean
+	 * )
+	 */
+	public void setShadowVisible(boolean visible) {
+		// TODO Auto-generated method stub
+
+	}
+	/*
+	 * // Constants for circle drawing final static int LEFT_TOP = 0; final
+	 * static int LEFT_BOTTOM = 1; final static int RIGHT_TOP = 2; final static
+	 * int RIGHT_BOTTOM = 3;
+	 * 
+	 * // drop shadow constants final static int SIDE_DROP_WIDTH = 3; final
+	 * static int BOTTOM_DROP_WIDTH = 4;
+	 * 
+	 * // keylines final static int OUTER_KEYLINE = 1; final static int
+	 * INNER_KEYLINE = 0; final static int TOP_KEYLINE = 0;
+	 * 
+	 * // Item Constants static final int ITEM_TOP_MARGIN = 2; static final int
+	 * ITEM_BOTTOM_MARGIN = 6; static final int ITEM_LEFT_MARGIN = 4; static
+	 * final int ITEM_RIGHT_MARGIN = 4; static final int INTERNAL_SPACING = 4;
+	 * 
+	 * static final String E4_TOOLBAR_ACTIVE_IMAGE =
+	 * "org.eclipse.e4.renderer.toolbar_background_active_image"; //$NON-NLS-1$
+	 * static final String E4_TOOLBAR_INACTIVE_IMAGE =
+	 * "org.eclipse.e4.renderer.toolbar_background_inactive_image";
+	 * //$NON-NLS-1$
+	 * 
+	 * int[] shape;
+	 * 
+	 * Image shadowImage, toolbarActiveImage, toolbarInactiveImage;
+	 * 
+	 * int cornerSize = 14;
+	 * 
+	 * boolean shadowEnabled = true; Color shadowColor; Color outerKeyline,
+	 * innerKeyline; Color[] activeToolbar; int[] activePercents; Color[]
+	 * inactiveToolbar; int[] inactivePercents; boolean active; Color
+	 * selectedTabFillColor; Color tabOutlineColor;
+	 * 
+	 * int paddingLeft = 0, paddingRight = 0, paddingTop = 0, paddingBottom = 0;
+	 * 
+	 * @Inject public CTabRendering(CTabFolder parent) { super(parent); }
+	 * 
+	 * protected Rectangle computeTrim(int part, int state, int x, int y, int
+	 * width, int height) { boolean onBottom = parent.getTabPosition() ==
+	 * SWT.BOTTOM; int borderTop = onBottom ? INNER_KEYLINE + OUTER_KEYLINE :
+	 * TOP_KEYLINE + OUTER_KEYLINE; int borderBottom = onBottom ? TOP_KEYLINE +
+	 * OUTER_KEYLINE : INNER_KEYLINE + OUTER_KEYLINE; int marginWidth =
+	 * parent.marginWidth; int marginHeight = parent.marginHeight; int
+	 * sideDropWidth = shadowEnabled ? SIDE_DROP_WIDTH : 0; switch (part) { case
+	 * PART_BODY: if (state == SWT.FILL) { x = -1 - paddingLeft; int tabHeight =
+	 * parent.getTabHeight() + 1; y = onBottom ? y - paddingTop - marginHeight -
+	 * borderTop - (cornerSize / 4) : y - paddingTop - marginHeight - tabHeight
+	 * - borderTop - (cornerSize / 4); width = 2 + paddingLeft + paddingRight;
+	 * height += paddingTop + paddingBottom; height += tabHeight + (cornerSize /
+	 * 4) + borderBottom + borderTop; } else { x = x - marginWidth -
+	 * OUTER_KEYLINE - INNER_KEYLINE - sideDropWidth - (cornerSize / 2); width =
+	 * width + 2 * OUTER_KEYLINE + 2 * INNER_KEYLINE + 2 marginWidth + 2 *
+	 * sideDropWidth + cornerSize; int tabHeight = parent.getTabHeight() + 1; //
+	 * TODO: Figure out // what // to do about the // +1 // TODO: Fix if
+	 * (parent.getMinimized()) { y = onBottom ? y - borderTop - 5 : y -
+	 * tabHeight - borderTop - 5; height = borderTop + borderBottom + tabHeight;
+	 * } else { // y = tabFolder.onBottom ? y - marginHeight - //
+	 * highlight_margin // - borderTop: y - marginHeight - highlight_header - //
+	 * tabHeight // - borderTop; y = onBottom ? y - marginHeight - borderTop -
+	 * (cornerSize / 4) : y - marginHeight - tabHeight - borderTop - (cornerSize
+	 * / 4); height = height + borderBottom + borderTop + 2 marginHeight +
+	 * tabHeight + cornerSize / 2 + cornerSize / 4 + (shadowEnabled ?
+	 * BOTTOM_DROP_WIDTH : 0); } } break; case PART_HEADER: x = x -
+	 * (INNER_KEYLINE + OUTER_KEYLINE) - sideDropWidth; width = width + 2 *
+	 * (INNER_KEYLINE + OUTER_KEYLINE + sideDropWidth);
+	 * 
+	 * break; case PART_BORDER: x = x - INNER_KEYLINE - OUTER_KEYLINE -
+	 * sideDropWidth - (cornerSize / 4); width = width + 2 * (INNER_KEYLINE +
+	 * OUTER_KEYLINE + sideDropWidth) + cornerSize / 2; height = height +
+	 * borderTop + borderBottom; y = y - borderTop; if (onBottom) { if
+	 * (shadowEnabled) { height += 3; } }
+	 * 
+	 * break; default: if (0 <= part && part < parent.getItemCount()) { x = x -
+	 * ITEM_LEFT_MARGIN;// - (CORNER_SIZE/2); width = width + ITEM_LEFT_MARGIN +
+	 * ITEM_RIGHT_MARGIN + 1; y = y - ITEM_TOP_MARGIN; height = height +
+	 * ITEM_TOP_MARGIN + ITEM_BOTTOM_MARGIN; } break; } return new Rectangle(x,
+	 * y, width, height); }
+	 * 
+	 * protected Point computeSize(int part, int state, GC gc, int wHint, int
+	 * hHint) { wHint += paddingLeft + paddingRight; hHint += paddingTop +
+	 * paddingBottom; if (0 <= part && part < parent.getItemCount()) {
+	 * gc.setAdvanced(true); Point result = super.computeSize(part, state, gc,
+	 * wHint, hHint); return result; } return super.computeSize(part, state, gc,
+	 * wHint, hHint); }
+	 * 
+	 * protected void dispose() { if (shadowImage != null &&
+	 * !shadowImage.isDisposed()) { shadowImage.dispose(); shadowImage = null; }
+	 * super.dispose(); }
+	 * 
+	 * protected void draw(int part, int state, Rectangle bounds, GC gc) {
+	 * 
+	 * switch (part) { case PART_BODY: this.drawTabBody(gc, bounds, state);
+	 * return; case PART_HEADER: this.drawTabHeader(gc, bounds, state); return;
+	 * default: if (0 <= part && part < parent.getItemCount()) {
+	 * gc.setAdvanced(true); if (bounds.width == 0 || bounds.height == 0)
+	 * return; if ((state & SWT.SELECTED) != 0) { drawSelectedTab(part, gc,
+	 * bounds, state); state &= ~SWT.BACKGROUND; super.draw(part, state, bounds,
+	 * gc); } else { drawUnselectedTab(part, gc, bounds, state); if ((state &
+	 * SWT.HOT) == 0 && !active) { gc.setAlpha(0x7f); state &= ~SWT.BACKGROUND;
+	 * super.draw(part, state, bounds, gc); gc.setAlpha(0xff); } else { state &=
+	 * ~SWT.BACKGROUND; super.draw(part, state, bounds, gc); } } return; } }
+	 * super.draw(part, state, bounds, gc); }
+	 * 
+	 * void drawTabHeader(GC gc, Rectangle bounds, int state) { //
+	 * gc.setClipping(bounds.x, bounds.y, bounds.width, // parent.getTabHeight()
+	 * + 1);
+	 * 
+	 * boolean onBottom = parent.getTabPosition() == SWT.BOTTOM; int[] points =
+	 * new int[1024]; int index = 0; int radius = cornerSize / 2; int
+	 * marginWidth = parent.marginWidth; int marginHeight = parent.marginHeight;
+	 * int delta = INNER_KEYLINE + OUTER_KEYLINE + 2 (shadowEnabled ?
+	 * SIDE_DROP_WIDTH : 0) + 2 * marginWidth; int width = bounds.width - delta;
+	 * int height = bounds.height - INNER_KEYLINE - OUTER_KEYLINE - 2
+	 * marginHeight - (shadowEnabled ? BOTTOM_DROP_WIDTH : 0); int circX =
+	 * bounds.x + delta / 2 + radius; int circY = bounds.y + radius;
+	 * 
+	 * // Fill in background Region clipping = new Region();
+	 * gc.getClipping(clipping); Region region = new Region();
+	 * region.add(shape); region.intersect(clipping); gc.setClipping(region);
+	 * 
+	 * int header = shadowEnabled ? onBottom ? 6 : 3 : 1; // TODO: this needs //
+	 * to be added to // computeTrim for // HEADER Rectangle trim =
+	 * computeTrim(PART_HEADER, state, 0, 0, 0, 0); trim.width = bounds.width -
+	 * trim.width;
+	 * 
+	 * // XXX: The magic numbers need to be cleaned up. See
+	 * https://bugs.eclipse.org/425777 for details. trim.height =
+	 * (parent.getTabHeight() + (onBottom ? 7 : 4)) - trim.height;
+	 * 
+	 * trim.x = -trim.x; trim.y = onBottom ? bounds.height -
+	 * parent.getTabHeight() - 1 - header : -trim.y; draw(PART_BACKGROUND,
+	 * SWT.NONE, trim, gc);
+	 * 
+	 * gc.setClipping(clipping); clipping.dispose(); region.dispose();
+	 * 
+	 * int[] ltt = drawCircle(circX + 1, circY + 1, radius, LEFT_TOP);
+	 * System.arraycopy(ltt, 0, points, index, ltt.length); index += ltt.length;
+	 * 
+	 * int[] lbb = drawCircle(circX + 1, circY + height - (radius * 2) - 2,
+	 * radius, LEFT_BOTTOM); System.arraycopy(lbb, 0, points, index,
+	 * lbb.length); index += lbb.length;
+	 * 
+	 * int[] rb = drawCircle(circX + width - (radius * 2) - 2, circY + height -
+	 * (radius * 2) - 2, radius, RIGHT_BOTTOM); System.arraycopy(rb, 0, points,
+	 * index, rb.length); index += rb.length;
+	 * 
+	 * int[] rt = drawCircle(circX + width - (radius * 2) - 2, circY + 1,
+	 * radius, RIGHT_TOP); System.arraycopy(rt, 0, points, index, rt.length);
+	 * index += rt.length; points[index++] = points[0]; points[index++] =
+	 * points[1];
+	 * 
+	 * int[] tempPoints = new int[index]; System.arraycopy(points, 0,
+	 * tempPoints, 0, index);
+	 * 
+	 * if (outerKeyline == null) outerKeyline =
+	 * gc.getDevice().getSystemColor(SWT.COLOR_BLACK);
+	 * gc.setForeground(outerKeyline); gc.drawPolyline(shape); }
+	 * 
+	 * void drawTabBody(GC gc, Rectangle bounds, int state) { int[] points = new
+	 * int[1024]; int index = 0; int radius = cornerSize / 2; int marginWidth =
+	 * parent.marginWidth; int marginHeight = parent.marginHeight; int delta =
+	 * INNER_KEYLINE + OUTER_KEYLINE + 2 (shadowEnabled ? SIDE_DROP_WIDTH : 0) +
+	 * 2 * marginWidth; int width = bounds.width - delta; int height =
+	 * Math.max(parent.getTabHeight() + INNER_KEYLINE + OUTER_KEYLINE +
+	 * (shadowEnabled ? BOTTOM_DROP_WIDTH : 0), bounds.height - INNER_KEYLINE -
+	 * OUTER_KEYLINE - 2 marginHeight - (shadowEnabled ? BOTTOM_DROP_WIDTH :
+	 * 0));
+	 * 
+	 * int circX = bounds.x + delta / 2 + radius; int circY = bounds.y + radius;
+	 * 
+	 * // Body index = 0; int[] ltt = drawCircle(circX, circY, radius,
+	 * LEFT_TOP); System.arraycopy(ltt, 0, points, index, ltt.length); index +=
+	 * ltt.length;
+	 * 
+	 * int[] lbb = drawCircle(circX, circY + height - (radius * 2), radius,
+	 * LEFT_BOTTOM); System.arraycopy(lbb, 0, points, index, lbb.length); index
+	 * += lbb.length;
+	 * 
+	 * int[] rb = drawCircle(circX + width - (radius * 2), circY + height -
+	 * (radius * 2), radius, RIGHT_BOTTOM); System.arraycopy(rb, 0, points,
+	 * index, rb.length); index += rb.length;
+	 * 
+	 * int[] rt = drawCircle(circX + width - (radius * 2), circY, radius,
+	 * RIGHT_TOP); System.arraycopy(rt, 0, points, index, rt.length); index +=
+	 * rt.length; points[index++] = circX; points[index++] = circY - radius;
+	 * 
+	 * int[] tempPoints = new int[index]; System.arraycopy(points, 0,
+	 * tempPoints, 0, index); gc.fillPolygon(tempPoints);
+	 * 
+	 * // Fill in parent background for non-rectangular shape Region r = new
+	 * Region(); r.add(bounds); r.subtract(tempPoints);
+	 * gc.setBackground(parent.getParent().getBackground()); Display display =
+	 * parent.getDisplay(); Region clipping = new Region();
+	 * gc.getClipping(clipping); r.intersect(clipping); gc.setClipping(r);
+	 * Rectangle mappedBounds = display .map(parent, parent.getParent(),
+	 * bounds); parent.getParent().drawBackground(gc, bounds.x, bounds.y,
+	 * bounds.width, bounds.height, mappedBounds.x, mappedBounds.y);
+	 * 
+	 * // Shadow if (shadowEnabled) drawShadow(display, bounds, gc);
+	 * 
+	 * gc.setClipping(clipping); clipping.dispose(); r.dispose();
+	 * 
+	 * // Remember for use in header drawing shape = tempPoints; }
+	 * 
+	 * void drawSelectedTab(int itemIndex, GC gc, Rectangle bounds, int state) {
+	 * if (parent.getSingle() && parent.getItem(itemIndex).isShowing()) return;
+	 * 
+	 * boolean onBottom = parent.getTabPosition() == SWT.BOTTOM; int header =
+	 * shadowEnabled ? 2 : 0; int width = bounds.width; int[] points = new
+	 * int[1024]; int index = 0; int radius = cornerSize / 2; int circX =
+	 * bounds.x + radius; int circY = onBottom ? bounds.y + bounds.height + 1 -
+	 * header - radius : bounds.y - 1 + radius; int selectionX1, selectionY1,
+	 * selectionX2, selectionY2; int bottomY = onBottom ? bounds.y - header :
+	 * bounds.y + bounds.height; if (itemIndex == 0 && bounds.x ==
+	 * -computeTrim(CTabFolderRenderer.PART_HEADER, SWT.NONE, 0, 0, 0, 0).x) {
+	 * circX -= 1; points[index++] = circX - radius; points[index++] = bottomY;
+	 * 
+	 * points[index++] = selectionX1 = circX - radius; points[index++] =
+	 * selectionY1 = bottomY; } else { if (active) { points[index++] =
+	 * shadowEnabled ? SIDE_DROP_WIDTH : 0 + INNER_KEYLINE + OUTER_KEYLINE;
+	 * points[index++] = bottomY; } points[index++] = selectionX1 = bounds.x;
+	 * points[index++] = selectionY1 = bottomY; }
+	 * 
+	 * int startX = -1, endX = -1; if (!onBottom) { int[] ltt =
+	 * drawCircle(circX, circY, radius, LEFT_TOP); startX = ltt[6]; for (int i =
+	 * 0; i < ltt.length / 2; i += 2) { int tmp = ltt[i]; ltt[i] =
+	 * ltt[ltt.length - i - 2]; ltt[ltt.length - i - 2] = tmp; tmp = ltt[i + 1];
+	 * ltt[i + 1] = ltt[ltt.length - i - 1]; ltt[ltt.length - i - 1] = tmp; }
+	 * System.arraycopy(ltt, 0, points, index, ltt.length); index += ltt.length;
+	 * 
+	 * int[] rt = drawCircle(circX + width - (radius * 2), circY, radius,
+	 * RIGHT_TOP); endX = rt[rt.length - 4]; for (int i = 0; i < rt.length / 2;
+	 * i += 2) { int tmp = rt[i]; rt[i] = rt[rt.length - i - 2]; rt[rt.length -
+	 * i - 2] = tmp; tmp = rt[i + 1]; rt[i + 1] = rt[rt.length - i - 1];
+	 * rt[rt.length - i - 1] = tmp; } System.arraycopy(rt, 0, points, index,
+	 * rt.length); index += rt.length;
+	 * 
+	 * points[index++] = selectionX2 = bounds.width + circX - radius;
+	 * points[index++] = selectionY2 = bounds.y + bounds.height; } else { int[]
+	 * ltt = drawCircle(circX, circY, radius, LEFT_BOTTOM); startX = ltt[6];
+	 * System.arraycopy(ltt, 0, points, index, ltt.length); index += ltt.length;
+	 * 
+	 * int[] rt = drawCircle(circX + width - (radius * 2), circY, radius,
+	 * RIGHT_BOTTOM); endX = rt[rt.length - 4]; System.arraycopy(rt, 0, points,
+	 * index, rt.length); index += rt.length;
+	 * 
+	 * points[index++] = selectionX2 = bounds.width + circX - radius;
+	 * points[index++] = selectionY2 = bottomY; }
+	 * 
+	 * if (active) { points[index++] = parent.getSize().x - (shadowEnabled ?
+	 * SIDE_DROP_WIDTH : 0 + INNER_KEYLINE + OUTER_KEYLINE); points[index++] =
+	 * bottomY; } gc.setClipping(0, onBottom ? bounds.y - header : bounds.y,
+	 * parent.getSize().x - (shadowEnabled ? SIDE_DROP_WIDTH : 0 + INNER_KEYLINE
+	 * + OUTER_KEYLINE), bounds.y + bounds.height);// bounds.height // + // 4);
+	 * if (selectedTabFillColor == null) selectedTabFillColor =
+	 * gc.getDevice().getSystemColor( SWT.COLOR_WHITE);
+	 * gc.setBackground(selectedTabFillColor);
+	 * gc.setForeground(selectedTabFillColor); Color gradientTop = null; Pattern
+	 * backgroundPattern = null; if (!active && !onBottom) { RGB blendColor =
+	 * gc.getDevice() .getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW).getRGB();
+	 * RGB topGradient = blend(blendColor, parent.getParent()
+	 * .getBackground().getRGB(), 40); gradientTop = new Color(gc.getDevice(),
+	 * topGradient); backgroundPattern = new Pattern(gc.getDevice(), 0, 0, 0,
+	 * bounds.height + 1, gradientTop, gc.getDevice()
+	 * .getSystemColor(SWT.COLOR_WHITE));
+	 * gc.setBackgroundPattern(backgroundPattern); } int[] tmpPoints = new
+	 * int[index]; System.arraycopy(points, 0, tmpPoints, 0, index);
+	 * gc.fillPolygon(tmpPoints); gc.drawLine(selectionX1, selectionY1,
+	 * selectionX2, selectionY2); if (tabOutlineColor == null) tabOutlineColor =
+	 * gc.getDevice().getSystemColor(SWT.COLOR_BLACK);
+	 * gc.setForeground(tabOutlineColor); Color gradientLineTop = null; Pattern
+	 * foregroundPattern = null; if (!active && !onBottom) { RGB blendColor =
+	 * gc.getDevice() .getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW).getRGB();
+	 * RGB topGradient = blend(blendColor, tabOutlineColor.getRGB(), 40);
+	 * gradientLineTop = new Color(gc.getDevice(), topGradient);
+	 * foregroundPattern = new Pattern(gc.getDevice(), 0, 0, 0, bounds.height +
+	 * 1, gradientLineTop, gc.getDevice() .getSystemColor(SWT.COLOR_WHITE));
+	 * gc.setForegroundPattern(foregroundPattern); } gc.drawPolyline(tmpPoints);
+	 * Rectangle rect = null; gc.setClipping(rect);
+	 * 
+	 * if (active) { if (outerKeyline == null) outerKeyline =
+	 * gc.getDevice().getSystemColor(SWT.COLOR_RED);
+	 * gc.setForeground(outerKeyline); gc.drawPolyline(shape); } else { if
+	 * (!onBottom) { gc.drawLine(startX, 0, endX, 0); } if (gradientTop != null)
+	 * gradientTop.dispose(); if (backgroundPattern != null)
+	 * backgroundPattern.dispose(); if (gradientLineTop != null)
+	 * gradientLineTop.dispose(); if (foregroundPattern != null)
+	 * foregroundPattern.dispose();
+	 * 
+	 * } }
+	 * 
+	 * void drawUnselectedTab(int itemIndex, GC gc, Rectangle bounds, int state)
+	 * { if ((state & SWT.HOT) != 0) { int header = shadowEnabled ? 2 : 0; int
+	 * width = bounds.width; boolean onBottom = parent.getTabPosition() ==
+	 * SWT.BOTTOM; int[] points = new int[1024]; int[] inactive = new int[8];
+	 * int index = 0, inactive_index = 0; int radius = cornerSize / 2; int circX
+	 * = bounds.x + radius; int circY = onBottom ? bounds.y + bounds.height + 1
+	 * - header - radius : bounds.y - 1 + radius; int bottomY = onBottom ?
+	 * bounds.y - header : bounds.y + bounds.height;
+	 * 
+	 * int leftIndex = circX; if (itemIndex == 0) { if
+	 * (parent.getSelectionIndex() != 0) leftIndex -= 1; points[index++] =
+	 * leftIndex - radius; points[index++] = bottomY; } else { points[index++] =
+	 * bounds.x; points[index++] = bottomY; }
+	 * 
+	 * if (!active) { System.arraycopy(points, 0, inactive, 0, index);
+	 * inactive_index += 2; }
+	 * 
+	 * int rightIndex = circX - 1; if (!onBottom) { int[] ltt =
+	 * drawCircle(leftIndex, circY, radius, LEFT_TOP); for (int i = 0; i <
+	 * ltt.length / 2; i += 2) { int tmp = ltt[i]; ltt[i] = ltt[ltt.length - i -
+	 * 2]; ltt[ltt.length - i - 2] = tmp; tmp = ltt[i + 1]; ltt[i + 1] =
+	 * ltt[ltt.length - i - 1]; ltt[ltt.length - i - 1] = tmp; }
+	 * System.arraycopy(ltt, 0, points, index, ltt.length); index += ltt.length;
+	 * 
+	 * if (!active) { System.arraycopy(ltt, 0, inactive, inactive_index, 2);
+	 * inactive_index += 2; }
+	 * 
+	 * int[] rt = drawCircle(rightIndex + width - (radius * 2), circY, radius,
+	 * RIGHT_TOP); for (int i = 0; i < rt.length / 2; i += 2) { int tmp = rt[i];
+	 * rt[i] = rt[rt.length - i - 2]; rt[rt.length - i - 2] = tmp; tmp = rt[i +
+	 * 1]; rt[i + 1] = rt[rt.length - i - 1]; rt[rt.length - i - 1] = tmp; }
+	 * System.arraycopy(rt, 0, points, index, rt.length); index += rt.length; if
+	 * (!active) { System.arraycopy(rt, rt.length - 4, inactive, inactive_index,
+	 * 2); inactive[inactive_index] -= 1; inactive_index += 2; } } else { int[]
+	 * ltt = drawCircle(leftIndex, circY, radius, LEFT_BOTTOM);
+	 * System.arraycopy(ltt, 0, points, index, ltt.length); index += ltt.length;
+	 * 
+	 * if (!active) { System.arraycopy(ltt, 0, inactive, inactive_index, 2);
+	 * inactive_index += 2; }
+	 * 
+	 * int[] rt = drawCircle(rightIndex + width - (radius * 2), circY, radius,
+	 * RIGHT_BOTTOM); System.arraycopy(rt, 0, points, index, rt.length); index
+	 * += rt.length; if (!active) { System.arraycopy(rt, rt.length - 4,
+	 * inactive, inactive_index, 2); inactive[inactive_index] -= 1;
+	 * inactive_index += 2; }
+	 * 
+	 * }
+	 * 
+	 * points[index++] = bounds.width + rightIndex - radius; points[index++] =
+	 * bottomY;
+	 * 
+	 * if (!active) { System.arraycopy(points, index - 2, inactive,
+	 * inactive_index, 2); inactive[inactive_index] -= 1; inactive_index += 2; }
+	 * gc.setClipping(points[0], onBottom ? bounds.y - header : bounds.y,
+	 * parent.getSize().x - (shadowEnabled ? SIDE_DROP_WIDTH : 0 + INNER_KEYLINE
+	 * + OUTER_KEYLINE), bounds.y + bounds.height);
+	 * 
+	 * gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE)); int[]
+	 * tmpPoints = new int[index]; System.arraycopy(points, 0, tmpPoints, 0,
+	 * index); gc.fillPolygon(tmpPoints); Color tempBorder = new
+	 * Color(gc.getDevice(), 182, 188, 204); gc.setForeground(tempBorder);
+	 * tempBorder.dispose(); if (active) { gc.drawPolyline(tmpPoints); } else {
+	 * gc.drawLine(inactive[0], inactive[1], inactive[2], inactive[3]);
+	 * gc.drawLine(inactive[4], inactive[5], inactive[6], inactive[7]); }
+	 * 
+	 * Rectangle rect = null; gc.setClipping(rect);
+	 * 
+	 * if (outerKeyline == null) outerKeyline =
+	 * gc.getDevice().getSystemColor(SWT.COLOR_BLACK); //
+	 * gc.setForeground(outerKeyline); // gc.drawPolyline(shape); } }
+	 * 
+	 * static int[] drawCircle(int xC, int yC, int r, int circlePart) { int x =
+	 * 0, y = r, u = 1, v = 2 * r - 1, e = 0; int[] points = new int[1024];
+	 * int[] pointsMirror = new int[1024]; int loop = 0; int loopMirror = 0;
+	 * while (x < y) { if (circlePart == RIGHT_BOTTOM) { points[loop++] = xC +
+	 * x; points[loop++] = yC + y; } if (circlePart == RIGHT_TOP) {
+	 * points[loop++] = xC + y; points[loop++] = yC - x; } if (circlePart ==
+	 * LEFT_TOP) { points[loop++] = xC - x; points[loop++] = yC - y; } if
+	 * (circlePart == LEFT_BOTTOM) { points[loop++] = xC - y; points[loop++] =
+	 * yC + x; } x++; e += u; u += 2; if (v < 2 * e) { y--; e -= v; v -= 2; } if
+	 * (x > y) break; if (circlePart == RIGHT_BOTTOM) {
+	 * pointsMirror[loopMirror++] = xC + y; pointsMirror[loopMirror++] = yC + x;
+	 * } if (circlePart == RIGHT_TOP) { pointsMirror[loopMirror++] = xC + x;
+	 * pointsMirror[loopMirror++] = yC - y; } if (circlePart == LEFT_TOP) {
+	 * pointsMirror[loopMirror++] = xC - y; pointsMirror[loopMirror++] = yC - x;
+	 * } if (circlePart == LEFT_BOTTOM) { pointsMirror[loopMirror++] = xC - x;
+	 * pointsMirror[loopMirror++] = yC + y; } // grow? if ((loop + 1) >
+	 * points.length) { int length = points.length * 2; int[] newPointTable =
+	 * new int[length]; int[] newPointTableMirror = new int[length];
+	 * System.arraycopy(points, 0, newPointTable, 0, points.length); points =
+	 * newPointTable; System.arraycopy(pointsMirror, 0, newPointTableMirror, 0,
+	 * pointsMirror.length); pointsMirror = newPointTableMirror; } } int[]
+	 * finalArray = new int[loop + loopMirror]; System.arraycopy(points, 0,
+	 * finalArray, 0, loop); for (int i = loopMirror - 1, j = loop; i > 0; i = i
+	 * - 2, j = j + 2) { int tempY = pointsMirror[i]; int tempX = pointsMirror[i
+	 * - 1]; finalArray[j] = tempX; finalArray[j + 1] = tempY; } return
+	 * finalArray; }
+	 * 
+	 * static RGB blend(RGB c1, RGB c2, int ratio) { int r = blend(c1.red,
+	 * c2.red, ratio); int g = blend(c1.green, c2.green, ratio); int b =
+	 * blend(c1.blue, c2.blue, ratio); return new RGB(r, g, b); }
+	 * 
+	 * static int blend(int v1, int v2, int ratio) { int b = (ratio * v1 + (100
+	 * - ratio) * v2) / 100; return Math.min(255, b); }
+	 * 
+	 * void drawShadow(final Display display, Rectangle bounds, GC gc) { if
+	 * (shadowImage == null) { createShadow(display); } int x = bounds.x; int y
+	 * = bounds.y; int SIZE = shadowImage.getBounds().width / 3;
+	 * 
+	 * int height = Math.max(bounds.height, SIZE * 2); int width =
+	 * Math.max(bounds.width, SIZE * 2); // top left gc.drawImage(shadowImage,
+	 * 0, 0, SIZE, SIZE, 2, 10, SIZE, 20); int fillHeight = height - SIZE * 2;
+	 * int fillWidth = width + 5 - SIZE * 2;
+	 * 
+	 * int xFill = 0; for (int i = SIZE; i < fillHeight; i += SIZE) { xFill = i;
+	 * gc.drawImage(shadowImage, 0, SIZE, SIZE, SIZE, 2, i, SIZE, SIZE); }
+	 * 
+	 * // Pad the rest of the shadow gc.drawImage(shadowImage, 0, SIZE, SIZE,
+	 * fillHeight - xFill, 2, xFill + SIZE, SIZE, fillHeight - xFill);
+	 * 
+	 * // bl gc.drawImage(shadowImage, 0, 40, 20, 20, 2, y + height - SIZE, 20,
+	 * 20);
+	 * 
+	 * int yFill = 0; for (int i = SIZE; i <= fillWidth; i += SIZE) { yFill = i;
+	 * gc.drawImage(shadowImage, SIZE, SIZE * 2, SIZE, SIZE, i, y + height -
+	 * SIZE, SIZE, SIZE); } // Pad the rest of the shadow
+	 * gc.drawImage(shadowImage, SIZE, SIZE * 2, fillWidth - yFill, SIZE, yFill
+	 * + SIZE, y + height - SIZE, fillWidth - yFill, SIZE);
+	 * 
+	 * // br gc.drawImage(shadowImage, SIZE * 2, SIZE * 2, SIZE, SIZE, x + width
+	 * - SIZE - 1, y + height - SIZE, SIZE, SIZE);
+	 * 
+	 * // tr gc.drawImage(shadowImage, (SIZE * 2), 0, SIZE, SIZE, x + width -
+	 * SIZE - 1, 10, SIZE, SIZE);
+	 * 
+	 * xFill = 0; for (int i = SIZE; i < fillHeight; i += SIZE) { xFill = i;
+	 * gc.drawImage(shadowImage, SIZE * 2, SIZE, SIZE, SIZE, x + width - SIZE -
+	 * 1, i, SIZE, SIZE); }
+	 * 
+	 * // Pad the rest of the shadow gc.drawImage(shadowImage, SIZE * 2, SIZE,
+	 * SIZE, fillHeight - xFill, x + width - SIZE - 1, xFill + SIZE, SIZE,
+	 * fillHeight - xFill); }
+	 * 
+	 * void createShadow(final Display display) { if (shadowImage != null) {
+	 * shadowImage.dispose(); shadowImage = null; } ImageData data = new
+	 * ImageData(60, 60, 32, new PaletteData(0xFF0000, 0xFF00, 0xFF)); Image
+	 * tmpImage = shadowImage = new Image(display, data); GC gc = new
+	 * GC(tmpImage); if (shadowColor == null) shadowColor =
+	 * gc.getDevice().getSystemColor(SWT.COLOR_GRAY);
+	 * gc.setBackground(shadowColor); drawTabBody(gc, new Rectangle(0, 0, 60,
+	 * 60), SWT.None); ImageData blured = blur(tmpImage, 5, 25); shadowImage =
+	 * new Image(display, blured); tmpImage.dispose(); }
+	 * 
+	 * public ImageData blur(Image src, int radius, int sigma) { float[] kernel
+	 * = create1DKernel(radius, sigma);
+	 * 
+	 * ImageData imgPixels = src.getImageData(); int width = imgPixels.width;
+	 * int height = imgPixels.height;
+	 * 
+	 * int[] inPixels = new int[width * height]; int[] outPixels = new int[width
+	 * * height]; int offset = 0; for (int y = 0; y < height; y++) { for (int x
+	 * = 0; x < width; x++) { RGB rgb =
+	 * imgPixels.palette.getRGB(imgPixels.getPixel(x, y)); if (rgb.red == 255 &&
+	 * rgb.green == 255 && rgb.blue == 255) { inPixels[offset] = (rgb.red << 16)
+	 * | (rgb.green << 8) | rgb.blue; } else { inPixels[offset] =
+	 * (imgPixels.getAlpha(x, y) << 24) | (rgb.red << 16) | (rgb.green << 8) |
+	 * rgb.blue; } offset++; } }
+	 * 
+	 * convolve(kernel, inPixels, outPixels, width, height, true);
+	 * convolve(kernel, outPixels, inPixels, height, width, true);
+	 * 
+	 * ImageData dst = new ImageData(imgPixels.width, imgPixels.height, 24, new
+	 * PaletteData(0xff0000, 0xff00, 0xff));
+	 * 
+	 * dst.setPixels(0, 0, inPixels.length, inPixels, 0); offset = 0; for (int y
+	 * = 0; y < height; y++) { for (int x = 0; x < width; x++) { if
+	 * (inPixels[offset] == -1) { dst.setAlpha(x, y, 0); } else { int a =
+	 * (inPixels[offset] >> 24) & 0xff; // if (a < 150) a = 0; dst.setAlpha(x,
+	 * y, a); } offset++; } } return dst; }
+	 * 
+	 * private void convolve(float[] kernel, int[] inPixels, int[] outPixels,
+	 * int width, int height, boolean alpha) { int kernelWidth = kernel.length;
+	 * int kernelMid = kernelWidth / 2; for (int y = 0; y < height; y++) { int
+	 * index = y; int currentLine = y * width; for (int x = 0; x < width; x++) {
+	 * // do point float a = 0, r = 0, g = 0, b = 0; for (int k = -kernelMid; k
+	 * <= kernelMid; k++) { float val = kernel[k + kernelMid]; int xcoord = x +
+	 * k; if (xcoord < 0) xcoord = 0; if (xcoord >= width) xcoord = width - 1;
+	 * int pixel = inPixels[currentLine + xcoord]; // float alp = ((pixel >> 24)
+	 * & 0xff); a += val * ((pixel >> 24) & 0xff); r += val * (((pixel >> 16) &
+	 * 0xff)); g += val * (((pixel >> 8) & 0xff)); b += val * (((pixel) &
+	 * 0xff)); } int ia = alpha ? clamp((int) (a + 0.5)) : 0xff; int ir =
+	 * clamp((int) (r + 0.5)); int ig = clamp((int) (g + 0.5)); int ib =
+	 * clamp((int) (b + 0.5)); outPixels[index] = (ia << 24) | (ir << 16) | (ig
+	 * << 8) | ib; index += height; } }
+	 * 
+	 * }
+	 * 
+	 * private int clamp(int value) { if (value > 255) return 255; if (value <
+	 * 0) return 0; return value; }
+	 * 
+	 * private float[] create1DKernel(int radius, int sigma) { // guideline:
+	 * 3*sigma should be the radius int size = radius * 2 + 1; float[] kernel =
+	 * new float[size]; int radiusSquare = radius * radius; float sigmaSquare =
+	 * 2 * sigma * sigma; float piSigma = 2 * (float) Math.PI * sigma; float
+	 * sqrtSigmaPi2 = (float) Math.sqrt(piSigma); int start = size / 2; int
+	 * index = 0; float total = 0; for (int i = -start; i <= start; i++) { float
+	 * d = i * i; if (d > radiusSquare) { kernel[index] = 0; } else {
+	 * kernel[index] = (float) Math.exp(-(d) / sigmaSquare) / sqrtSigmaPi2; }
+	 * total += kernel[index]; index++; } for (int i = 0; i < size; i++) {
+	 * kernel[i] /= total; } return kernel; }
+	 * 
+	 * public Rectangle getPadding() { return new Rectangle(paddingTop,
+	 * paddingRight, paddingBottom, paddingLeft); }
+	 * 
+	 * public void setPadding(int paddingLeft, int paddingRight, int paddingTop,
+	 * int paddingBottom) { this.paddingLeft = paddingLeft; this.paddingRight =
+	 * paddingRight; this.paddingTop = paddingTop; this.paddingBottom =
+	 * paddingBottom; parent.redraw(); }
+	 * 
+	 * public void setCornerRadius(int radius) { cornerSize = radius;
+	 * parent.redraw(); }
+	 * 
+	 * public void setShadowVisible(boolean visible) { this.shadowEnabled =
+	 * visible; parent.redraw(); }
+	 * 
+	 * public void setShadowColor(Color color) { this.shadowColor = color;
+	 * createShadow(parent.getDisplay()); parent.redraw(); }
+	 * 
+	 * public void setOuterKeyline(Color color) { this.outerKeyline = color; //
+	 * TODO: HACK! Should be set based on pseudo-state. if (color != null) {
+	 * setActive(!(color.getRed() == 255 && color.getGreen() == 255 && color
+	 * .getBlue() == 255)); } parent.redraw(); }
+	 * 
+	 * public void setSelectedTabFill(Color color) { this.selectedTabFillColor =
+	 * color; parent.redraw(); }
+	 * 
+	 * public void setTabOutline(Color color) { this.tabOutlineColor = color;
+	 * parent.redraw(); }
+	 * 
+	 * public void setInnerKeyline(Color color) { this.innerKeyline = color;
+	 * parent.redraw(); }
+	 * 
+	 * public void setActiveToolbarGradient(Color[] color, int[] percents) {
+	 * activeToolbar = color; activePercents = percents; }
+	 * 
+	 * public void setInactiveToolbarGradient(Color[] color, int[] percents) {
+	 * inactiveToolbar = color; inactivePercents = percents; }
+	 * 
+	 * public void setActive(boolean active) { this.active = active; }
+	 */
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CompositeRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CompositeRenderer.java
new file mode 100644
index 0000000..ef2e2c1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/CompositeRenderer.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+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.ToolBar;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Factory for <code>org.eclipse.e4.workbench.emf.workbench.Composite</code>
+ */
+public class CompositeRenderer extends SWTPartRenderer {
+
+	public CompositeRenderer() {
+		super();
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MPart) || !(parent instanceof Composite))
+			return null;
+
+		final Widget parentWidget = (Widget) parent;
+		String policy = "VerticalComposite"; //compositeModel.getPolicy(); //$NON-NLS-1$
+
+		if (policy != null && (policy.equals("HorizontalComposite") //$NON-NLS-1$
+				|| policy.equals("VerticalComposite"))) { //$NON-NLS-1$
+			return new Composite((Composite) parentWidget, SWT.NONE);
+		}
+
+		return null;
+	}
+
+	@Override
+	public void postProcess(MUIElement element) {
+		super.postProcess(element);
+
+		String policy = "VerticalComposite"; //compositeModel.getPolicy(); //$NON-NLS-1$
+		if (policy != null && policy.endsWith("Composite")) { //$NON-NLS-1$
+			Composite composite = (Composite) element.getWidget();
+			Control[] children = composite.getChildren();
+			GridLayout gl = new GridLayout(
+					policy.startsWith("Horizontal") ? children.length : 1, false); //$NON-NLS-1$
+			gl.horizontalSpacing = 0;
+			gl.verticalSpacing = 0;
+			gl.marginHeight = 0;
+			gl.marginWidth = 0;
+			composite.setLayout(gl);
+			for (int i = 0; i < children.length; i++) {
+				Control child = children[i];
+				boolean grabV = !(child instanceof ToolBar);
+				boolean grabH = !(child instanceof ToolBar);
+				child.setLayoutData(new GridData(SWT.FILL, SWT.FILL, grabH,
+						grabV));
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributedPartRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributedPartRenderer.java
new file mode 100644
index 0000000..3a2c8bb
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributedPartRenderer.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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@vogella.com> - Bug 426460, 441150
+ *     Andrey Loskutov <loskutov@gmx.de> - Bug 466524
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+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.workbench.IPresentationEngine;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Default SWT renderer responsible for an MPart. See
+ * {@link WorkbenchRendererFactory}
+ */
+public class ContributedPartRenderer extends SWTPartRenderer {
+
+	@Inject
+	private IPresentationEngine engine;
+
+	@Inject
+	@Optional
+	private Logger logger;
+
+	private MPart partToActivate;
+
+	private Listener activationListener = new Listener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void handleEvent(Event event) {
+			// we only want to activate the part if the activated widget is
+			// actually bound to a model element
+			MPart part = (MPart) event.widget.getData(OWNING_ME);
+			if (part != null) {
+				try {
+					partToActivate = part;
+					activate(partToActivate);
+				} finally {
+					partToActivate = null;
+				}
+			}
+		}
+	};
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MPart) || !(parent instanceof Composite))
+			return null;
+
+		Widget parentWidget = (Widget) parent;
+		Widget newWidget = null;
+		final MPart part = (MPart) element;
+
+		final Composite newComposite = new Composite((Composite) parentWidget,
+				SWT.NONE) {
+
+			/**
+					 *
+					 */
+			private static final long serialVersionUID = 1L;
+			/**
+			 * Field to determine whether we are currently in the midst of
+			 * granting focus to the part.
+			 */
+			private boolean beingFocused = false;
+
+			@Override
+			public boolean setFocus() {
+				if (!beingFocused) {
+					try {
+						// we are currently asking the part to take focus
+						beingFocused = true;
+
+						// delegate an attempt to set the focus here to the
+						// part's implementation (if there is one)
+						Object object = part.getObject();
+						if (object != null && isEnabled()) {
+							IPresentationEngine pe = part.getContext().get(
+									IPresentationEngine.class);
+							pe.focusGui(part);
+							return true;
+						}
+						return super.setFocus();
+					} finally {
+						// we are done, unset our flag
+						beingFocused = false;
+					}
+				}
+
+				// already being focused, likely some strange recursive call,
+				// just return
+				return true;
+			}
+		};
+
+		newComposite.setLayout(new FillLayout(SWT.VERTICAL));
+
+		newWidget = newComposite;
+		bindWidget(element, newWidget);
+
+		// Create a context for this part
+		IEclipseContext localContext = part.getContext();
+		localContext.set(Composite.class, newComposite);
+
+		IContributionFactory contributionFactory = localContext.get(IContributionFactory.class);
+		Object newPart = contributionFactory.create(part.getContributionURI(),
+				localContext);
+		part.setObject(newPart);
+
+		return newWidget;
+	}
+
+	/**
+	 * @param part
+	 * @param description
+	 */
+	public static void setDescription(MPart part, String description) {
+		if (!(part.getWidget() instanceof Composite))
+			return;
+
+		Composite c = (Composite) part.getWidget();
+
+		// Do we already have a label?
+		if (c.getChildren().length == 3) {
+			Label label = (Label) c.getChildren()[0];
+			if (description == null)
+				description = ""; //$NON-NLS-1$
+			// hide the label if there is no text to show
+			boolean hasText = !description.equals(""); //$NON-NLS-1$
+			label.setVisible(hasText);
+			label.setText(description);
+			label.setToolTipText(description);
+
+			// also hide the separator
+			c.getChildren()[1].setVisible(hasText);
+			c.layout();
+		} else if (c.getChildren().length == 1) {
+			c.setLayout(new Layout() {
+
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				protected Point computeSize(Composite composite, int wHint,
+						int hHint, boolean flushCache) {
+					return new Point(0, 0);
+				}
+
+				@Override
+				protected void layout(Composite composite, boolean flushCache) {
+					Rectangle bounds = composite.getBounds();
+					if (composite.getChildren().length == 1) {
+						composite.getChildren()[0].setBounds(composite
+								.getBounds());
+					} else if (composite.getChildren().length == 3) {
+						Label label = (Label) composite.getChildren()[0];
+						Label separator = (Label) composite.getChildren()[1];
+						Control partCtrl = composite.getChildren()[2];
+
+						// if the label is empty, give it a zero size
+						int labelHeight = !label.getText().isEmpty() ? label
+								.computeSize(bounds.width, SWT.DEFAULT).y : 0;
+						label.setBounds(0, 0, bounds.width, labelHeight);
+
+						int separatorHeight = labelHeight > 0 ? separator
+								.computeSize(bounds.width, SWT.DEFAULT).y : 0;
+						separator.setBounds(0, labelHeight, bounds.width,
+								separatorHeight);
+
+						partCtrl.setBounds(0, labelHeight + separatorHeight,
+								bounds.width, bounds.height - labelHeight
+										- separatorHeight);
+					}
+				}
+			});
+
+			Label separator = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
+			separator.moveAbove(null);
+			Label label = new Label(c, SWT.NONE);
+			label.setText(description);
+			label.setToolTipText(description);
+			label.moveAbove(null);
+			c.layout();
+		}
+	}
+
+	@Override
+	protected boolean requiresFocus(MPart element) {
+		if (element == partToActivate) {
+			return true;
+		}
+		return super.requiresFocus(element);
+	}
+
+	@Override
+	public void hookControllerLogic(final MUIElement me) {
+		super.hookControllerLogic(me);
+		if (!(me instanceof MPart)) {
+			return;
+		}
+		Widget widget = (Widget) me.getWidget();
+		if (widget instanceof Composite) {
+			widget.addListener(SWT.Activate, activationListener);
+		}
+
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement element) {
+		if (element instanceof MToolBar) {
+			MUIElement container = (MUIElement) ((EObject) element)
+					.eContainer();
+			MUIElement parent = container.getParent();
+			if (parent == null) {
+				MPlaceholder placeholder = container.getCurSharedRef();
+				if (placeholder != null) {
+					return placeholder.getParent().getWidget();
+				}
+			} else {
+				return parent.getWidget();
+			}
+		}
+		return super.getUIContainer(element);
+	}
+
+	@Override
+	public void disposeWidget(MUIElement element) {
+		if (element instanceof MPart) {
+			MPart part = (MPart) element;
+			MToolBar toolBar = part.getToolbar();
+			if (toolBar != null) {
+				Widget widget = (Widget) toolBar.getWidget();
+				if (widget != null) {
+					unbindWidget(toolBar);
+					widget.dispose();
+				}
+			}
+
+			for (MMenu menu : part.getMenus()) {
+				engine.removeGui(menu);
+			}
+		}
+
+		Composite parent = null;
+		if (element.getWidget() instanceof Composite) {
+			parent = ((Composite) element.getWidget()).getParent();
+		}
+
+		if (parent != null) {
+			try {
+				parent.setRedraw(false);
+				super.disposeWidget(element);
+			} finally {
+				parent.setRedraw(true);
+			}
+		} else {
+			super.disposeWidget(element);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java
new file mode 100644
index 0000000..5fd1eb0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.core.internal.expressions.OrExpression;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MExpression;
+import org.eclipse.e4.ui.model.application.ui.impl.UiFactoryImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.action.MenuManager;
+
+public class ContributionRecord {
+	public static final String FACTORY = "ContributionFactory"; //$NON-NLS-1$
+	static final String STATIC_CONTEXT = "ContributionFactoryContext"; //$NON-NLS-1$
+
+	MMenu menuModel;
+	private MMenuContribution menuContribution;
+	private ArrayList<MMenuElement> generatedElements = new ArrayList<MMenuElement>();
+	private HashSet<MMenuElement> sharedElements = new HashSet<MMenuElement>();
+	private MenuManagerRenderer renderer;
+	boolean isVisible = true;
+	private IEclipseContext infoContext;
+	private Runnable factoryDispose;
+
+	public ContributionRecord(MMenu menuModel, MMenuContribution contribution,
+			MenuManagerRenderer renderer) {
+		this.menuModel = menuModel;
+		this.menuContribution = contribution;
+		this.renderer = renderer;
+	}
+
+	public MenuManager getManagerForModel() {
+		return renderer.getManager(menuModel);
+	}
+
+	public MMenuContribution getMenuContribution() {
+		return menuContribution;
+	}
+
+	/**
+	 * Access to analyze for tests. For Looking, not touching!
+	 *
+	 * @return the shared elements collection
+	 */
+	public Collection<MMenuElement> getSharedElements() {
+		return sharedElements;
+	}
+
+	/**
+	 * Access to analyze for tests. For Looking, not touching!
+	 *
+	 * @return the generated elements collection
+	 */
+	public Collection<MMenuElement> getGeneratedElements() {
+		return generatedElements;
+	}
+
+	/**
+	 * @param context
+	 */
+	public void updateVisibility(IEclipseContext context) {
+		ExpressionContext exprContext = new ExpressionContext(context);
+		updateIsVisible(exprContext);
+		HashSet<ContributionRecord> recentlyUpdated = new HashSet<ContributionRecord>();
+		recentlyUpdated.add(this);
+		boolean changed = false;
+		for (MMenuElement item : generatedElements) {
+			boolean currentVisibility = computeVisibility(recentlyUpdated,
+					item, exprContext);
+			if (item.isVisible() != currentVisibility) {
+				changed = true;
+				item.setVisible(currentVisibility);
+			}
+		}
+		for (MMenuElement item : sharedElements) {
+			boolean currentVisibility = computeVisibility(recentlyUpdated,
+					item, exprContext);
+			if (item.isVisible() != currentVisibility) {
+				changed = true;
+				item.setVisible(currentVisibility);
+			}
+		}
+
+		if (changed) {
+			MenuManager manager = getManagerForModel();
+			if (manager != null) {
+				manager.markDirty();
+			}
+		}
+	}
+
+	public void collectInfo(ExpressionInfo info) {
+		ContributionsAnalyzer.collectInfo(info,
+				menuContribution.getVisibleWhen());
+		for (MMenuElement item : generatedElements) {
+			ContributionsAnalyzer.collectInfo(info, item.getVisibleWhen());
+		}
+		for (MMenuElement item : sharedElements) {
+			ContributionsAnalyzer.collectInfo(info, item.getVisibleWhen());
+		}
+	}
+
+	public void updateIsVisible(ExpressionContext exprContext) {
+		isVisible = ContributionsAnalyzer.isVisible(menuContribution,
+				exprContext);
+	}
+
+	public boolean computeVisibility(
+			HashSet<ContributionRecord> recentlyUpdated, MMenuElement item,
+			ExpressionContext exprContext) {
+		boolean currentVisibility = isVisible;
+		if (item instanceof MMenu || item instanceof MMenuSeparator) {
+			ArrayList<ContributionRecord> list = renderer.getList(item);
+			if (list != null) {
+				Iterator<ContributionRecord> cr = list.iterator();
+				while (!currentVisibility && cr.hasNext()) {
+					ContributionRecord rec = cr.next();
+					if (!recentlyUpdated.contains(rec)) {
+						rec.updateIsVisible(exprContext);
+						recentlyUpdated.add(rec);
+					}
+					currentVisibility |= rec.isVisible;
+				}
+			}
+		}
+		if (currentVisibility
+				&& item.getPersistedState().get(
+						MenuManagerRenderer.VISIBILITY_IDENTIFIER) != null) {
+			String identifier = item.getPersistedState().get(
+					MenuManagerRenderer.VISIBILITY_IDENTIFIER);
+			Object rc = exprContext.eclipseContext.get(identifier);
+			if (rc instanceof Boolean) {
+				currentVisibility = ((Boolean) rc).booleanValue();
+			}
+		}
+		if (currentVisibility
+				&& item.getVisibleWhen() instanceof MCoreExpression) {
+			boolean val = ContributionsAnalyzer.isVisible(
+					(MCoreExpression) item.getVisibleWhen(), exprContext);
+			currentVisibility = val;
+		}
+		return currentVisibility;
+	}
+
+	private Expression getExpression(MExpression expression) {
+		if (expression instanceof MCoreExpression) {
+			Object coreExpression = ((MCoreExpression) expression)
+					.getCoreExpression();
+			return coreExpression instanceof Expression ? (Expression) coreExpression
+					: null;
+		}
+		return null;
+	}
+
+	private MExpression merge(MExpression expressionA, MExpression expressionB) {
+		Expression coreExpressionA = getExpression(expressionA);
+		Expression coreExpressionB = getExpression(expressionB);
+		if (coreExpressionA == null || coreExpressionB == null) {
+			// implied to always be visible
+			return null;
+		}
+		if (coreExpressionA.equals(coreExpressionB)) {
+			return expressionA;
+		}
+
+		// combine the two expressions
+		OrExpression expression = new OrExpression();
+		expression.add(coreExpressionA);
+		expression.add(coreExpressionB);
+
+		MCoreExpression exp = UiFactoryImpl.eINSTANCE.createCoreExpression();
+		exp.setCoreExpressionId("programmatic.value"); //$NON-NLS-1$
+		exp.setCoreExpression(expression);
+		return exp;
+	}
+
+	public boolean mergeIntoModel() {
+		int idx = getIndex(menuModel, menuContribution.getPositionInParent());
+		if (idx == -1) {
+			return false;
+		}
+
+		final List<MMenuElement> copyElements;
+		if (menuContribution.getTransientData().get(FACTORY) != null) {
+			copyElements = mergeFactoryIntoModel();
+		} else {
+			copyElements = new ArrayList<MMenuElement>();
+			for (MMenuElement item : menuContribution.getChildren()) {
+				MMenuElement copy = (MMenuElement) EcoreUtil
+						.copy((EObject) item);
+				copyElements.add(copy);
+			}
+		}
+
+		for (MMenuElement copy : copyElements) {
+			if (copy instanceof MMenu) {
+				MMenu shared = findExistingMenu(copy.getElementId());
+				if (shared == null) {
+					shared = (MMenu) copy;
+					renderer.linkElementToContributionRecord(copy, this);
+					menuModel.getChildren().add(idx++, copy);
+				} else {
+					shared.setVisibleWhen(merge(copy.getVisibleWhen(),
+							shared.getVisibleWhen()));
+					copy = shared;
+				}
+				sharedElements.add(shared);
+			} else if (copy instanceof MMenuSeparator) {
+				MMenuSeparator shared = findExistingSeparator(copy
+						.getElementId());
+				if (shared == null) {
+					shared = (MMenuSeparator) copy;
+					renderer.linkElementToContributionRecord(copy, this);
+					menuModel.getChildren().add(idx++, copy);
+				} else {
+					copy = shared;
+				}
+				sharedElements.add(shared);
+			} else {
+				generatedElements.add(copy);
+				renderer.linkElementToContributionRecord(copy, this);
+				menuModel.getChildren().add(idx++, copy);
+			}
+			if (copy instanceof MMenu || copy instanceof MMenuSeparator) {
+				renderer.addRecord(copy, this);
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * @return
+	 */
+	private List<MMenuElement> mergeFactoryIntoModel() {
+		Object obj = menuContribution.getTransientData().get(FACTORY);
+		if (!(obj instanceof IContextFunction)) {
+			return Collections.EMPTY_LIST;
+		}
+		IEclipseContext staticContext = getStaticContext();
+		staticContext.remove(List.class);
+		factoryDispose = (Runnable) ((IContextFunction) obj).compute(
+				staticContext, null);
+		return staticContext.get(List.class);
+	}
+
+	private IEclipseContext getStaticContext() {
+		if (infoContext == null) {
+			IEclipseContext parentContext = renderer.getContext(menuModel);
+			if (parentContext != null) {
+				infoContext = parentContext.createChild(STATIC_CONTEXT);
+			} else {
+				infoContext = EclipseContextFactory.create(STATIC_CONTEXT);
+			}
+			ContributionsAnalyzer.populateModelInterfaces(menuModel,
+					infoContext, menuModel.getClass().getInterfaces());
+			infoContext.set(MenuManagerRenderer.class, renderer);
+		}
+		return infoContext;
+	}
+
+	MMenu findExistingMenu(String id) {
+		if (id == null) {
+			return null;
+		}
+		for (MMenuElement item : menuModel.getChildren()) {
+			if (item instanceof MMenu && id.equals(item.getElementId())) {
+				return (MMenu) item;
+			}
+		}
+		return null;
+	}
+
+	MMenuSeparator findExistingSeparator(String id) {
+		if (id == null) {
+			return null;
+		}
+		for (MMenuElement item : menuModel.getChildren()) {
+			if (item instanceof MMenuSeparator
+					&& id.equals(item.getElementId())) {
+				return (MMenuSeparator) item;
+			}
+		}
+		return null;
+	}
+
+	public void dispose() {
+		for (MMenuElement copy : generatedElements) {
+			menuModel.getChildren().remove(copy);
+		}
+		for (MMenuElement shared : sharedElements) {
+			renderer.removeRecord(shared, this);
+			ArrayList<ContributionRecord> array = renderer.getList(shared);
+			if (array.isEmpty()) {
+				menuModel.getChildren().remove(shared);
+			}
+		}
+		if (factoryDispose != null) {
+			factoryDispose.run();
+			factoryDispose = null;
+		}
+	}
+
+	private static int getIndex(MElementContainer<?> menuModel,
+			String positionInParent) {
+		String id = null;
+		String modifier = null;
+		if (positionInParent != null && positionInParent.length() > 0) {
+			String[] array = positionInParent.split("="); //$NON-NLS-1$
+			modifier = array[0];
+			id = array[1];
+		}
+		if (id == null) {
+			return menuModel.getChildren().size();
+		}
+
+		int idx = 0;
+		int size = menuModel.getChildren().size();
+		while (idx < size) {
+			if (id.equals(menuModel.getChildren().get(idx).getElementId())) {
+				if ("after".equals(modifier)) { //$NON-NLS-1$
+					idx++;
+				} else if ("endof".equals(modifier)) { //$NON-NLS-1$
+					// Skip current menu item
+					idx++;
+
+					// Skip all menu items until next MenuSeparator is found
+					while (idx < size
+							&& !(menuModel.getChildren().get(idx) instanceof MMenuSeparator && menuModel
+									.getChildren().get(idx).getElementId() != null)) {
+						idx++;
+					}
+				}
+				return idx;
+			}
+			idx++;
+		}
+		return id.equals("additions") ? menuModel.getChildren().size() : -1; //$NON-NLS-1$
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectContributionItem.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectContributionItem.java
new file mode 100644
index 0000000..5837c50
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectContributionItem.java
@@ -0,0 +1,575 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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
+ *     Joseph Carroll <jdsalingerjr@gmail.com> - Bug 385414 Contributing wizards
+ *     to toolbar always displays icon and text
+ *     Bruce Skingle <Bruce.Skingle@immutify.com> - Bug 443092
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.MContribution;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.resource.DeviceResourceException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+
+public class DirectContributionItem extends ContributionItem {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/** Internal key for transient maps to provide a runnable on widget disposal */
+	public static final String DISPOSABLE = "IDisposable"; //$NON-NLS-1$
+
+	private static final String FORCE_TEXT = "FORCE_TEXT"; //$NON-NLS-1$
+	private static final String ICON_URI = "iconURI"; //$NON-NLS-1$
+	private static final String DISABLED_URI = "disabledURI"; //$NON-NLS-1$
+	private static final String DCI_STATIC_CONTEXT = "DCI-staticContext"; //$NON-NLS-1$
+
+	private static final Object missingExecute = new Object();
+
+	private MItem model;
+	private Widget widget;
+	private Listener menuItemListener;
+	private LocalResourceManager localResourceManager;
+	private IEclipseContext infoContext;
+
+	@Inject
+	private IContributionFactory contribFactory;
+
+	@Inject
+	private EModelService modelService;
+
+	private ISWTResourceUtilities resUtils = null;
+
+	@Inject
+	void setResourceUtils(IResourceUtilities<ImageDescriptor> utils) {
+		resUtils = (ISWTResourceUtilities) utils;
+	}
+
+	@Inject
+	@Optional
+	private Logger logger;
+
+	private IMenuListener menuListener = new IMenuListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void menuAboutToShow(IMenuManager manager) {
+			update(null);
+		}
+	};
+
+	public void setModel(MItem item) {
+		model = item;
+		setId(model.getElementId());
+		updateVisible();
+	}
+
+	@Override
+	public void fill(Menu menu, int index) {
+		if (model == null) {
+			return;
+		}
+		if (widget != null) {
+			return;
+		}
+		int style = SWT.PUSH;
+		if (model.getType() == ItemType.PUSH)
+			style = SWT.PUSH;
+		else if (model.getType() == ItemType.CHECK)
+			style = SWT.CHECK;
+		else if (model.getType() == ItemType.RADIO)
+			style = SWT.RADIO;
+		MenuItem item = null;
+		if (index >= 0) {
+			item = new MenuItem(menu, style, index);
+		} else {
+			item = new MenuItem(menu, style);
+		}
+		item.setData(this);
+
+		item.addListener(SWT.Dispose, getItemListener());
+		item.addListener(SWT.Selection, getItemListener());
+		item.addListener(SWT.DefaultSelection, getItemListener());
+
+		widget = item;
+		model.setWidget(widget);
+		widget.setData(AbstractPartRenderer.OWNING_ME, model);
+
+		update(null);
+	}
+
+	@Override
+	public void fill(ToolBar parent, int index) {
+		if (model == null) {
+			return;
+		}
+		if (widget != null) {
+			return;
+		}
+		boolean isDropdown = false;
+		if (model instanceof MToolItem) {
+			MMenu menu = ((MToolItem) model).getMenu();
+			isDropdown = menu != null;
+		}
+		int style = SWT.PUSH;
+		if (isDropdown)
+			style = SWT.DROP_DOWN;
+		else if (model.getType() == ItemType.CHECK)
+			style = SWT.CHECK;
+		else if (model.getType() == ItemType.RADIO)
+			style = SWT.RADIO;
+		ToolItem item = null;
+		if (index >= 0) {
+			item = new ToolItem(parent, style, index);
+		} else {
+			item = new ToolItem(parent, style);
+		}
+		item.setData(this);
+
+		item.addListener(SWT.Dispose, getItemListener());
+		item.addListener(SWT.Selection, getItemListener());
+		item.addListener(SWT.DefaultSelection, getItemListener());
+
+		widget = item;
+		model.setWidget(widget);
+		widget.setData(AbstractPartRenderer.OWNING_ME, model);
+
+		update(null);
+	}
+
+	private void updateVisible() {
+		setVisible((model).isVisible());
+		final IContributionManager parent = getParent();
+		if (parent != null) {
+			parent.markDirty();
+		}
+	}
+
+	@Override
+	public void update() {
+		update(null);
+	}
+
+	@Override
+	public void update(String id) {
+		updateIcons();
+		if (widget instanceof MenuItem) {
+			updateMenuItem();
+		} else if (widget instanceof ToolItem) {
+			updateToolItem();
+		}
+	}
+
+	private void updateMenuItem() {
+		MenuItem item = (MenuItem) widget;
+		String text = model.getLocalizedLabel();
+		if (text != null) {
+			item.setText(text);
+		} else {
+			item.setText(""); //$NON-NLS-1$
+		}
+		item.setSelection(model.isSelected());
+		item.setEnabled(model.isEnabled());
+	}
+
+	private void updateToolItem() {
+		ToolItem item = (ToolItem) widget;
+		final String text = model.getLocalizedLabel();
+		Image icon = item.getImage();
+		boolean mode = model.getTags().contains(FORCE_TEXT);
+		if ((icon == null || mode) && text != null) {
+			item.setText(text);
+		} else {
+			item.setText(""); //$NON-NLS-1$
+		}
+		final String tooltip = model.getLocalizedTooltip();
+		item.setToolTipText(tooltip);
+		item.setSelection(model.isSelected());
+		item.setEnabled(model.isEnabled());
+	}
+
+	private void updateIcons() {
+		if (!(widget instanceof Item)) {
+			return;
+		}
+		Item item = (Item) widget;
+		String iconURI = model.getIconURI() != null ? model.getIconURI() : ""; //$NON-NLS-1$
+		String disabledURI = getDisabledIconURI(model);
+		if (!iconURI.equals(item.getData(ICON_URI))
+				|| !disabledURI.equals(item.getData(DISABLED_URI))) {
+			LocalResourceManager resourceManager = new LocalResourceManager(
+					JFaceResources.getResources());
+			Image iconImage = getImage(iconURI, resourceManager);
+			item.setImage(iconImage);
+			item.setData(ICON_URI, iconURI);
+			if (item instanceof ToolItem) {
+				iconImage = getImage(disabledURI, resourceManager);
+				((ToolItem) item).setDisabledImage(iconImage);
+				item.setData(DISABLED_URI, disabledURI);
+			}
+			disposeOldImages();
+			localResourceManager = resourceManager;
+		}
+	}
+
+	private Image getImage(String iconURI, LocalResourceManager resourceManager) {
+		Image image = null;
+
+		if (iconURI != null && iconURI.length() > 0) {
+			ImageDescriptor iconDescriptor = resUtils
+					.imageDescriptorFromURI(URI.createURI(iconURI));
+			if (iconDescriptor != null) {
+				try {
+					image = resourceManager.createImage(iconDescriptor);
+				} catch (DeviceResourceException e) {
+					iconDescriptor = ImageDescriptor
+							.getMissingImageDescriptor();
+					image = resourceManager.createImage(iconDescriptor);
+					// as we replaced the failed icon, log the message once.
+					Activator.trace(Policy.DEBUG_MENUS,
+							"failed to create image " + iconURI, e); //$NON-NLS-1$
+				}
+			}
+		}
+		return image;
+	}
+
+	private String getDisabledIconURI(MItem toolItem) {
+		Object obj = toolItem.getTransientData().get(
+				IPresentationEngine.DISABLED_ICON_IMAGE_KEY);
+		return obj instanceof String ? (String) obj : ""; //$NON-NLS-1$
+	}
+
+	private void disposeOldImages() {
+		if (localResourceManager != null) {
+			localResourceManager.dispose();
+			localResourceManager = null;
+		}
+	}
+
+	private Listener getItemListener() {
+		if (menuItemListener == null) {
+			menuItemListener = new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(Event event) {
+					switch (event.type) {
+					case SWT.Dispose:
+						handleWidgetDispose(event);
+						break;
+					case SWT.DefaultSelection:
+					case SWT.Selection:
+						if (event.widget != null) {
+							handleWidgetSelection(event);
+						}
+						break;
+					}
+				}
+			};
+		}
+		return menuItemListener;
+	}
+
+	private void handleWidgetDispose(Event event) {
+		if (event.widget == widget) {
+			if (infoContext != null) {
+				infoContext.dispose();
+				infoContext = null;
+			}
+			widget.removeListener(SWT.Selection, getItemListener());
+			widget.removeListener(SWT.Dispose, getItemListener());
+			widget.removeListener(SWT.DefaultSelection, getItemListener());
+			widget = null;
+			Object obj = model.getTransientData().get(DISPOSABLE);
+			if (obj instanceof Runnable) {
+				((Runnable) obj).run();
+			}
+			model.setWidget(null);
+			disposeOldImages();
+		}
+	}
+
+	@Override
+	public void dispose() {
+		if (widget != null) {
+			widget.dispose();
+			widget = null;
+			model.setWidget(null);
+		}
+	}
+
+	private void handleWidgetSelection(Event event) {
+		if (widget != null && !widget.isDisposed()) {
+			if (dropdownEvent(event)) {
+				return;
+			}
+			if (model.getType() == ItemType.CHECK
+					|| model.getType() == ItemType.RADIO) {
+				boolean selection = false;
+				if (widget instanceof MenuItem) {
+					selection = ((MenuItem) widget).getSelection();
+				} else if (widget instanceof ToolItem) {
+					selection = ((ToolItem) widget).getSelection();
+				}
+				model.setSelected(selection);
+			}
+			if (canExecuteItem(event)) {
+				executeItem(event);
+			}
+		}
+	}
+
+	private boolean dropdownEvent(Event event) {
+		if (event.detail == SWT.ARROW && model instanceof MToolItem) {
+			ToolItem ti = (ToolItem) event.widget;
+			MMenu mmenu = ((MToolItem) model).getMenu();
+			if (mmenu == null) {
+				return false;
+			}
+			Menu menu = getMenu(mmenu, ti);
+			if (menu == null) {
+				return true;
+			}
+			Rectangle itemBounds = ti.getBounds();
+			Point displayAt = ti.getParent().toDisplay(itemBounds.x,
+					itemBounds.y + itemBounds.height);
+			menu.setLocation(displayAt);
+			menu.setVisible(true);
+
+			Display display = menu.getDisplay();
+			while (menu.isVisible()) {
+				if (!display.readAndDispatch()) {
+					display.sleep();
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+
+	protected Menu getMenu(final MMenu mmenu, ToolItem toolItem) {
+		Object obj = mmenu.getWidget();
+		if (obj instanceof Menu && !((Menu) obj).isDisposed()) {
+			return (Menu) obj;
+		}
+		// this is a temporary passthrough of the IMenuCreator
+		if (RenderedElementUtil.isRenderedMenu(mmenu)) {
+			obj = RenderedElementUtil.getContributionManager(mmenu);
+			if (obj instanceof IContextFunction) {
+				final IEclipseContext lclContext = getContext(mmenu);
+				obj = ((IContextFunction) obj).compute(lclContext, null);
+				RenderedElementUtil.setContributionManager(mmenu, obj);
+			}
+			if (obj instanceof IMenuCreator) {
+				final IMenuCreator creator = (IMenuCreator) obj;
+				final Menu menu = creator.getMenu(toolItem.getParent()
+						.getShell());
+				if (menu != null) {
+					toolItem.addDisposeListener(new DisposeListener() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetDisposed(DisposeEvent e) {
+							if (menu != null && !menu.isDisposed()) {
+								creator.dispose();
+								mmenu.setWidget(null);
+							}
+						}
+					});
+					// mmenu.setWidget(menu);
+					menu.setData(AbstractPartRenderer.OWNING_ME, menu);
+					return menu;
+				}
+			}
+		} else {
+			final IEclipseContext lclContext = getContext(model);
+			IPresentationEngine engine = lclContext
+					.get(IPresentationEngine.class);
+			obj = engine.createGui(mmenu, toolItem.getParent(), lclContext);
+			if (obj instanceof Menu) {
+				return (Menu) obj;
+			}
+			if (logger != null) {
+				logger.debug("Rendering returned " + obj); //$NON-NLS-1$
+			}
+		}
+		return null;
+	}
+
+	private IEclipseContext getStaticContext(Event event) {
+		if (infoContext == null) {
+			infoContext = EclipseContextFactory.create(DCI_STATIC_CONTEXT);
+			ContributionsAnalyzer.populateModelInterfaces(model, infoContext,
+					model.getClass().getInterfaces());
+		}
+		if (event == null) {
+			infoContext.remove(Event.class);
+		} else {
+			infoContext.set(Event.class, event);
+		}
+		return infoContext;
+	}
+
+	private void executeItem(Event trigger) {
+		final IEclipseContext lclContext = getContext(model);
+		if (!checkContribution(lclContext)) {
+			return;
+		}
+		MContribution contrib = (MContribution) model;
+		IEclipseContext staticContext = getStaticContext(trigger);
+		Object result = ContextInjectionFactory.invoke(contrib.getObject(), Execute.class,
+				getExecutionContext(lclContext), staticContext, missingExecute);
+		if (result == missingExecute && logger != null) {
+			logger.error("Contribution is missing @Execute: " + contrib.getContributionURI()); //$NON-NLS-1$
+		}
+	}
+
+	private boolean canExecuteItem(Event trigger) {
+		final IEclipseContext lclContext = getContext(model);
+		if (!checkContribution(lclContext)) {
+			return false;
+		}
+		MContribution contrib = (MContribution) model;
+		IEclipseContext staticContext = getStaticContext(trigger);
+		Boolean result = ((Boolean) ContextInjectionFactory.invoke(
+				contrib.getObject(), CanExecute.class,
+				getExecutionContext(lclContext), staticContext, Boolean.TRUE));
+		return result.booleanValue();
+	}
+
+	/**
+	 * Return the execution context for the @CanExecute and @Execute methods.
+	 * This should be the same as the execution context used by the
+	 * EHandlerService.
+	 *
+	 * @param context
+	 *            the context for this item
+	 * @return the execution context
+	 */
+	private IEclipseContext getExecutionContext(IEclipseContext context) {
+		if (context == null)
+			return null;
+
+		return context.getActiveLeaf();
+	}
+
+	private boolean checkContribution(IEclipseContext lclContext) {
+		if (!(model instanceof MContribution)) {
+			return false;
+		}
+		MContribution contrib = (MContribution) model;
+		if (contrib.getObject() == null) {
+			contrib.setObject(contribFactory.create(
+					contrib.getContributionURI(), lclContext));
+		}
+		return contrib.getObject() != null;
+	}
+
+	@Override
+	public void setParent(IContributionManager parent) {
+		if (getParent() instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) getParent();
+			menuMgr.removeMenuListener(menuListener);
+		}
+		if (parent instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) parent;
+			menuMgr.addMenuListener(menuListener);
+		}
+		super.setParent(parent);
+	}
+
+	/**
+	 * Return a parent context for this part.
+	 *
+	 * @param element
+	 *            the part to start searching from
+	 * @return the parent's closest context, or global context if none in the
+	 *         hierarchy
+	 */
+	protected IEclipseContext getContextForParent(MUIElement element) {
+		return modelService.getContainingContext(element);
+	}
+
+	/**
+	 * Return a context for this part.
+	 *
+	 * @param part
+	 *            the part to start searching from
+	 * @return the closest context, or global context if none in the hierarchy
+	 */
+	protected IEclipseContext getContext(MUIElement part) {
+		if (part instanceof MContext) {
+			return ((MContext) part).getContext();
+		}
+		return getContextForParent(part);
+	}
+
+	public Widget getWidget() {
+		return widget;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectMenuItemRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectMenuItemRenderer.java
new file mode 100644
index 0000000..f887b23
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DirectMenuItemRenderer.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * Create a contribute part.
+ */
+public class DirectMenuItemRenderer extends MenuItemRenderer {
+
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MDirectMenuItem) || !(parent instanceof Menu))
+			return null;
+
+		MDirectMenuItem itemModel = (MDirectMenuItem) element;
+		if (itemModel.getVisibleWhen() != null) {
+			processVisible(itemModel);
+		}
+
+		if (!itemModel.isVisible()) {
+			return null;
+		}
+
+		// determine the index at which we should create the new item
+		int addIndex = calcVisibleIndex(element);
+
+		// OK, it's a real menu item, what kind?
+		int flags = 0;
+		if (itemModel.getType() == ItemType.PUSH)
+			flags = SWT.PUSH;
+		else if (itemModel.getType() == ItemType.CHECK)
+			flags = SWT.CHECK;
+		else if (itemModel.getType() == ItemType.RADIO)
+			flags = SWT.RADIO;
+
+		MenuItem newItem = new MenuItem((Menu) parent, flags, addIndex);
+		setItemText(itemModel, newItem);
+		newItem.setImage(getImage(itemModel));
+		setEnabled(itemModel, newItem);
+		newItem.setEnabled(itemModel.isEnabled());
+		newItem.setSelection(itemModel.isSelected());
+
+		return newItem;
+	}
+
+	private void setEnabled(MDirectMenuItem itemModel, final MenuItem newItem) {
+		// TODO direct query to @CanExecute goes here
+	}
+
+	@Override
+	public void hookControllerLogic(MUIElement me) {
+		super.hookControllerLogic(me);
+
+		// 'Execute' the operation if possible
+		if (me instanceof MDirectMenuItem
+				&& ((MDirectMenuItem) me).getContributionURI() != null) {
+			final MMenuItem item = (MMenuItem) me;
+			final MDirectMenuItem contrib = (MDirectMenuItem) me;
+			final IEclipseContext lclContext = getContext(me);
+			MenuItem mi = (MenuItem) me.getWidget();
+			mi.addSelectionListener(new SelectionListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					lclContext.set(MItem.class.getName(), item);
+					ContextInjectionFactory.invoke(contrib.getObject(),
+							Execute.class, lclContext);
+					lclContext.remove(MItem.class.getName());
+				}
+
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+			});
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DynamicContributionContributionItem.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DynamicContributionContributionItem.java
new file mode 100644
index 0000000..66f0174
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/DynamicContributionContributionItem.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2013 MEDEVIT, FHV 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:
+ *     Marco Descher <marco@descher.at> - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import org.eclipse.e4.ui.model.application.ui.menu.MDynamicMenuContribution;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+
+/**
+ * This item currently serves as a placeholder to determine the correct location
+ * of a dynamic menu contribution entry.
+ */
+class DynamicContributionContributionItem extends ContributionItem {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private MDynamicMenuContribution model;
+
+	private IMenuListener menuListener = new IMenuListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void menuAboutToShow(IMenuManager manager) {
+			manager.markDirty();
+		}
+	};
+
+	/**
+	 * Create the item and associated model;
+	 *
+	 * @param item
+	 */
+	public DynamicContributionContributionItem(MDynamicMenuContribution item) {
+		super(item.getElementId());
+		model = item;
+	}
+
+	@Override
+	public boolean isDirty() {
+		return true;
+	}
+
+	@Override
+	public boolean isDynamic() {
+		return true;
+	}
+
+	/**
+	 * @return the model element
+	 */
+	public MDynamicMenuContribution getModel() {
+		return model;
+	}
+
+	@Override
+	public void setParent(IContributionManager parent) {
+		if (getParent() instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) getParent();
+			menuMgr.removeMenuListener(menuListener);
+		}
+		if (parent instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) parent;
+			menuMgr.addMenuListener(menuListener);
+		}
+		super.setParent(parent);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ElementReferenceRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ElementReferenceRenderer.java
new file mode 100644
index 0000000..ca107b2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ElementReferenceRenderer.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Create an element from a reference
+ */
+public class ElementReferenceRenderer extends SWTPartRenderer {
+	@Inject
+	@Named(WorkbenchRendererFactory.SHARED_ELEMENTS_STORE)
+	private Map<MUIElement, Set<MPlaceholder>> renderedMap;
+
+	@Inject
+	private IPresentationEngine renderingEngine;
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		MPlaceholder ph = (MPlaceholder) element;
+		final MUIElement ref = ph.getRef();
+		ref.setCurSharedRef(ph);
+
+		Set<MPlaceholder> renderedRefs = renderedMap.get(ref);
+		if (renderedRefs == null) {
+			renderedRefs = new HashSet<MPlaceholder>();
+			renderedMap.put(ref, renderedRefs);
+		}
+
+		if (!renderedRefs.contains(ph))
+			renderedRefs.add(ph);
+
+		Composite newComp = new Composite((Composite) parent, SWT.NONE);
+		newComp.setLayout(new FillLayout());
+
+		// if the placeholder is *not* in the currently active perspective
+		// then don't re-parent the current view
+		int phLoc = modelService.getElementLocation(ph);
+		if (phLoc == EModelService.IN_ACTIVE_PERSPECTIVE
+				|| phLoc == EModelService.IN_SHARED_AREA
+				|| phLoc == EModelService.OUTSIDE_PERSPECTIVE) {
+			Control refWidget = (Control) ref.getWidget();
+			if (refWidget == null) {
+				ref.setToBeRendered(true);
+				refWidget = (Control) renderingEngine.createGui(ref, newComp,
+						getContextForParent(ref));
+			} else {
+				if (refWidget.getParent() != newComp) {
+					refWidget.setParent(newComp);
+				}
+			}
+
+			if (ref instanceof MContext) {
+				IEclipseContext context = ((MContext) ref).getContext();
+				IEclipseContext newParentContext = getContext(ph);
+				if (context.getParent() != newParentContext) {
+					context.setParent(newParentContext);
+				}
+			}
+		}
+
+		return newComp;
+	}
+
+	@Override
+	public void disposeWidget(MUIElement element) {
+		MPlaceholder ph = (MPlaceholder) element;
+		MUIElement refElement = ph.getRef();
+		Control refCtrl = (Control) refElement.getWidget();
+
+		// Remove the element ref from the rendered list
+		Set<MPlaceholder> refs = renderedMap.get(refElement);
+		refs.remove(ph);
+
+		IEclipseContext curContext = modelService.getContainingContext(ph);
+
+		if (refs.size() == 0) {
+			// Ensure that the image is the 'original' image for this
+			// part. See bug 347471 for details
+			if (refElement instanceof MPart) {
+				MPart thePart = (MPart) refElement;
+				String imageURI = thePart.getIconURI();
+				thePart.setIconURI(null);
+				thePart.setIconURI(imageURI);
+			}
+
+			renderingEngine.removeGui(refElement);
+		} else {
+			// Ensure that the dispose of the element reference doesn't cascade
+			// to dispose the 'real' part
+			if (refCtrl != null && !refCtrl.isDisposed()) {
+				MPlaceholder currentRef = refElement.getCurSharedRef();
+				if (currentRef == ph) {
+					// Find another *rendered* ref to pass the part on to
+					for (MPlaceholder aPH : refs) {
+						Composite phComp = (Composite) aPH.getWidget();
+						if (phComp == null || phComp.isDisposed())
+							continue;
+
+						// Reparent the context(s) (if any)
+						IEclipseContext newParentContext = modelService
+								.getContainingContext(aPH);
+						List<MContext> allContexts = modelService.findElements(
+								refElement, null, MContext.class, null);
+						for (MContext ctxtElement : allContexts) {
+							IEclipseContext theContext = ctxtElement
+									.getContext();
+							// this may be null if it hasn't been rendered yet
+							if (theContext != null) {
+								if (theContext.getParent() == curContext) {
+									// about to reparent the context, if we're
+									// the active child of the current parent,
+									// deactivate ourselves first
+									if (curContext.getActiveChild() == theContext) {
+										theContext.deactivate();
+									}
+									theContext.setParent(newParentContext);
+								}
+							}
+						}
+
+						// reset the 'cur' ref
+						refElement.setCurSharedRef(aPH);
+
+						// Reparent the widget
+						refCtrl.setParent(phComp);
+						break;
+					}
+				} else if (currentRef != null) {
+					Composite phComp = (Composite) currentRef.getWidget();
+					if (phComp == null || phComp.isDisposed()) {
+						super.disposeWidget(element);
+						return;
+					}
+
+					// Reparent the context(s) (if any)
+					IEclipseContext newParentContext = modelService
+							.getContainingContext(currentRef);
+					List<MContext> allContexts = modelService.findElements(
+							refElement, null, MContext.class, null);
+					for (MContext ctxtElement : allContexts) {
+						IEclipseContext theContext = ctxtElement.getContext();
+						// this may be null if it hasn't been rendered yet
+						if (theContext != null
+								&& theContext.getParent() == curContext) {
+							// about to reparent the context, if we're the
+							// active child of the current parent, deactivate
+							// ourselves first
+							if (curContext.getActiveChild() == theContext) {
+								theContext.deactivate();
+							}
+							theContext.setParent(newParentContext);
+						}
+					}
+				}
+			}
+		}
+
+		super.disposeWidget(element);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledContributionItem.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledContributionItem.java
new file mode 100644
index 0000000..d389b0b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledContributionItem.java
@@ -0,0 +1,895 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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
+ *     Joseph Carroll <jdsalingerjr@gmail.com> - Bug 385414 Contributing wizards to toolbar always displays icon and text
+ *     Snjezana Peco <snjezana.peco@redhat.com> - Memory leaks in Juno when opening and closing XML Editor - http://bugs.eclipse.org/397909
+ *     Marco Descher <marco@descher.at> - Bug 397677
+ *     Dmitry Spiridenok - Bug 429756
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 445723, 450863
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 461026
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.commands.IStateListener;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.State;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.commands.internal.ICommandHelpService;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil;
+import org.eclipse.e4.ui.internal.workbench.renderers.swt.IUpdateService;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MParameter;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.services.help.EHelpService;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.menus.IMenuStateIds;
+import org.eclipse.jface.resource.DeviceResourceException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+
+public class HandledContributionItem extends ContributionItem {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constant from org.eclipse.ui.handlers.RadioState.PARAMETER_ID
+	 */
+	private static final String ORG_ECLIPSE_UI_COMMANDS_RADIO_STATE_PARAMETER = "org.eclipse.ui.commands.radioStateParameter"; //$NON-NLS-1$
+
+	/**
+	 * Constant from org.eclipse.ui.handlers.RadioState.STATE_ID
+	 */
+	private static final String ORG_ECLIPSE_UI_COMMANDS_RADIO_STATE = "org.eclipse.ui.commands.radioState"; //$NON-NLS-1$
+
+	/**
+	 * Constant from org.eclipse.ui.handlers.RegistryToggleState.STATE_ID
+	 */
+	private static final String ORG_ECLIPSE_UI_COMMANDS_TOGGLE_STATE = "org.eclipse.ui.commands.toggleState"; //$NON-NLS-1$
+
+	private static final String FORCE_TEXT = "FORCE_TEXT"; //$NON-NLS-1$
+	private static final String ICON_URI = "iconURI"; //$NON-NLS-1$
+	private static final String DISABLED_URI = "disabledURI"; //$NON-NLS-1$
+	private static final String DISPOSABLE_CHECK = "IDisposable"; //$NON-NLS-1$
+	private static final String WW_SUPPORT = "org.eclipse.ui.IWorkbenchWindow"; //$NON-NLS-1$
+	private static final String HCI_STATIC_CONTEXT = "HCI-staticContext"; //$NON-NLS-1$
+	private MHandledItem model;
+	private Widget widget;
+	private Listener menuItemListener;
+	private LocalResourceManager localResourceManager;
+
+	@Inject
+	@Optional
+	private Logger logger;
+
+	// We'll only ever log an error during update once to prevent spamming the
+	// log
+	private boolean logged = false;
+
+	@Inject
+	private ECommandService commandService;
+
+	@Inject
+	private EModelService modelService;
+
+	@Inject
+	private EBindingService bindingService;
+
+	@Inject
+	@Optional
+	private IUpdateService updateService;
+
+	@Inject
+	@Optional
+	private EHelpService helpService;
+
+	@Inject
+	@Optional
+	@SuppressWarnings("restriction")
+	private ICommandHelpService commandHelpService;
+
+	private Runnable unreferenceRunnable;
+
+	private ISWTResourceUtilities resUtils = null;
+
+	private IStateListener stateListener = new IStateListener() {
+		@Override
+		public void handleStateChange(State state, Object oldValue) {
+			updateState();
+		}
+	};
+
+	@Inject
+	void setResourceUtils(IResourceUtilities<ImageDescriptor> utils) {
+		resUtils = (ISWTResourceUtilities) utils;
+	}
+
+	private ISafeRunnable getUpdateRunner() {
+		if (updateRunner == null) {
+			updateRunner = new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					boolean shouldEnable = canExecuteItem(null);
+					if (shouldEnable != model.isEnabled()) {
+						model.setEnabled(shouldEnable);
+						update();
+					}
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					if (!logged) {
+						logged = true;
+						if (logger != null) {
+							logger.error(
+									exception,
+									"Internal error during tool item enablement updating, this is only logged once per tool item."); //$NON-NLS-1$
+						}
+					}
+				}
+			};
+		}
+		return updateRunner;
+	}
+
+	protected void updateItemEnablement() {
+		if (!(model.getWidget() instanceof ToolItem))
+			return;
+
+		ToolItem widget = (ToolItem) model.getWidget();
+		if (widget == null || widget.isDisposed())
+			return;
+
+		SafeRunner.run(getUpdateRunner());
+	}
+
+	private IMenuListener menuListener = new IMenuListener() {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		public void menuAboutToShow(IMenuManager manager) {
+			update(null);
+		}
+	};
+
+	private ISafeRunnable updateRunner;
+
+	private IEclipseContext infoContext;
+
+	private State styleState;
+
+	private State toggleState;
+
+	private State radioState;
+
+	public void setModel(MHandledItem item) {
+		model = item;
+		setId(model.getElementId());
+		generateCommand();
+		if (model.getCommand() == null) {
+			if (logger != null) {
+				logger.error("Element " + model.getElementId() + " invalid, no command defined."); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		updateVisible();
+	}
+
+	/**
+	 *
+	 */
+	private void generateCommand() {
+		if (model.getCommand() != null && model.getWbCommand() == null) {
+			String cmdId = model.getCommand().getElementId();
+			if (cmdId == null) {
+				Activator.log(IStatus.ERROR, "Unable to generate parameterized command for " + model //$NON-NLS-1$
+						+ ". ElementId is not allowed to be null."); //$NON-NLS-1$
+				return;
+			}
+			List<MParameter> modelParms = model.getParameters();
+			Map<String, Object> parameters = new HashMap<String, Object>(4);
+			for (MParameter mParm : modelParms) {
+				parameters.put(mParm.getName(), mParm.getValue());
+			}
+			ParameterizedCommand parmCmd = commandService.createCommand(cmdId,
+					parameters);
+			Activator.trace(Policy.DEBUG_MENUS, "command: " + parmCmd, null); //$NON-NLS-1$
+			if (parmCmd == null) {
+				Activator.log(IStatus.ERROR,
+						"Unable to generate parameterized command for " + model //$NON-NLS-1$
+								+ " with " + parameters); //$NON-NLS-1$
+				return;
+			}
+
+			model.setWbCommand(parmCmd);
+
+			styleState = parmCmd.getCommand().getState(IMenuStateIds.STYLE);
+			toggleState = parmCmd.getCommand().getState(
+					ORG_ECLIPSE_UI_COMMANDS_TOGGLE_STATE);
+			radioState = parmCmd.getCommand().getState(
+					ORG_ECLIPSE_UI_COMMANDS_RADIO_STATE);
+			updateState();
+
+			if (styleState != null) {
+				styleState.addListener(stateListener);
+			} else if (toggleState != null) {
+				toggleState.addListener(stateListener);
+			} else if (radioState != null) {
+				radioState.addListener(stateListener);
+			}
+		}
+	}
+
+	private void updateState() {
+		if (styleState != null) {
+			model.setSelected(((Boolean) styleState.getValue()).booleanValue());
+		} else if (toggleState != null) {
+			model.setSelected(((Boolean) toggleState.getValue()).booleanValue());
+		} else if (radioState != null && model.getWbCommand() != null) {
+			ParameterizedCommand c = model.getWbCommand();
+			Object parameter = c.getParameterMap().get(
+					ORG_ECLIPSE_UI_COMMANDS_RADIO_STATE_PARAMETER);
+			String value = (String) radioState.getValue();
+			model.setSelected(value != null && value.equals(parameter));
+		}
+	}
+
+	@Override
+	public void fill(Menu menu, int index) {
+		if (model == null) {
+			return;
+		}
+		if (widget != null) {
+			return;
+		}
+		int style = SWT.PUSH;
+		if (model.getType() == ItemType.PUSH)
+			style = SWT.PUSH;
+		else if (model.getType() == ItemType.CHECK)
+			style = SWT.CHECK;
+		else if (model.getType() == ItemType.RADIO)
+			style = SWT.RADIO;
+		MenuItem item = null;
+		if (index >= 0) {
+			item = new MenuItem(menu, style, index);
+		} else {
+			item = new MenuItem(menu, style);
+		}
+		item.setData(this);
+
+		item.addListener(SWT.Dispose, getItemListener());
+		item.addListener(SWT.Selection, getItemListener());
+		item.addListener(SWT.DefaultSelection, getItemListener());
+		item.addListener(SWT.Help, getItemListener());
+
+		widget = item;
+		model.setWidget(widget);
+		widget.setData(AbstractPartRenderer.OWNING_ME, model);
+
+		update(null);
+
+		if (updateService != null) {
+			unreferenceRunnable = updateService.registerElementForUpdate(
+					model.getWbCommand(), model);
+		}
+	}
+
+	@Override
+	public void fill(ToolBar parent, int index) {
+		if (model == null) {
+			return;
+		}
+		if (widget != null) {
+			return;
+		}
+		boolean isDropdown = false;
+		if (model instanceof MToolItem) {
+			MMenu menu = ((MToolItem) model).getMenu();
+			isDropdown = menu != null;
+		}
+		int style = SWT.PUSH;
+		if (isDropdown)
+			style = SWT.DROP_DOWN;
+		else if (model.getType() == ItemType.CHECK)
+			style = SWT.CHECK;
+		else if (model.getType() == ItemType.RADIO)
+			style = SWT.RADIO;
+		ToolItem item = null;
+		if (index >= 0) {
+			item = new ToolItem(parent, style, index);
+		} else {
+			item = new ToolItem(parent, style);
+		}
+		item.setData(this);
+
+		item.addListener(SWT.Dispose, getItemListener());
+		item.addListener(SWT.Selection, getItemListener());
+		item.addListener(SWT.DefaultSelection, getItemListener());
+
+		widget = item;
+		model.setWidget(widget);
+		widget.setData(AbstractPartRenderer.OWNING_ME, model);
+		ToolItemUpdater updater = getUpdater();
+		if (updater != null) {
+			updater.registerItem(this);
+		}
+
+		update(null);
+		hookCheckListener();
+
+		if (updateService != null) {
+			unreferenceRunnable = updateService.registerElementForUpdate(
+					model.getWbCommand(), model);
+		}
+	}
+
+	private void hookCheckListener() {
+		if (model.getType() != ItemType.CHECK) {
+			return;
+		}
+		Object obj = model.getTransientData().get(ItemType.CHECK.toString());
+		if (obj instanceof IContextFunction) {
+			IEclipseContext context = getContext(model);
+			IEclipseContext staticContext = getStaticContext(null);
+			staticContext.set(MPart.class, context.get(MPart.class));
+			staticContext.set(WW_SUPPORT, context.get(WW_SUPPORT));
+
+			IContextFunction func = (IContextFunction) obj;
+			obj = func.compute(staticContext, null);
+			if (obj != null) {
+				model.getTransientData().put(DISPOSABLE_CHECK, obj);
+			}
+		}
+	}
+
+	private void unhookCheckListener() {
+		if (model.getType() != ItemType.CHECK) {
+			return;
+		}
+		final Object obj = model.getTransientData().remove(DISPOSABLE_CHECK);
+		if (obj == null) {
+			return;
+		}
+		((Runnable) obj).run();
+	}
+
+	private void updateVisible() {
+		setVisible((model).isVisible());
+		final IContributionManager parent = getParent();
+		if (parent != null) {
+			parent.markDirty();
+		}
+	}
+
+	@Override
+	public void update() {
+		update(null);
+	}
+
+	@Override
+	public void update(String id) {
+		updateIcons();
+		if (widget instanceof MenuItem) {
+			updateMenuItem();
+		} else if (widget instanceof ToolItem) {
+			updateToolItem();
+		}
+	}
+
+	private void updateMenuItem() {
+		MenuItem item = (MenuItem) widget;
+		String text = model.getLocalizedLabel();
+		ParameterizedCommand parmCmd = model.getWbCommand();
+		String keyBindingText = null;
+		if (parmCmd != null) {
+			if (text == null || text.isEmpty()) {
+				text = model.getCommand().getLocalizedCommandName();
+			}
+			if (bindingService != null) {
+				TriggerSequence binding = bindingService
+						.getBestSequenceFor(parmCmd);
+				if (binding != null)
+					keyBindingText = binding.format();
+			}
+		}
+		if (text != null) {
+			if (model instanceof MMenuElement) {
+				String mnemonics = ((MMenuElement) model).getMnemonics();
+				if (mnemonics != null && !mnemonics.isEmpty()) {
+					int idx = text.indexOf(mnemonics);
+					if (idx != -1) {
+						text = text.substring(0, idx) + '&'
+								+ text.substring(idx);
+					}
+				}
+			}
+			if (keyBindingText == null)
+				item.setText(text);
+			else
+				item.setText(text + '\t' + keyBindingText);
+		} else {
+			item.setText(""); //$NON-NLS-1$
+		}
+		item.setSelection(model.isSelected());
+		item.setEnabled(model.isEnabled());
+	}
+
+	private void updateToolItem() {
+		ToolItem item = (ToolItem) widget;
+
+		if (item.getImage() == null || model.getTags().contains(FORCE_TEXT)) {
+			final String text = model.getLocalizedLabel();
+			if (text == null || text.length() == 0) {
+				final MCommand command = model.getCommand();
+				if (command == null) {
+					// Set some text so that the item stays visible in the menu
+					item.setText("UnLabled"); //$NON-NLS-1$
+				} else {
+					item.setText(command.getLocalizedCommandName());
+				}
+			} else {
+				item.setText(text);
+			}
+		} else {
+			item.setText(""); //$NON-NLS-1$
+		}
+
+		final String tooltip = getToolTipText();
+		item.setToolTipText(tooltip);
+		item.setSelection(model.isSelected());
+		item.setEnabled(model.isEnabled());
+	}
+
+	private String getToolTipText() {
+		String text = model.getLocalizedTooltip();
+		ParameterizedCommand parmCmd = model.getWbCommand();
+		if (parmCmd == null) {
+			generateCommand();
+			parmCmd = model.getWbCommand();
+		}
+
+		if (parmCmd != null && text == null) {
+			try {
+				text = parmCmd.getName();
+			} catch (NotDefinedException e) {
+				return null;
+			}
+		}
+
+		TriggerSequence sequence = bindingService.getBestSequenceFor(parmCmd);
+		if (sequence != null) {
+			text = text + " (" + sequence.format() + ')'; //$NON-NLS-1$
+		}
+		return text;
+	}
+
+	private void updateIcons() {
+		if (!(widget instanceof Item)) {
+			return;
+		}
+		Item item = (Item) widget;
+		String iconURI = model.getIconURI() != null ? model.getIconURI() : ""; //$NON-NLS-1$
+		String disabledURI = getDisabledIconURI(model);
+		Object disabledData = item.getData(DISABLED_URI);
+		if (disabledData == null)
+			disabledData = ""; //$NON-NLS-1$
+		if (!iconURI.equals(item.getData(ICON_URI))
+				|| !disabledURI.equals(disabledData)) {
+			LocalResourceManager resourceManager = new LocalResourceManager(
+					JFaceResources.getResources());
+			Image iconImage = getImage(iconURI, resourceManager);
+			item.setImage(iconImage);
+			item.setData(ICON_URI, iconURI);
+			if (item instanceof ToolItem) {
+				iconImage = getImage(disabledURI, resourceManager);
+				((ToolItem) item).setDisabledImage(iconImage);
+				item.setData(DISABLED_URI, disabledURI);
+			}
+			disposeOldImages();
+			localResourceManager = resourceManager;
+		}
+	}
+
+	private String getDisabledIconURI(MItem toolItem) {
+		Object obj = toolItem.getTransientData().get(
+				IPresentationEngine.DISABLED_ICON_IMAGE_KEY);
+		return obj instanceof String ? (String) obj : ""; //$NON-NLS-1$
+	}
+
+	private Image getImage(String iconURI, LocalResourceManager resourceManager) {
+		Image image = null;
+
+		if (iconURI != null && iconURI.length() > 0) {
+			ImageDescriptor iconDescriptor = resUtils
+					.imageDescriptorFromURI(URI.createURI(iconURI));
+			if (iconDescriptor != null) {
+				try {
+					image = resourceManager.createImage(iconDescriptor);
+				} catch (DeviceResourceException e) {
+					iconDescriptor = ImageDescriptor
+							.getMissingImageDescriptor();
+					image = resourceManager.createImage(iconDescriptor);
+					// as we replaced the failed icon, log the message once.
+					Activator.trace(Policy.DEBUG_MENUS,
+							"failed to create image " + iconURI, e); //$NON-NLS-1$
+				}
+			}
+		}
+		return image;
+	}
+
+	private void disposeOldImages() {
+		if (localResourceManager != null) {
+			localResourceManager.dispose();
+			localResourceManager = null;
+		}
+	}
+
+	private Listener getItemListener() {
+		if (menuItemListener == null) {
+			menuItemListener = new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(Event event) {
+					switch (event.type) {
+					case SWT.Dispose:
+						handleWidgetDispose(event);
+						break;
+					case SWT.DefaultSelection:
+					case SWT.Selection:
+						if (event.widget != null) {
+							handleWidgetSelection(event);
+						}
+						break;
+					case SWT.Help:
+						handleHelpRequest();
+						break;
+					}
+				}
+			};
+		}
+		return menuItemListener;
+	}
+
+	private void handleWidgetDispose(Event event) {
+		if (event.widget == widget) {
+			if (unreferenceRunnable != null) {
+				unreferenceRunnable.run();
+				unreferenceRunnable = null;
+			}
+			unhookCheckListener();
+			ToolItemUpdater updater = getUpdater();
+			if (updater != null) {
+				updater.removeItem(this);
+			}
+			if (infoContext != null) {
+				infoContext.dispose();
+				infoContext = null;
+			}
+			widget.removeListener(SWT.Selection, getItemListener());
+			widget.removeListener(SWT.Dispose, getItemListener());
+			widget.removeListener(SWT.DefaultSelection, getItemListener());
+			widget.removeListener(SWT.Help, getItemListener());
+			widget = null;
+			model.setWidget(null);
+			disposeOldImages();
+		}
+	}
+
+	@Override
+	public void dispose() {
+		if (widget != null) {
+			if (unreferenceRunnable != null) {
+				unreferenceRunnable.run();
+				unreferenceRunnable = null;
+			}
+
+			ParameterizedCommand command = model.getWbCommand();
+			if (command != null) {
+				if (styleState != null) {
+					styleState.removeListener(stateListener);
+					styleState = null;
+				}
+				if (toggleState != null) {
+					toggleState.removeListener(stateListener);
+					toggleState = null;
+				}
+				if (radioState != null) {
+					radioState.removeListener(stateListener);
+					radioState = null;
+				}
+			}
+			widget.dispose();
+			widget = null;
+			model.setWidget(null);
+		}
+	}
+
+	private void handleWidgetSelection(Event event) {
+		if (widget != null && !widget.isDisposed()) {
+			if (dropdownEvent(event)) {
+				return;
+			}
+			if (model.getType() == ItemType.CHECK
+					|| model.getType() == ItemType.RADIO) {
+				boolean selection = false;
+				if (widget instanceof MenuItem) {
+					selection = ((MenuItem) widget).getSelection();
+				} else if (widget instanceof ToolItem) {
+					selection = ((ToolItem) widget).getSelection();
+				}
+				model.setSelected(selection);
+			}
+			if (canExecuteItem(event)) {
+				executeItem(event);
+			}
+		}
+	}
+
+	@SuppressWarnings("restriction")
+	private void handleHelpRequest() {
+		MCommand command = model.getCommand();
+		if (command == null || helpService == null
+				|| commandHelpService == null) {
+			return;
+		}
+
+		String contextHelpId = commandHelpService.getHelpContextId(
+				command.getElementId(), getContext(model));
+		if (contextHelpId != null) {
+			helpService.displayHelp(contextHelpId);
+		}
+	}
+
+	/**
+	 * @param event
+	 * @return
+	 */
+	private boolean dropdownEvent(Event event) {
+		if (event.detail == SWT.ARROW && model instanceof MToolItem) {
+			ToolItem ti = (ToolItem) event.widget;
+			MMenu mmenu = ((MToolItem) model).getMenu();
+			if (mmenu == null) {
+				return false;
+			}
+			Menu menu = getMenu(mmenu, ti);
+			if (menu == null || menu.isDisposed()) {
+				return true;
+			}
+			Rectangle itemBounds = ti.getBounds();
+			Point displayAt = ti.getParent().toDisplay(itemBounds.x,
+					itemBounds.y + itemBounds.height);
+			menu.setLocation(displayAt);
+			menu.setVisible(true);
+
+			Display display = menu.getDisplay();
+			while (!menu.isDisposed() && menu.isVisible()) {
+				if (!display.readAndDispatch()) {
+					display.sleep();
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+
+	protected Menu getMenu(final MMenu mmenu, ToolItem toolItem) {
+		Object obj = mmenu.getWidget();
+		if (obj instanceof Menu && !((Menu) obj).isDisposed()) {
+			return (Menu) obj;
+		}
+		// this is a temporary passthrough of the IMenuCreator
+		if (RenderedElementUtil.isRenderedMenu(mmenu)) {
+			obj = RenderedElementUtil.getContributionManager(mmenu);
+			if (obj instanceof IContextFunction) {
+				final IEclipseContext lclContext = getContext(mmenu);
+				obj = ((IContextFunction) obj).compute(lclContext, null);
+				RenderedElementUtil.setContributionManager(mmenu, obj);
+			}
+			if (obj instanceof IMenuCreator) {
+				final IMenuCreator creator = (IMenuCreator) obj;
+				final Menu menu = creator.getMenu(toolItem.getParent()
+						.getShell());
+				if (menu != null) {
+					toolItem.addDisposeListener(new DisposeListener() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetDisposed(DisposeEvent e) {
+							if (menu != null && !menu.isDisposed()) {
+								creator.dispose();
+								mmenu.setWidget(null);
+							}
+						}
+					});
+					// mmenu.setWidget(menu);
+					menu.setData(AbstractPartRenderer.OWNING_ME, menu);
+					return menu;
+				}
+			}
+		} else {
+			final IEclipseContext lclContext = getContext(model);
+			IPresentationEngine engine = lclContext
+					.get(IPresentationEngine.class);
+			obj = engine.createGui(mmenu, toolItem.getParent(), lclContext);
+			if (obj instanceof Menu) {
+				Menu menu = (Menu) obj;
+				// menu.setData(AbstractPartRenderer.OWNING_ME, menu);
+				return menu;
+			}
+			if (logger != null) {
+				logger.debug("Rendering returned " + obj); //$NON-NLS-1$
+			}
+		}
+		return null;
+	}
+
+	private IEclipseContext getStaticContext(Event event) {
+		if (infoContext == null) {
+			infoContext = EclipseContextFactory.create(HCI_STATIC_CONTEXT);
+			ContributionsAnalyzer.populateModelInterfaces(model, infoContext,
+					model.getClass().getInterfaces());
+		}
+		if (event == null) {
+			infoContext.remove(Event.class);
+		} else {
+			infoContext.set(Event.class, event);
+		}
+		return infoContext;
+	}
+
+	private void executeItem(Event trigger) {
+		ParameterizedCommand cmd = model.getWbCommand();
+		if (cmd == null) {
+			return;
+		}
+		final IEclipseContext lclContext = getContext(model);
+		EHandlerService service = (EHandlerService) lclContext
+				.get(EHandlerService.class.getName());
+		final IEclipseContext staticContext = getStaticContext(trigger);
+		service.executeHandler(cmd, staticContext);
+	}
+
+	private boolean canExecuteItem(Event trigger) {
+		ParameterizedCommand cmd = model.getWbCommand();
+		if (cmd == null) {
+			return false;
+		}
+		final IEclipseContext lclContext = getContext(model);
+		EHandlerService service = lclContext.get(EHandlerService.class);
+		if (service == null) {
+			return false;
+		}
+		final IEclipseContext staticContext = getStaticContext(trigger);
+		return service.canExecute(cmd, staticContext);
+	}
+
+	@Override
+	public void setParent(IContributionManager parent) {
+		if (getParent() instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) getParent();
+			menuMgr.removeMenuListener(menuListener);
+		}
+		if (parent instanceof IMenuManager) {
+			IMenuManager menuMgr = (IMenuManager) parent;
+			menuMgr.addMenuListener(menuListener);
+		}
+		super.setParent(parent);
+	}
+
+	/**
+	 * Return a parent context for this part.
+	 *
+	 * @param element
+	 *            the part to start searching from
+	 * @return the parent's closest context, or global context if none in the
+	 *         hierarchy
+	 */
+	protected IEclipseContext getContextForParent(MUIElement element) {
+		return modelService.getContainingContext(element);
+	}
+
+	/**
+	 * Return a context for this part.
+	 *
+	 * @param part
+	 *            the part to start searching from
+	 * @return the closest context, or global context if none in the hierarchy
+	 */
+	protected IEclipseContext getContext(MUIElement part) {
+		if (part instanceof MContext) {
+			return ((MContext) part).getContext();
+		}
+		return getContextForParent(part);
+	}
+
+	public Widget getWidget() {
+		return widget;
+	}
+
+	/**
+	 * @return the model
+	 */
+	public MHandledItem getModel() {
+		return model;
+	}
+
+	private ToolItemUpdater getUpdater() {
+		if (model != null) {
+			Object obj = model.getRenderer();
+			if (obj instanceof ToolBarManagerRenderer) {
+				return ((ToolBarManagerRenderer) obj).getUpdater();
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledMenuItemRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledMenuItemRenderer.java
new file mode 100644
index 0000000..92fab82
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/HandledMenuItemRenderer.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.model.application.commands.MParameter;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * Create a contribute part.
+ */
+public class HandledMenuItemRenderer extends MenuItemRenderer {
+
+	private static final String HMI_STATIC_CONTEXT = "HMIR-staticContext"; //$NON-NLS-1$
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MHandledMenuItem) || !(parent instanceof Menu))
+			return null;
+
+		MHandledMenuItem itemModel = (MHandledMenuItem) element;
+		if (itemModel.getVisibleWhen() != null) {
+			processVisible(itemModel);
+		}
+
+		if (!itemModel.isVisible()) {
+			return null;
+		}
+
+		// determine the index at which we should create the new item
+		int addIndex = calcVisibleIndex(element);
+
+		// OK, it's a real menu item, what kind?
+		int flags = 0;
+		if (itemModel.getType() == ItemType.PUSH)
+			flags = SWT.PUSH;
+		else if (itemModel.getType() == ItemType.CHECK)
+			flags = SWT.CHECK;
+		else if (itemModel.getType() == ItemType.RADIO)
+			flags = SWT.RADIO;
+
+		ParameterizedCommand cmd = itemModel.getWbCommand();
+		if (cmd == null) {
+			IEclipseContext lclContext = getContext(itemModel);
+			cmd = generateParameterizedCommand(itemModel, lclContext);
+		}
+		MenuItem newItem = new MenuItem((Menu) parent, flags, addIndex);
+		setItemText(itemModel, newItem);
+		setEnabled(itemModel, newItem);
+		newItem.setImage(getImage(itemModel));
+		newItem.setSelection(itemModel.isSelected());
+
+		return newItem;
+	}
+
+	private void setEnabled(MHandledMenuItem itemModel, MenuItem newItem) {
+		ParameterizedCommand cmd = itemModel.getWbCommand();
+		if (cmd == null) {
+			return;
+		}
+		final IEclipseContext lclContext = getContext(itemModel);
+		EHandlerService service = lclContext.get(EHandlerService.class);
+		final IEclipseContext staticContext = EclipseContextFactory
+				.create(HMI_STATIC_CONTEXT);
+		ContributionsAnalyzer.populateModelInterfaces(itemModel, staticContext,
+				itemModel.getClass().getInterfaces());
+
+		try {
+			itemModel.setEnabled(service.canExecute(cmd, staticContext));
+		} finally {
+			staticContext.dispose();
+		}
+		newItem.setEnabled(itemModel.isEnabled());
+	}
+
+	@Override
+	protected void setItemText(MMenuItem model, MenuItem item) {
+		String text = model.getLocalizedLabel();
+		if (model instanceof MHandledItem) {
+			MHandledItem handledItem = (MHandledItem) model;
+			IEclipseContext context = getContext(model);
+			EBindingService bs = (EBindingService) context
+					.get(EBindingService.class.getName());
+			ParameterizedCommand cmd = handledItem.getWbCommand();
+			if (cmd != null && (text == null || text.length() == 0)) {
+				try {
+					text = cmd.getName();
+				} catch (NotDefinedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+			TriggerSequence sequence = bs.getBestSequenceFor(handledItem
+					.getWbCommand());
+			if (sequence != null) {
+				text = text + '\t' + sequence.format();
+			}
+			item.setText(text == null ? handledItem.getCommand().getElementId()
+					: text);
+		} else {
+			super.setItemText(model, item);
+		}
+	}
+
+	@Override
+	public void hookControllerLogic(MUIElement me) {
+		// If the item is a CHECK or RADIO update the model's state to match
+		super.hookControllerLogic(me);
+
+		// 'Execute' the operation if possible
+		if (me instanceof MHandledItem) {
+			final MHandledItem item = (MHandledItem) me;
+			final IEclipseContext lclContext = getContext(me);
+			MenuItem mi = (MenuItem) me.getWidget();
+			mi.addListener(SWT.Selection, new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(Event e) {
+					EHandlerService service = (EHandlerService) lclContext
+							.get(EHandlerService.class.getName());
+					ParameterizedCommand cmd = item.getWbCommand();
+					if (cmd == null) {
+						return;
+					}
+					final IEclipseContext staticContext = EclipseContextFactory
+							.create(HMI_STATIC_CONTEXT);
+					if (e != null) {
+						staticContext.set(Event.class, e);
+					}
+					ContributionsAnalyzer.populateModelInterfaces(item,
+							staticContext, item.getClass().getInterfaces());
+					try {
+						service.executeHandler(cmd, staticContext);
+					} finally {
+						staticContext.dispose();
+					}
+				}
+			});
+		}
+	}
+
+	public static ParameterizedCommand generateParameterizedCommand(
+			final MHandledItem item, final IEclipseContext lclContext) {
+		ECommandService cmdService = (ECommandService) lclContext
+				.get(ECommandService.class.getName());
+		Map<String, Object> parameters = null;
+		List<MParameter> modelParms = item.getParameters();
+		if (modelParms != null && !modelParms.isEmpty()) {
+			parameters = new HashMap<String, Object>();
+			for (MParameter mParm : modelParms) {
+				parameters.put(mParm.getName(), mParm.getValue());
+			}
+		}
+		ParameterizedCommand cmd = cmdService.createCommand(item.getCommand()
+				.getElementId(), parameters);
+		item.setWbCommand(cmd);
+		return cmd;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LayoutModifierToolControl.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LayoutModifierToolControl.java
new file mode 100644
index 0000000..e672008
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LayoutModifierToolControl.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import javax.annotation.PostConstruct;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * This is a specialized tool control used by the TrimBarLayout to modify the
+ * layout mechanisms.
+ */
+public class LayoutModifierToolControl {
+	@PostConstruct
+	void createWidget(Composite parent, MToolControl tc) {
+		Composite comp = new Composite(parent, SWT.NONE) {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Point computeSize(int wHint, int hHint, boolean flushCache) {
+				return new Point(0, 0);
+			}
+		};
+		comp.setSize(0, 0);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LazyStackRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LazyStackRenderer.java
new file mode 100644
index 0000000..6ef72e7
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/LazyStackRenderer.java
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2015 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@vogella.com> - Bug 441150
+ *     Fabio Zadrozny (fabiofz@gmail.com) - Bug 436763
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 457939
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MGenericStack;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * This class encapsulates the functionality necessary to manage stacks of parts
+ * in a 'lazy loading' manner. For these stacks only the currently 'active'
+ * child <b>most</b> be rendered so in this class we over ride that default
+ * behavior for processing the stack's contents to prevent all of the contents
+ * from being rendered, calling 'childAdded' instead. This not only saves time
+ * and SWT resources but is necessary in an IDE world where we must not
+ * arbitrarily cause plug-in loading.
+ *
+ */
+public abstract class LazyStackRenderer extends SWTPartRenderer {
+	private EventHandler lazyLoader = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
+
+			if (!(element instanceof MGenericStack<?>))
+				return;
+
+			@SuppressWarnings("unchecked")
+			MGenericStack<MUIElement> stack = (MGenericStack<MUIElement>) element;
+			if (stack.getRenderer() != LazyStackRenderer.this)
+				return;
+			LazyStackRenderer lsr = (LazyStackRenderer) stack.getRenderer();
+
+			// Gather up the elements that are being 'hidden' by this change
+			MUIElement oldSel = (MUIElement) event
+					.getProperty(UIEvents.EventTags.OLD_VALUE);
+			if (oldSel != null) {
+				hideElementRecursive(oldSel);
+			}
+
+			if (stack.getSelectedElement() != null)
+				lsr.showTab(stack.getSelectedElement());
+		}
+	};
+
+	public void init(IEventBroker eventBroker) {
+		// Ensure that there only ever *one* listener. Each subclass
+		// will call this method
+		eventBroker.unsubscribe(lazyLoader);
+
+		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT,
+				lazyLoader);
+	}
+
+	/**
+	 * @param eventBroker
+	 */
+	public void contextDisposed(IEventBroker eventBroker) {
+		eventBroker.unsubscribe(lazyLoader);
+	}
+
+	@Override
+	public void postProcess(MUIElement element) {
+		if (!(element instanceof MPerspectiveStack)
+				&& (!(element instanceof MGenericStack<?>) || isMinimizedStack(element))) {
+			return;
+		}
+
+		@SuppressWarnings("unchecked")
+		MGenericStack<MUIElement> stack = (MGenericStack<MUIElement>) element;
+		MUIElement selPart = stack.getSelectedElement();
+		if (selPart != null) {
+			showTab(selPart);
+		} else if (stack.getChildren().size() > 0) {
+			// Set the selection to the first renderable element
+			for (MUIElement kid : stack.getChildren()) {
+				if (kid.isToBeRendered() && kid.isVisible()) {
+					stack.setSelectedElement(kid);
+					break;
+				}
+			}
+		}
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> me) {
+		// Lazy Loading: here we only process the contents through childAdded,
+		// we specifically do not render them
+		IPresentationEngine renderer = (IPresentationEngine) context
+				.get(IPresentationEngine.class.getName());
+
+		for (MUIElement element : me.getChildren()) {
+			if (!element.isToBeRendered() || !element.isVisible())
+				continue;
+			boolean lazy = true;
+
+			// Special case: we also render any placeholder that refers to
+			// an *existing* part, this doesn't break lazy loading since the
+			// part is already there...see bug 378138 for details
+			if (element instanceof MPlaceholder) {
+				MPlaceholder ph = (MPlaceholder) element;
+				if (ph.getRef() instanceof MPart
+						&& ph.getRef().getWidget() != null) {
+					lazy = false;
+				}
+			}
+
+			if (lazy) {
+				createTab(me, element);
+			} else {
+				renderer.createGui(element);
+			}
+		}
+	}
+
+	/**
+	 * This method is necessary to allow the parent container to show affordance
+	 * (i.e. tabs) for child elements -without- creating the actual part
+	 *
+	 * @param me
+	 *            The parent model element
+	 * @param part
+	 *            The child to show the affordance for
+	 */
+	protected void createTab(MElementContainer<MUIElement> me, MUIElement part) {
+	}
+
+	protected void showTab(MUIElement element) {
+		// Now process any newly visible elements
+		MUIElement curSel = element.getParent().getSelectedElement();
+		if (curSel != null) {
+			showElementRecursive(curSel);
+		}
+	}
+
+	private void hideElementRecursive(MUIElement element) {
+		if (element == null || element.getWidget() == null)
+			return;
+
+		if (element instanceof MPlaceholder) {
+			MPlaceholder ph = (MPlaceholder) element;
+			element = ph.getRef();
+		}
+
+		// Hide any floating windows
+		if (element instanceof MWindow && element.getWidget() != null) {
+			element.setVisible(false);
+		}
+
+		if (element instanceof MGenericStack<?>) {
+			// For stacks only the currently selected elements are being hidden
+			MGenericStack<?> container = (MGenericStack<?>) element;
+			MUIElement curSel = container.getSelectedElement();
+			hideElementRecursive(curSel);
+		} else if (element instanceof MElementContainer<?>) {
+			MElementContainer<?> container = (MElementContainer<?>) element;
+			for (MUIElement childElement : container.getChildren()) {
+				hideElementRecursive(childElement);
+			}
+
+			// OK, now process detached windows
+			if (element instanceof MWindow) {
+				for (MWindow w : ((MWindow) element).getWindows()) {
+					hideElementRecursive(w);
+				}
+			} else if (element instanceof MPerspective) {
+				for (MWindow w : ((MPerspective) element).getWindows()) {
+					hideElementRecursive(w);
+				}
+			}
+		}
+	}
+
+	private void showElementRecursive(MUIElement element) {
+		if (!element.isToBeRendered())
+			return;
+
+		if (element instanceof MPartStack
+				&& element.getRenderer() instanceof StackRenderer) {
+			MPartStack stackModel = (MPartStack) element;
+			StackRenderer sr = (StackRenderer) element.getRenderer();
+			CTabFolder ctf = (CTabFolder) element.getWidget();
+
+			MUIElement curSel = stackModel.getSelectedElement();
+			MPart part = (MPart) ((curSel instanceof MPlaceholder) ? ((MPlaceholder) curSel)
+					.getRef() : curSel);
+
+			// Ensure that the placeholder's ref is set correctly before
+			// adjusting its toolbar
+			if (curSel instanceof MPlaceholder) {
+				part.setCurSharedRef((MPlaceholder) curSel);
+			}
+			sr.adjustTopRight(ctf);
+		}
+
+		if (element instanceof MPlaceholder && element.getWidget() != null) {
+			MPlaceholder ph = (MPlaceholder) element;
+			MUIElement ref = ph.getRef();
+			ref.setCurSharedRef(ph);
+
+			Composite phComp = (Composite) ph.getWidget();
+			Control refCtrl = (Control) ph.getRef().getWidget();
+
+			// If the parent changes we need to adjust the bounds of the child
+			// we do not call layout() because this could lead to
+			// a big amount of layout calls in unrelated places e.g. none
+			// visible children of a CTabFolder (see 460745)
+			if (refCtrl.getParent() != phComp) {
+				refCtrl.setParent(phComp);
+				refCtrl.setSize(phComp.getSize());
+			}
+
+			element = ref;
+		}
+
+		if (element instanceof MContext) {
+			IEclipseContext context = ((MContext) element).getContext();
+			if (context != null) {
+				IEclipseContext newParentContext = modelService
+						.getContainingContext(element);
+				if (context.getParent() != newParentContext) {
+					//					System.out.println("Update Context: " + context.toString() //$NON-NLS-1$
+					//							+ " new parent: " + newParentContext.toString()); //$NON-NLS-1$
+					context.setParent(newParentContext);
+				}
+			}
+		}
+
+		Shell layoutShellLater = null;
+		// Show any floating windows
+		if (element instanceof MWindow && element.getWidget() != null) {
+			int visCount = 0;
+			for (MUIElement kid : ((MWindow) element).getChildren()) {
+				if (kid.isToBeRendered() && kid.isVisible())
+					visCount++;
+			}
+			if (visCount > 0) {
+				element.setVisible(true);
+				Object widget = element.getWidget();
+				if (widget instanceof Shell) {
+					Shell shell = (Shell) widget;
+					layoutShellLater = shell;
+				}
+			}
+		}
+
+		if (element instanceof MGenericStack<?>) {
+			// For stacks only the currently selected elements are being visible
+			MGenericStack<?> container = (MGenericStack<?>) element;
+			MUIElement curSel = container.getSelectedElement();
+			if (curSel == null && container.getChildren().size() > 0)
+				curSel = container.getChildren().get(0);
+			if (curSel != null)
+				showElementRecursive(curSel);
+		} else if (element instanceof MElementContainer<?>) {
+			MElementContainer<?> container = (MElementContainer<?>) element;
+			List<MUIElement> kids = new ArrayList<MUIElement>(
+					container.getChildren());
+			for (MUIElement childElement : kids) {
+				showElementRecursive(childElement);
+			}
+
+			// OK, now process detached windows
+			if (element instanceof MWindow) {
+				for (MWindow w : ((MWindow) element).getWindows()) {
+					showElementRecursive(w);
+				}
+			} else if (element instanceof MPerspective) {
+				for (MWindow w : ((MPerspective) element).getWindows()) {
+					showElementRecursive(w);
+				}
+			}
+		}
+
+		// i.e.: Bug 436763: after we make items visible, if we made a new
+		// floating shell visible, we have to re-layout it for its contents to
+		// become correct.
+		if (layoutShellLater != null) {
+			layoutShellLater.layout(true, true);
+		}
+	}
+
+	private boolean isMinimizedStack(MUIElement stack) {
+		return stack.getTags().contains(IPresentationEngine.MINIMIZED)
+				&& !stack.getTags().contains(IPresentationEngine.ACTIVE);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuItemRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuItemRenderer.java
new file mode 100644
index 0000000..ab28d41
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuItemRenderer.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import java.util.HashMap;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.internal.expressions.ReferenceExpression;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator;
+import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Create a contribute part.
+ */
+public abstract class MenuItemRenderer extends SWTPartRenderer {
+	static class VisibleRAT extends RunAndTrack {
+		Expression exp;
+		MMenuItem item;
+		ExpressionContext ec;
+		boolean participating = true;
+
+		public VisibleRAT(MMenuItem i, Expression e, IEclipseContext c) {
+			exp = e;
+			item = i;
+			ec = new ExpressionContext(c);
+		}
+
+		@Override
+		public boolean changed(IEclipseContext context) {
+			try {
+				item.setVisible(EvaluationResult.FALSE != exp.evaluate(ec));
+			} catch (CoreException e) {
+				item.setVisible(false);
+				WorkbenchSWTActivator.trace(
+						"/trace/menus", "VisibleRAT failed", e); //$NON-NLS-1$//$NON-NLS-2$
+			}
+			return participating;
+		}
+	}
+
+	private HashMap<MMenuItem, Expression> menuItemToExpression = new HashMap<MMenuItem, Expression>();
+	private HashMap<MMenuItem, VisibleRAT> menuItemToRAT = new HashMap<MMenuItem, VisibleRAT>();
+
+	@Inject
+	Logger logger;
+	@Inject
+	IEventBroker eventBroker;
+	private EventHandler itemUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MMenuItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			MenuItem menuItem = (MenuItem) itemModel.getWidget();
+
+			// No widget == nothing to update
+			if (menuItem == null)
+				return;
+
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			if (UIEvents.UILabel.LABEL.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+				setItemText(itemModel, menuItem);
+			} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+				menuItem.setImage(getImage(itemModel));
+			}
+		}
+	};
+
+	private EventHandler selectionUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MToolItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			MenuItem menuItem = (MenuItem) itemModel.getWidget();
+			if (menuItem != null) {
+				menuItem.setSelection(itemModel.isSelected());
+			}
+		}
+	};
+
+	private EventHandler enabledUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MMenuItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			MenuItem menuItem = (MenuItem) itemModel.getWidget();
+			if (menuItem != null) {
+				menuItem.setEnabled(itemModel.isEnabled());
+			}
+		}
+	};
+
+	@PostConstruct
+	public void init() {
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_SELECTED, selectionUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_ENABLED, enabledUpdater);
+	}
+
+	@PreDestroy
+	public void contextDisposed() {
+		eventBroker.unsubscribe(itemUpdater);
+		eventBroker.unsubscribe(selectionUpdater);
+		eventBroker.unsubscribe(enabledUpdater);
+	}
+
+	protected void processVisible(MMenuItem item) {
+		if (menuItemToExpression.get(item) != null) {
+			return;
+		}
+		MCoreExpression exp = (MCoreExpression) item.getVisibleWhen();
+		Expression ref = null;
+		if (exp.getCoreExpression() instanceof Expression) {
+			ref = (Expression) exp.getCoreExpression();
+		} else {
+			ref = new ReferenceExpression(exp.getCoreExpressionId());
+			exp.setCoreExpression(ref);
+		}
+		menuItemToExpression.put(item, ref);
+		IEclipseContext itemContext = getContext(item);
+		VisibleRAT rat = new VisibleRAT(item, ref, itemContext);
+		menuItemToRAT.put(item, rat);
+		itemContext.runAndTrack(rat);
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		// Since there's no place to 'store' a child that's not in a menu
+		// we'll blow it away and re-create on an add
+		Widget widget = (Widget) child.getWidget();
+		if (widget != null && !widget.isDisposed())
+			widget.dispose();
+		menuItemToExpression.remove(child);
+		VisibleRAT rat = menuItemToRAT.remove(child);
+		if (rat != null) {
+			rat.participating = false;
+		}
+	}
+
+	protected void setItemText(MMenuItem model, MenuItem item) {
+		String text = model.getLocalizedLabel();
+		if (text == null) {
+			text = ""; //$NON-NLS-1$
+		}
+		item.setText(text);
+	}
+
+	@Override
+	public void hookControllerLogic(MUIElement me) {
+		// If the item is a CHECK or RADIO update the model's state to match
+		if (me instanceof MItem) {
+			final MItem item = (MItem) me;
+			if (item.getType() == ItemType.CHECK
+					|| item.getType() == ItemType.RADIO) {
+				MenuItem ti = (MenuItem) me.getWidget();
+				ti.addSelectionListener(new SelectionListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						item.setSelected(((MenuItem) e.widget).getSelection());
+					}
+
+					@Override
+					public void widgetDefaultSelected(SelectionEvent e) {
+						item.setSelected(((MenuItem) e.widget).getSelection());
+					}
+				});
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerHideProcessor.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerHideProcessor.java
new file mode 100644
index 0000000..3d48923
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerHideProcessor.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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
+ *     Marco Descher <marco@descher.at> - Bug 403081, 403083
+ *     Bruce Skingle <Bruce.Skingle@immutify.com> - Bug 442570
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.di.AboutToHide;
+import org.eclipse.e4.ui.model.application.ui.menu.MDynamicMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.action.IMenuListener2;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.widgets.Menu;
+
+/**
+ * <code>MenuManagerHideProcessor</code> provides hooks for renderer processing
+ * before and after the <code>MenuManager</code> calls out to its
+ * <code>IMenuManagerListener2</code> for the <code>menuAboutToHide</code>
+ * events.
+ */
+public class MenuManagerHideProcessor implements IMenuListener2 {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	@Inject
+	private MenuManagerRenderer renderer;
+
+	@Inject
+	private EModelService modelService;
+
+	@Override
+	public void menuAboutToShow(IMenuManager manager) {
+		if (!(manager instanceof MenuManager)) {
+			return;
+		}
+		MenuManager menuManager = (MenuManager) manager;
+		final MMenu menuModel = renderer.getMenuModel(menuManager);
+		final Menu menu = menuManager.getMenu();
+		if (menuModel instanceof MPopupMenu) {
+			hidePopup(menu, (MPopupMenu) menuModel, menuManager);
+		}
+		if (menuModel != null && menu != null)
+			processDynamicElements((MenuManager) manager, menu, menuModel);
+	}
+
+	/**
+	 * Process dynamic menu contributions provided by
+	 * {@link MDynamicMenuContribution} application model elements
+	 *
+	 * @param menu
+	 * @param menuModel
+	 *
+	 */
+	private void processDynamicElements(final MenuManager menuManager, Menu menu, final MMenu menuModel) {
+		// We need to make a copy of the dynamic items which need to be removed
+		// because the actual remove happens asynchronously.
+		final Map<MDynamicMenuContribution, ArrayList<MMenuElement>> toBeHidden = new HashMap<MDynamicMenuContribution, ArrayList<MMenuElement>>();
+
+		for (MMenuElement currentMenuElement : menuModel.getChildren()) {
+			if (currentMenuElement instanceof MDynamicMenuContribution) {
+
+				final Map<String, Object> storageMap = currentMenuElement.getTransientData();
+				@SuppressWarnings("unchecked")
+				ArrayList<MMenuElement> mel = (ArrayList<MMenuElement>) storageMap
+						.get(MenuManagerShowProcessor.DYNAMIC_ELEMENT_STORAGE_KEY);
+
+				toBeHidden.put((MDynamicMenuContribution) currentMenuElement, mel);
+
+				// make existing entries for this dynamic contribution item
+				// invisible if there are any
+				if (mel != null && mel.size() > 0) {
+
+					for (MMenuElement item : mel) {
+						item.setVisible(false);
+					}
+				}
+				currentMenuElement.getTransientData().remove(MenuManagerShowProcessor.DYNAMIC_ELEMENT_STORAGE_KEY);
+			}
+		}
+
+		if (!menu.isDisposed()) {
+			menu.getDisplay().asyncExec(new Runnable() {
+				@Override
+				public void run() {
+					for (Entry<MDynamicMenuContribution, ArrayList<MMenuElement>> entry : toBeHidden.entrySet()) {
+						MDynamicMenuContribution currentMenuElement = entry.getKey();
+						Object contribution = currentMenuElement.getObject();
+						IEclipseContext dynamicMenuContext = EclipseContextFactory.create();
+
+						ArrayList<MMenuElement> mel = entry.getValue();
+
+						dynamicMenuContext.set(List.class, mel);
+						IEclipseContext parentContext = modelService.getContainingContext(currentMenuElement);
+						ContextInjectionFactory.invoke(contribution, AboutToHide.class, parentContext,
+								dynamicMenuContext, null);
+						dynamicMenuContext.dispose();
+						// remove existing entries for this dynamic
+						// contribution item if there are any
+						if (mel != null && mel.size() > 0) {
+							renderer.removeDynamicMenuContributions(menuManager, menuModel, mel);
+						}
+					}
+				}
+			});
+		}
+	}
+
+	@Override
+	public void menuAboutToHide(IMenuManager manager) {
+	}
+
+	private void hidePopup(Menu menu, MPopupMenu menuModel,
+			MenuManager menuManager) {
+		final IEclipseContext popupContext = menuModel.getContext();
+		final IEclipseContext originalChild = (IEclipseContext) popupContext
+				.get(MenuManagerRendererFilter.TMP_ORIGINAL_CONTEXT);
+		popupContext.remove(MenuManagerRendererFilter.TMP_ORIGINAL_CONTEXT);
+		if (!menu.isDisposed()) {
+			menu.getDisplay().asyncExec(new Runnable() {
+				@Override
+				public void run() {
+					if (originalChild == null) {
+						popupContext.deactivate();
+					} else {
+						originalChild.activate();
+					}
+				}
+			});
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java
new file mode 100644
index 0000000..d1fa10b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java
@@ -0,0 +1,1195 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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
+ *     Marco Descher <marco@descher.at> - Bug 389063, Bug 398865, Bug 398866, Bug 405471
+ *     Sopot Cela <sopotcela@gmail.com>
+ *     Steven Spungin <steven@spungin.tv> - Bug 437747
+ *     Alan Staves <alan.staves@microfocus.com> - Bug 435274
+ *     Patrick Naish <patrick.naish@microfocus.com> - Bug 435274
+ *     René Brandstetter <Rene.Brandstetter@gmx.net> - Bug 378849
+ *     Andrey Loskutov <loskutov@gmx.de> - Bug 378849
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 460556
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 391430
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil;
+import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+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.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MDynamicMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.ElementContainer;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.action.AbstractGroupMarker;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.SubContributionItem;
+import org.eclipse.jface.internal.MenuManagerEventHelper;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Create a contribute part.
+ */
+public class MenuManagerRenderer extends SWTPartRenderer {
+	public static final String VISIBILITY_IDENTIFIER = "IIdentifier"; //$NON-NLS-1$
+	private static final String NO_LABEL = "UnLabled"; //$NON-NLS-1$
+	public static final String GROUP_MARKER = "org.eclipse.jface.action.GroupMarker.GroupMarker(String)"; //$NON-NLS-1$
+
+	private Map<MMenu, MenuManager> modelToManager = new HashMap<MMenu, MenuManager>();
+	private Map<MenuManager, MMenu> managerToModel = new HashMap<MenuManager, MMenu>();
+
+	private Map<MMenuElement, IContributionItem> modelToContribution = new HashMap<MMenuElement, IContributionItem>();
+	private Map<IContributionItem, MMenuElement> contributionToModel = new HashMap<IContributionItem, MMenuElement>();
+
+	private Map<MMenuElement, ContributionRecord> modelContributionToRecord = new HashMap<MMenuElement, ContributionRecord>();
+	private Map<MMenuElement, ArrayList<ContributionRecord>> sharedElementToRecord = new HashMap<MMenuElement, ArrayList<ContributionRecord>>();
+
+	private Collection<IContributionManager> mgrToUpdate = new LinkedHashSet<>();
+
+	@Inject
+	private Logger logger;
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	IEventBroker eventBroker;
+	private EventHandler itemUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MMenuItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+
+			IContributionItem ici = getContribution(itemModel);
+			if (ici == null) {
+				return;
+			}
+
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			if (UIEvents.UILabel.LABEL.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+				ici.update();
+			} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+				ici.update();
+			}
+		}
+	};
+
+	private EventHandler labelUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MMenu
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenu))
+				return;
+
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			MMenu model = (MMenu) event.getProperty(UIEvents.EventTags.ELEMENT);
+			MenuManager manager = getManager(model);
+			if ((manager == null))
+				return;
+			if (UIEvents.UILabel.LABEL.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+				manager.setMenuText(getText(model));
+				manager.update(IAction.TEXT);
+			}
+			if (UIEvents.UILabel.ICONURI.equals(attName)) {
+				manager.setImageDescriptor(getImageDescriptor(model));
+				manager.update(IAction.IMAGE);
+			}
+		}
+	};
+
+	private EventHandler toBeRenderedUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			if (element instanceof MMenuItem) {
+				MMenuItem itemModel = (MMenuItem) element;
+				if (UIEvents.UIElement.TOBERENDERED.equals(attName)) {
+					Object obj = itemModel.getParent();
+					if (!(obj instanceof MMenu)) {
+						return;
+					}
+					MenuManager parent = getManager((MMenu) obj);
+					if (itemModel.isToBeRendered()) {
+						if (parent != null) {
+							modelProcessSwitch(parent, itemModel);
+						}
+					} else {
+						IContributionItem ici = getContribution(itemModel);
+						clearModelToContribution(itemModel, ici);
+						if (ici != null && parent != null) {
+							parent.remove(ici);
+						}
+						if (ici != null) {
+							ici.dispose();
+						}
+					}
+				}
+			}
+
+			if (element instanceof MPart) {
+				MPart part = (MPart) element;
+				if (UIEvents.UIElement.TOBERENDERED.equals(attName)) {
+					boolean tbr = (Boolean) event
+							.getProperty(UIEvents.EventTags.NEW_VALUE);
+					if (!tbr) {
+						List<MMenu> menus = part.getMenus();
+						for (MMenu menu : menus) {
+							if (menu instanceof MPopupMenu)
+								unlinkMenu(menu);
+						}
+					}
+				}
+			}
+
+			if (UIEvents.UIElement.VISIBLE.equals(attName)) {
+				if (element instanceof MMenu) {
+					MMenu menuModel = (MMenu) element;
+					MenuManager manager = getManager(menuModel);
+					if (manager == null) {
+						return;
+					}
+					manager.setVisible(menuModel.isVisible());
+					if (manager.getParent() != null) {
+						manager.getParent().markDirty();
+						scheduleManagerUpdate(manager.getParent());
+					}
+				} else if (element instanceof MMenuElement) {
+					MMenuElement itemModel = (MMenuElement) element;
+					Object obj = getContribution(itemModel);
+					if (!(obj instanceof ContributionItem)) {
+						return;
+					}
+					ContributionItem item = (ContributionItem) obj;
+					item.setVisible(itemModel.isVisible());
+					if (item.getParent() != null) {
+						item.getParent().markDirty();
+						scheduleManagerUpdate(item.getParent());
+					}
+				}
+			}
+		}
+	};
+
+	private EventHandler selectionUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MToolItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			IContributionItem ici = getContribution(itemModel);
+			if (ici != null) {
+				ici.update();
+			}
+		}
+	};
+
+	private EventHandler enabledUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MMenuItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
+				return;
+
+			MMenuItem itemModel = (MMenuItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			IContributionItem ici = getContribution(itemModel);
+			if (ici != null) {
+				ici.update();
+			}
+		}
+	};
+
+	private MenuManagerRendererFilter rendererFilter;
+
+	@PostConstruct
+	public void init() {
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, labelUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_SELECTED, selectionUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_ENABLED, enabledUpdater);
+		eventBroker
+				.subscribe(UIEvents.UIElement.TOPIC_ALL, toBeRenderedUpdater);
+
+		context.set(MenuManagerRenderer.class, this);
+		Display display = context.get(Display.class);
+		rendererFilter = ContextInjectionFactory.make(
+				MenuManagerRendererFilter.class, context);
+		display.addFilter(SWT.Show, rendererFilter);
+		display.addFilter(SWT.Hide, rendererFilter);
+		display.addFilter(SWT.Dispose, rendererFilter);
+		context.set(MenuManagerRendererFilter.class, rendererFilter);
+		MenuManagerEventHelper.getInstance().setShowHelper(
+				ContextInjectionFactory.make(MenuManagerShowProcessor.class,
+						context));
+		MenuManagerEventHelper.getInstance().setHideHelper(
+				ContextInjectionFactory.make(MenuManagerHideProcessor.class,
+						context));
+
+	}
+
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void subscribeTopicChildAdded(@UIEventTopic(ElementContainer.TOPIC_CHILDREN) Event event) {
+		// Ensure that this event is for a MMenuItem
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenu)) {
+			return;
+		}
+		MMenu menuModel = (MMenu) event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (UIEvents.isADD(event)) {
+			Object obj = menuModel;
+			processContents((MElementContainer<MUIElement>) obj);
+		}
+	}
+
+	@PreDestroy
+	public void contextDisposed() {
+		eventBroker.unsubscribe(itemUpdater);
+		eventBroker.unsubscribe(labelUpdater);
+		eventBroker.unsubscribe(selectionUpdater);
+		eventBroker.unsubscribe(enabledUpdater);
+		eventBroker.unsubscribe(toBeRenderedUpdater);
+
+		ContextInjectionFactory.uninject(MenuManagerEventHelper.getInstance()
+				.getShowHelper(),
+				context);
+		MenuManagerEventHelper.getInstance().setShowHelper(null);
+		ContextInjectionFactory.uninject(
+MenuManagerEventHelper.getInstance()
+				.getHideHelper(),
+				context);
+		MenuManagerEventHelper.getInstance().setHideHelper(null);
+
+		context.remove(MenuManagerRendererFilter.class);
+		Display display = context.get(Display.class);
+		if (display != null && !display.isDisposed() && rendererFilter != null) {
+			display.removeFilter(SWT.Show, rendererFilter);
+			display.removeFilter(SWT.Hide, rendererFilter);
+			display.removeFilter(SWT.Dispose, rendererFilter);
+		}
+		if (rendererFilter != null) {
+			ContextInjectionFactory.uninject(rendererFilter, context);
+			rendererFilter = null;
+		}
+		context.remove(MenuManagerRenderer.class);
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MMenu))
+			return null;
+
+		final MMenu menuModel = (MMenu) element;
+		Menu newMenu = null;
+		MenuManager menuManager = null;
+		boolean menuBar = false;
+
+		if (parent instanceof Decorations) {
+			MUIElement container = (MUIElement) ((EObject) element)
+					.eContainer();
+			if (container instanceof MWindow) {
+				menuManager = getManager(menuModel);
+				if (menuManager == null) {
+					menuManager = new MenuManager(NO_LABEL,
+							menuModel.getElementId());
+					linkModelToManager(menuModel, menuManager);
+				}
+				newMenu = menuManager.createMenuBar((Decorations) parent);
+				((Decorations) parent).setMenuBar(newMenu);
+				newMenu.setData(menuManager);
+				menuBar = true;
+			} else {
+				menuManager = getManager(menuModel);
+				if (menuManager == null) {
+					menuManager = new MenuManager(NO_LABEL,
+							menuModel.getElementId());
+					linkModelToManager(menuModel, menuManager);
+				}
+				newMenu = menuManager.createContextMenu((Control) parent);
+				// we can't be sure this is the correct parent.
+				// ((Control) parent).setMenu(newMenu);
+				newMenu.setData(menuManager);
+			}
+		} else if (parent instanceof Menu) {
+			// Object data = ((Menu) parent).getData();
+			logger.debug(new Exception(), "Trying to render a sub menu " //$NON-NLS-1$
+					+ menuModel + "\n\t" + parent); //$NON-NLS-1$
+			return null;
+
+		} else if (parent instanceof Control) {
+			menuManager = getManager(menuModel);
+			if (menuManager == null) {
+				menuManager = new MenuManager(NO_LABEL,
+						menuModel.getElementId());
+				linkModelToManager(menuModel, menuManager);
+			}
+			newMenu = menuManager.createContextMenu((Control) parent);
+			// we can't be sure this is the correct parent.
+			// ((Control) parent).setMenu(newMenu);
+			newMenu.setData(menuManager);
+		}
+		if (!menuManager.getRemoveAllWhenShown()) {
+			processContributions(menuModel, menuModel.getElementId(), menuBar,
+					menuModel instanceof MPopupMenu);
+		}
+		if (newMenu != null) {
+			newMenu.addDisposeListener(new DisposeListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					cleanUp(menuModel);
+					MenuManager manager = getManager(menuModel);
+					if (manager != null) {
+						manager.markDirty();
+					}
+				}
+			});
+		}
+		return newMenu;
+	}
+
+	/**
+	 * @param menuModel
+	 */
+	public void cleanUp(MMenu menuModel) {
+		for (MMenuElement childElement : menuModel.getChildren()) {
+			if (childElement instanceof MMenu) {
+				cleanUp((MMenu) childElement);
+			}
+		}
+		Collection<ContributionRecord> vals = modelContributionToRecord
+				.values();
+		List<ContributionRecord> disposedRecords = new ArrayList<ContributionRecord>();
+		for (ContributionRecord record : vals
+				.toArray(new ContributionRecord[vals.size()])) {
+			if (record.menuModel == menuModel) {
+				record.dispose();
+				for (MMenuElement copy : record.getGeneratedElements()) {
+					cleanUpCopy(record, copy);
+				}
+				for (MMenuElement copy : record.getSharedElements()) {
+					cleanUpCopy(record, copy);
+				}
+				record.getGeneratedElements().clear();
+				record.getSharedElements().clear();
+				disposedRecords.add(record);
+			}
+		}
+
+		Iterator<Entry<MMenuElement, ContributionRecord>> iterator = modelContributionToRecord
+				.entrySet().iterator();
+		for (; iterator.hasNext();) {
+			Entry<MMenuElement, ContributionRecord> entry = iterator.next();
+			ContributionRecord record = entry.getValue();
+			if (disposedRecords.contains(record))
+				iterator.remove();
+		}
+	}
+
+	public void cleanUpCopy(ContributionRecord record, MMenuElement copy) {
+		modelContributionToRecord.remove(copy);
+		if (copy instanceof MMenu) {
+			MMenu menuCopy = (MMenu) copy;
+			cleanUp(menuCopy);
+			MenuManager copyManager = getManager(menuCopy);
+			clearModelToManager(menuCopy, copyManager);
+			if (copyManager != null) {
+				record.getManagerForModel().remove(copyManager);
+				copyManager.dispose();
+			}
+		} else {
+			IContributionItem ici = getContribution(copy);
+			clearModelToContribution(copy, ici);
+			if (ici != null) {
+				record.getManagerForModel().remove(ici);
+			}
+		}
+	}
+
+	/**
+	 * @param menuModel
+	 * @param isMenuBar
+	 * @param isPopup
+	 */
+	public void processContributions(MMenu menuModel, String elementId,
+			boolean isMenuBar, boolean isPopup) {
+		if (elementId == null) {
+			return;
+		}
+		final ArrayList<MMenuContribution> toContribute = new ArrayList<MMenuContribution>();
+		ContributionsAnalyzer.XXXgatherMenuContributions(menuModel,
+				application.getMenuContributions(), elementId, toContribute,
+				null, isPopup);
+		generateContributions(menuModel, toContribute, isMenuBar);
+		for (MMenuElement element : menuModel.getChildren()) {
+			if (element instanceof MMenu) {
+				processContributions((MMenu) element, element.getElementId(),
+						false, isPopup);
+			}
+		}
+	}
+
+	/**
+	 * @param menuModel
+	 * @param toContribute
+	 */
+	private void generateContributions(MMenu menuModel,
+			ArrayList<MMenuContribution> toContribute, boolean menuBar) {
+		HashSet<String> existingMenuIds = new HashSet<String>();
+		HashSet<String> existingSeparatorNames = new HashSet<String>();
+		for (MMenuElement child : menuModel.getChildren()) {
+			String elementId = child.getElementId();
+			if (child instanceof MMenu && elementId != null) {
+				existingMenuIds.add(elementId);
+			} else if (child instanceof MMenuSeparator && elementId != null) {
+				existingSeparatorNames.add(elementId);
+			}
+		}
+
+		MenuManager manager = getManager(menuModel);
+		boolean done = toContribute.size() == 0;
+		while (!done) {
+			ArrayList<MMenuContribution> curList = new ArrayList<MMenuContribution>(
+					toContribute);
+			int retryCount = toContribute.size();
+			toContribute.clear();
+
+			for (MMenuContribution menuContribution : curList) {
+				if (!processAddition(menuModel, manager, menuContribution,
+						existingMenuIds, existingSeparatorNames, menuBar)) {
+					toContribute.add(menuContribution);
+				}
+			}
+
+			// We're done if the retryList is now empty (everything done) or
+			// if the list hasn't changed at all (no hope)
+			done = (toContribute.size() == 0)
+					|| (toContribute.size() == retryCount);
+		}
+	}
+
+	/**
+	 * @param menuModel
+	 * @param manager
+	 * @param menuContribution
+	 * @return true if the menuContribution was processed
+	 */
+	private boolean processAddition(MMenu menuModel, final MenuManager manager,
+			MMenuContribution menuContribution,
+			final HashSet<String> existingMenuIds,
+			HashSet<String> existingSeparatorNames, boolean menuBar) {
+		final ContributionRecord record = new ContributionRecord(menuModel,
+				menuContribution, this);
+		if (!record.mergeIntoModel()) {
+			return false;
+		}
+		if (menuBar || isPartMenu(menuModel)) {
+			final IEclipseContext parentContext = getContext(menuModel);
+			parentContext.runAndTrack(new RunAndTrack() {
+				@Override
+				public boolean changed(IEclipseContext context) {
+					record.updateVisibility(parentContext.getActiveLeaf());
+					scheduleManagerUpdate(manager);
+					return true;
+				}
+			});
+		}
+		return true;
+	}
+
+	private boolean isPartMenu(MMenu menuModel) {
+		// don't want popup menus as their visibility does not need to be
+		// tracked by a separate RunAndTrack
+		return !(menuModel instanceof MPopupMenu)
+				&& ((EObject) menuModel).eContainer() instanceof MPart;
+	}
+
+	private static ArrayList<ContributionRecord> DEFAULT = new ArrayList<ContributionRecord>();
+
+	public ArrayList<ContributionRecord> getList(MMenuElement item) {
+		ArrayList<ContributionRecord> tmp = sharedElementToRecord.get(item);
+		if (tmp == null) {
+			tmp = DEFAULT;
+		}
+		return tmp;
+	}
+
+	public void addRecord(MMenuElement item, ContributionRecord rec) {
+		ArrayList<ContributionRecord> tmp = sharedElementToRecord.get(item);
+		if (tmp == null) {
+			tmp = new ArrayList<ContributionRecord>();
+			sharedElementToRecord.put(item, tmp);
+		}
+		tmp.add(rec);
+	}
+
+	public void removeRecord(MMenuElement item, ContributionRecord rec) {
+		ArrayList<ContributionRecord> tmp = sharedElementToRecord.get(item);
+		if (tmp != null) {
+			tmp.remove(rec);
+			if (tmp.isEmpty()) {
+				sharedElementToRecord.remove(item);
+			}
+		}
+	}
+
+	void removeMenuContributions(final MMenu menuModel,
+			final ArrayList<MMenuElement> menuContributionsToRemove) {
+		for (MMenuElement item : menuContributionsToRemove) {
+			menuModel.getChildren().remove(item);
+		}
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		// I can either simply stop processing, or we can walk the model
+		// ourselves like the "old" days
+		// EMF gives us null lists if empty
+		if (container == null)
+			return;
+
+		// this is in direct violation of good programming
+		MenuManager parentManager = getManager((MMenu) ((Object) container));
+		if (parentManager == null) {
+			return;
+		}
+		// Process any contents of the newly created ME
+		List<MUIElement> parts = container.getChildren();
+		if (parts != null) {
+			MUIElement[] plist = parts.toArray(new MUIElement[parts.size()]);
+			for (int i = 0; i < plist.length; i++) {
+				MUIElement childME = plist[i];
+				modelProcessSwitch(parentManager, (MMenuElement) childME);
+			}
+		}
+		scheduleManagerUpdate(parentManager);
+	}
+
+	private void addToManager(MenuManager parentManager, MMenuElement model,
+			IContributionItem menuManager) {
+		MElementContainer<MUIElement> parent = model.getParent();
+		// technically this shouldn't happen
+		if (parent == null) {
+			parentManager.add(menuManager);
+		} else {
+			int index = parent.getChildren().indexOf(model);
+			// shouldn't be -1, but better safe than sorry
+			if (index > parentManager.getSize() || index == -1) {
+				parentManager.add(menuManager);
+			} else {
+				parentManager.insert(index, menuManager);
+			}
+		}
+	}
+
+	/**
+	 * @param parentManager
+	 * @param menuModel
+	 */
+	private void processMenu(MenuManager parentManager, MMenu menuModel) {
+		MenuManager menuManager = getManager(menuModel);
+		if (menuManager == null) {
+			menuModel.setRenderer(this);
+			String menuText = getText(menuModel);
+			ImageDescriptor desc = getImageDescriptor(menuModel);
+			menuManager = new MenuManager(menuText, desc,
+					menuModel.getElementId());
+			linkModelToManager(menuModel, menuManager);
+			menuManager.setVisible(menuModel.isVisible());
+			addToManager(parentManager, menuModel, menuManager);
+		}
+		// processContributions(menuModel, false);
+		List<MMenuElement> parts = menuModel.getChildren();
+		if (parts != null) {
+			MMenuElement[] plist = parts
+					.toArray(new MMenuElement[parts.size()]);
+			for (int i = 0; i < plist.length; i++) {
+				MMenuElement childME = plist[i];
+				modelProcessSwitch(menuManager, childME);
+			}
+		}
+	}
+
+	/**
+	 * @param menuManager
+	 * @param childME
+	 */
+	void modelProcessSwitch(MenuManager menuManager, MMenuElement childME) {
+		if (!childME.isToBeRendered()) {
+			return;
+		}
+		if (RenderedElementUtil.isRenderedMenuItem(childME)) {
+			MMenuItem itemModel = (MMenuItem) childME;
+			processRenderedItem(menuManager, itemModel);
+		} else if (OpaqueElementUtil.isOpaqueMenuItem(childME)) {
+			MMenuItem itemModel = (MMenuItem) childME;
+			processOpaqueItem(menuManager, itemModel);
+		} else if (childME instanceof MHandledMenuItem) {
+			MHandledMenuItem itemModel = (MHandledMenuItem) childME;
+			processHandledItem(menuManager, itemModel);
+		} else if (childME instanceof MDirectMenuItem) {
+			MDirectMenuItem itemModel = (MDirectMenuItem) childME;
+			processDirectItem(menuManager, itemModel, null);
+		} else if (childME instanceof MMenuSeparator) {
+			MMenuSeparator sep = (MMenuSeparator) childME;
+			processSeparator(menuManager, sep);
+			// } else if (childME instanceof MOpaqueMenu) {
+			// I'm not sure what to do here
+			// so I'll just take it out of the running
+		} else if (childME instanceof MMenu) {
+			MMenu itemModel = (MMenu) childME;
+			processMenu(menuManager, itemModel);
+		} else if (childME instanceof MDynamicMenuContribution) {
+			MDynamicMenuContribution itemModel = (MDynamicMenuContribution) childME;
+			processDynamicMenuContribution(menuManager, itemModel);
+		}
+	}
+
+	/**
+	 * @param parentManager
+	 * @param itemModel
+	 */
+	void processRenderedItem(MenuManager parentManager,
+ MMenuItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		Object obj = RenderedElementUtil.getContributionManager(itemModel);
+		if (obj instanceof IContextFunction) {
+			final IEclipseContext lclContext = getContext(itemModel);
+			ici = (IContributionItem) ((IContextFunction) obj).compute(
+					lclContext, null);
+			RenderedElementUtil.setContributionManager(itemModel, ici);
+		} else if (obj instanceof IContributionItem) {
+			ici = (IContributionItem) obj;
+		} else {
+			// TODO potentially log the state, we've got something we're not
+			// happy with
+			return;
+		}
+		ici.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ici);
+		linkModelToContribution(itemModel, ici);
+	}
+
+	void processOpaqueItem(MenuManager parentManager, MMenuItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		Object obj = OpaqueElementUtil.getOpaqueItem(itemModel);
+		if (obj instanceof IContributionItem) {
+			ici = (IContributionItem) obj;
+		} else {
+			return;
+		}
+		ici.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ici);
+		linkModelToContribution(itemModel, ici);
+	}
+
+	/**
+	 * @param menuManager
+	 * @param itemModel
+	 */
+	private void processSeparator(MenuManager menuManager,
+			MMenuSeparator itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		AbstractGroupMarker marker = null;
+		if (itemModel.getTags().contains(GROUP_MARKER)
+				|| !itemModel.isVisible()) {
+			if (itemModel.getElementId() != null) {
+				marker = new GroupMarker(itemModel.getElementId());
+			}
+		} else {
+			marker = new Separator();
+			marker.setId(itemModel.getElementId());
+		}
+		if (marker == null) {
+			return;
+		}
+		addToManager(menuManager, itemModel, marker);
+		linkModelToContribution(itemModel, marker);
+	}
+
+	/**
+	 * @param parentManager
+	 * @param itemModel
+	 * @param id
+	 */
+	void processDirectItem(MenuManager parentManager,
+			MDirectMenuItem itemModel, String id) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		final IEclipseContext lclContext = getContext(itemModel);
+		DirectContributionItem ci = ContextInjectionFactory.make(
+				DirectContributionItem.class, lclContext);
+		ci.setModel(itemModel);
+		ci.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	/**
+	 * @param menuManager
+	 * @param itemModel
+	 */
+	private void processDynamicMenuContribution(MenuManager menuManager,
+			MDynamicMenuContribution itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		DynamicContributionContributionItem ci = new DynamicContributionContributionItem(
+				itemModel);
+		addToManager(menuManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	/**
+	 * @param parentManager
+	 * @param itemModel
+	 */
+	void processHandledItem(MenuManager parentManager,
+			MHandledMenuItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		final IEclipseContext lclContext = getContext(itemModel);
+		HandledContributionItem ci = ContextInjectionFactory.make(
+				HandledContributionItem.class, lclContext);
+		ci.setModel(itemModel);
+		ci.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	private String getText(MMenu menuModel) {
+		String text = menuModel.getLocalizedLabel();
+		if (text == null || text.length() == 0) {
+			return NO_LABEL;
+		}
+		return text;
+	}
+
+	private ImageDescriptor getImageDescriptor(MUILabel element) {
+		IEclipseContext localContext = context;
+		String iconURI = element.getIconURI();
+		if (iconURI != null && iconURI.length() > 0) {
+			ISWTResourceUtilities resUtils = (ISWTResourceUtilities) localContext
+					.get(IResourceUtilities.class.getName());
+			return resUtils.imageDescriptorFromURI(URI.createURI(iconURI));
+		}
+		return null;
+	}
+
+	public MenuManager getManager(MMenu model) {
+		return modelToManager.get(model);
+	}
+
+	public MMenu getMenuModel(MenuManager manager) {
+		return managerToModel.get(manager);
+	}
+
+	public void linkModelToManager(MMenu model, MenuManager manager) {
+		modelToManager.put(model, manager);
+		managerToModel.put(manager, model);
+	}
+
+	public void clearModelToManager(MMenu model, MenuManager manager) {
+		for (MMenuElement element : model.getChildren()) {
+			IContributionItem ici = getContribution(element);
+			clearModelToContribution(element, ici);
+		}
+		modelToManager.remove(model);
+		managerToModel.remove(manager);
+	}
+
+	public IContributionItem getContribution(MMenuElement model) {
+		return modelToContribution.get(model);
+	}
+
+	public MMenuElement getMenuElement(IContributionItem item) {
+		return contributionToModel.get(item);
+	}
+
+	public void linkModelToContribution(MMenuElement model,
+			IContributionItem item) {
+		modelToContribution.put(model, item);
+		contributionToModel.put(item, model);
+	}
+
+	public void clearModelToContribution(MMenuElement model,
+			IContributionItem item) {
+		modelToContribution.remove(model);
+		contributionToModel.remove(item);
+	}
+
+	public ContributionRecord getContributionRecord(MMenuElement element) {
+		return modelContributionToRecord.get(element);
+	}
+
+	public void linkElementToContributionRecord(MMenuElement element,
+			ContributionRecord record) {
+		modelContributionToRecord.put(element, record);
+	}
+
+	/**
+	 * Search the records for testing. Look, but don't touch!
+	 *
+	 * @return the array of active ContributionRecords.
+	 */
+	public ContributionRecord[] getContributionRecords() {
+		HashSet<ContributionRecord> records = new HashSet<ContributionRecord>(
+				modelContributionToRecord.values());
+		return records.toArray(new ContributionRecord[records.size()]);
+	}
+
+	@Override
+	public IEclipseContext getContext(MUIElement el) {
+		return super.getContext(el);
+	}
+
+	/**
+	 * @param menuManager
+	 * @param menuModel
+	 */
+	public void reconcileManagerToModel(MenuManager menuManager, MMenu menuModel) {
+		List<MMenuElement> modelChildren = menuModel.getChildren();
+
+		HashSet<MMenuItem> oldModelItems = new HashSet<MMenuItem>();
+		HashSet<MMenu> oldMenus = new HashSet<MMenu>();
+		HashSet<MMenuSeparator> oldSeps = new HashSet<MMenuSeparator>();
+		for (MMenuElement itemModel : modelChildren) {
+			if (OpaqueElementUtil.isOpaqueMenuSeparator(itemModel)) {
+				oldSeps.add((MMenuSeparator) itemModel);
+			} else if (OpaqueElementUtil.isOpaqueMenuItem(itemModel)) {
+				oldModelItems.add((MMenuItem) itemModel);
+			} else if (OpaqueElementUtil.isOpaqueMenu(itemModel)) {
+				oldMenus.add((MMenu) itemModel);
+			}
+		}
+
+		IContributionItem[] items = menuManager.getItems();
+		for (int src = 0, dest = 0; src < items.length; src++, dest++) {
+			IContributionItem item = items[src];
+
+			if (item instanceof SubContributionItem) {
+				// get the wrapped contribution item
+				item = ((SubContributionItem) item).getInnerItem();
+			}
+
+			if (item instanceof MenuManager) {
+				MenuManager childManager = (MenuManager) item;
+				MMenu childModel = getMenuModel(childManager);
+				if (childModel == null) {
+					MMenu legacyModel = OpaqueElementUtil.createOpaqueMenu();
+					legacyModel.setElementId(childManager.getId());
+					legacyModel.setVisible(childManager.isVisible());
+					legacyModel.setLabel(childManager.getMenuText());
+
+					linkModelToManager(legacyModel, childManager);
+					OpaqueElementUtil.setOpaqueItem(legacyModel, childManager);
+					if (modelChildren.size() > dest) {
+						modelChildren.add(dest, legacyModel);
+					} else {
+						modelChildren.add(legacyModel);
+					}
+					reconcileManagerToModel(childManager, legacyModel);
+				} else {
+					if (OpaqueElementUtil.isOpaqueMenu(childModel)) {
+						oldMenus.remove(childModel);
+					}
+					if (modelChildren.size() > dest) {
+						if (modelChildren.get(dest) != childModel) {
+							modelChildren.remove(childModel);
+							modelChildren.add(dest, childModel);
+						}
+					} else {
+						modelChildren.add(childModel);
+					}
+					if (childModel instanceof MPopupMenu) {
+						if (((MPopupMenu) childModel).getContext() == null) {
+							IEclipseContext lclContext = getContext(menuModel);
+							if (lclContext != null) {
+								((MPopupMenu) childModel)
+										.setContext(lclContext
+												.createChild(childModel
+														.getElementId()));
+							}
+						}
+					}
+
+					if (childModel.getChildren().size() != childManager.getSize()) {
+						reconcileManagerToModel(childManager, childModel);
+					}
+				}
+			} else if (item.isSeparator() || item.isGroupMarker()) {
+				MMenuElement menuElement = getMenuElement(item);
+				if (menuElement == null) {
+					MMenuSeparator legacySep = OpaqueElementUtil
+							.createOpaqueMenuSeparator();
+					legacySep.setElementId(item.getId());
+					legacySep.setVisible(item.isVisible());
+					OpaqueElementUtil.setOpaqueItem(legacySep, item);
+					linkModelToContribution(legacySep, item);
+					if (modelChildren.size() > dest) {
+						modelChildren.add(dest, legacySep);
+					} else {
+						modelChildren.add(legacySep);
+					}
+				} else if (OpaqueElementUtil.isOpaqueMenuSeparator(menuElement)) {
+					MMenuSeparator legacySep = (MMenuSeparator) menuElement;
+					oldSeps.remove(legacySep);
+					if (modelChildren.size() > dest) {
+						if (modelChildren.get(dest) != legacySep) {
+							modelChildren.remove(legacySep);
+							modelChildren.add(dest, legacySep);
+						}
+					} else {
+						modelChildren.add(legacySep);
+					}
+				}
+			} else {
+				MMenuElement menuElement = getMenuElement(item);
+				if (menuElement == null) {
+					MMenuItem legacyItem = OpaqueElementUtil
+							.createOpaqueMenuItem();
+					legacyItem.setElementId(item.getId());
+					legacyItem.setVisible(item.isVisible());
+					OpaqueElementUtil.setOpaqueItem(legacyItem, item);
+					linkModelToContribution(legacyItem, item);
+					if (modelChildren.size() > dest) {
+						modelChildren.add(dest, legacyItem);
+					} else {
+						modelChildren.add(legacyItem);
+					}
+				} else if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)) {
+					MMenuItem legacyItem = (MMenuItem) menuElement;
+					oldModelItems.remove(legacyItem);
+					if (modelChildren.size() > dest) {
+						if (modelChildren.get(dest) != legacyItem) {
+							modelChildren.remove(legacyItem);
+							modelChildren.add(dest, legacyItem);
+						}
+					} else {
+						modelChildren.add(legacyItem);
+					}
+				}
+			}
+		}
+		if (!oldModelItems.isEmpty()) {
+			modelChildren.removeAll(oldModelItems);
+			for (MMenuItem model : oldModelItems) {
+				IContributionItem ici = (IContributionItem) OpaqueElementUtil
+						.getOpaqueItem(model);
+				clearModelToContribution(model, ici);
+			}
+		}
+		if (!oldMenus.isEmpty()) {
+			modelChildren.removeAll(oldMenus);
+			for (MMenu oldMenu : oldMenus) {
+				MenuManager oldManager = getManager(oldMenu);
+				clearModelToManager(oldMenu, oldManager);
+			}
+		}
+		if (!oldSeps.isEmpty()) {
+			modelChildren.removeAll(oldSeps);
+			for (MMenuSeparator model : oldSeps) {
+				IContributionItem item = (IContributionItem) OpaqueElementUtil
+						.getOpaqueItem(model);
+				clearModelToContribution(model, item);
+			}
+		}
+	}
+
+	/**
+	 * @param menuManager
+	 * @param element
+	 * @param evalContext
+	 */
+	public static void updateVisibility(MenuManager menuManager,
+			MMenuElement element, ExpressionContext evalContext) {
+		boolean current = element.isVisible();
+		boolean visible = true;
+		boolean evaluated = false;
+		if (element.getPersistedState().get(VISIBILITY_IDENTIFIER) != null) {
+			evaluated = true;
+			String identifier = element.getPersistedState().get(
+					VISIBILITY_IDENTIFIER);
+			Object rc = evalContext.eclipseContext.get(identifier);
+			if (rc instanceof Boolean) {
+				visible = ((Boolean) rc).booleanValue();
+			}
+		}
+		if (visible && (element.getVisibleWhen() instanceof MCoreExpression)) {
+			evaluated = true;
+			visible = ContributionsAnalyzer.isVisible(
+					(MCoreExpression) element.getVisibleWhen(), evalContext);
+		}
+		if (evaluated && visible != current) {
+			element.setVisible(visible);
+			menuManager.markDirty();
+		}
+	}
+
+	/**
+	 * Clean dynamic menu contributions provided by
+	 * {@link MDynamicMenuContribution} application model elements
+	 *
+	 * @param menuManager
+	 * @param menuModel
+	 * @param dump
+	 */
+	public void removeDynamicMenuContributions(MenuManager menuManager,
+			MMenu menuModel, ArrayList<MMenuElement> dump) {
+		removeMenuContributions(menuModel, dump);
+		for (MMenuElement mMenuElement : dump) {
+			IContributionItem ici = getContribution(mMenuElement);
+			if (ici == null && mMenuElement instanceof MMenu) {
+				MMenu menuElement = (MMenu) mMenuElement;
+				ici = getManager(menuElement);
+				clearModelToManager(menuElement, (MenuManager) ici);
+			} else {
+				clearModelToContribution(menuModel, ici);
+			}
+			menuManager.remove(ici);
+		}
+	}
+
+	private void unlinkMenu(MMenu menu) {
+
+		List<MMenuElement> children = menu.getChildren();
+		for (MMenuElement child : children) {
+			if (child instanceof MMenu)
+				unlinkMenu((MMenu) child);
+			else {
+				IContributionItem contribution = getContribution(child);
+				clearModelToContribution(child, contribution);
+			}
+		}
+		MenuManager mm = getManager(menu);
+		clearModelToManager(menu, mm);
+	}
+
+	private void scheduleManagerUpdate(IContributionManager mgr) {
+		// Bug 467000: Avoid repeatedly updating menu managers
+		// This workaround is opt-in for 4.5
+		boolean workaroundEnabled = Boolean.getBoolean("eclipse.workaround.bug467000"); //$NON-NLS-1$
+		if (!workaroundEnabled) {
+			mgr.update(false);
+			return;
+		}
+		synchronized (mgrToUpdate) {
+			if (this.mgrToUpdate.isEmpty()) {
+				Display display = context.get(Display.class);
+				if (display != null && !display.isDisposed()) {
+					display.timerExec(100, new Runnable() {
+
+						@Override
+						public void run() {
+							Collection<IContributionManager> toUpdate = new LinkedHashSet<>();
+							synchronized (mgrToUpdate) {
+								toUpdate.addAll(mgrToUpdate);
+								mgrToUpdate.clear();
+							}
+							for (IContributionManager mgr : toUpdate) {
+								mgr.update(false);
+							}
+						}
+					});
+				}
+				this.mgrToUpdate.add(mgr);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRendererFilter.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRendererFilter.java
new file mode 100644
index 0000000..4214a37
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRendererFilter.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import javax.inject.Inject;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.MenuService;
+import org.eclipse.e4.ui.internal.workbench.swt.Policy;
+import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Widget;
+
+public class MenuManagerRendererFilter implements Listener {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private static final String MMRF_STATIC_CONTEXT = "HCI-staticContext"; //$NON-NLS-1$
+
+	public static final String NUL_MENU_ITEM = "(None Applicable)"; //$NON-NLS-1$
+
+	static final String TMP_ORIGINAL_CONTEXT = "MenuServiceFilter.original.context"; //$NON-NLS-1$
+
+	private static void trace(String msg, Widget menu, MMenu menuModel) {
+		WorkbenchSWTActivator.trace(Policy.MENUS, msg + ": " + menu + ": " //$NON-NLS-1$ //$NON-NLS-2$
+				+ menuModel, null);
+	}
+
+	@Inject
+	private Logger logger;
+
+	@Inject
+	private EModelService modelService;
+
+	@Inject
+	private MenuManagerRenderer renderer;
+
+	private HashMap<Menu, Runnable> pendingCleanup = new HashMap<Menu, Runnable>();
+
+	private class SafeWrapper implements ISafeRunnable {
+		Event event;
+
+		@Override
+		public void handleException(Throwable e) {
+			if (e instanceof Error) {
+				// errors are deadly, we shouldn't ignore these
+				throw (Error) e;
+			}
+			// log exceptions otherwise
+			if (logger != null) {
+				logger.error(e);
+			}
+		}
+
+		@Override
+		public void run() throws Exception {
+			safeHandleEvent(event);
+		}
+	}
+
+	private SafeWrapper safeWrapper = new SafeWrapper();
+
+	@Override
+	public void handleEvent(final Event event) {
+		// wrap the handling in a SafeRunner so that exceptions do not prevent
+		// the menu from being shown
+		safeWrapper.event = event;
+		SafeRunner.run(safeWrapper);
+	}
+
+	private void safeHandleEvent(Event event) {
+		if (!(event.widget instanceof Menu)) {
+			return;
+		}
+		final Menu menu = (Menu) event.widget;
+		if ((menu.getStyle() & SWT.BAR) != 0) {
+			// don't process the menu bar, it's not fair :-)
+			return;
+		}
+		if (event.type == SWT.Dispose) {
+			trace("handleMenu.Dispose", menu, null); //$NON-NLS-1$
+			cleanUp(menu, null, null);
+			return;
+		}
+
+		// fill in all of the pieces
+		MenuManager menuManager = null;
+		Object obj = menu.getData(AbstractPartRenderer.OWNING_ME);
+		if (obj == null) {
+			Object tmp = menu
+					.getData("org.eclipse.jface.action.MenuManager.managerKey"); //$NON-NLS-1$
+			if (tmp instanceof MenuManager) {
+				MenuManager tmpManager = (MenuManager) tmp;
+				menuManager = tmpManager;
+				obj = renderer.getMenuModel(tmpManager);
+				if (obj instanceof MPopupMenu) {
+					MPopupMenu popupMenu = (MPopupMenu) obj;
+					if (popupMenu.getWidget() == null
+							&& menuManager.getMenu() != null) {
+						final MUIElement container = modelService
+								.getContainer(popupMenu);
+						if (container instanceof MPart) {
+							MenuService.registerMenu(menuManager.getMenu()
+									.getParent(), popupMenu,
+									((MPart) container).getContext());
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param info
+	 * @param menuModel
+	 * @param renderer
+	 * @param evalContext
+	 * @param recurse
+	 */
+	public static void collectInfo(ExpressionInfo info, final MMenu menuModel,
+			final MenuManagerRenderer renderer,
+			final IEclipseContext evalContext, boolean recurse) {
+		HashSet<ContributionRecord> records = new HashSet<ContributionRecord>();
+		for (MMenuElement element : menuModel.getChildren()) {
+			ContributionRecord record = renderer.getContributionRecord(element);
+			if (record != null) {
+				if (records.add(record)) {
+					record.collectInfo(info);
+				}
+			} else {
+				ContributionsAnalyzer.collectInfo(info,
+						element.getVisibleWhen());
+			}
+			if (recurse && element instanceof MMenu) {
+				MMenu childMenu = (MMenu) element;
+				collectInfo(info, childMenu, renderer, evalContext, false);
+			}
+		}
+	}
+
+	/**
+	 * @param menuModel
+	 * @param renderer
+	 * @param menuManager
+	 * @param evalContext
+	 */
+	public static void updateElementVisibility(final MMenu menuModel,
+			MenuManagerRenderer renderer, MenuManager menuManager,
+			final IEclipseContext evalContext, final int recurseLevel,
+			boolean updateEnablement) {
+		final ExpressionContext exprContext = new ExpressionContext(evalContext);
+		HashSet<ContributionRecord> records = new HashSet<ContributionRecord>();
+		for (MMenuElement element : menuModel.getChildren()) {
+			ContributionRecord record = renderer.getContributionRecord(element);
+			if (record != null) {
+				if (records.add(record)) {
+					record.updateVisibility(evalContext);
+				}
+			} else {
+				MenuManagerRenderer.updateVisibility(menuManager, element,
+						exprContext);
+			}
+			if (recurseLevel > 0 && element.isVisible()
+					&& element instanceof MMenu) {
+				MMenu childMenu = (MMenu) element;
+				MenuManager childManager = renderer.getManager(childMenu);
+				if (childManager != null) {
+					updateElementVisibility(childMenu, renderer, childManager,
+							evalContext, recurseLevel - 1, false);
+				}
+			}
+
+			if (updateEnablement && element instanceof MHandledMenuItem) {
+				ParameterizedCommand cmd = ((MHandledMenuItem) element)
+						.getWbCommand();
+				EHandlerService handlerService = evalContext
+						.get(EHandlerService.class);
+				if (cmd != null && handlerService != null) {
+					MHandledMenuItem item = (MHandledMenuItem) element;
+					final IEclipseContext staticContext = EclipseContextFactory
+							.create(MMRF_STATIC_CONTEXT);
+					ContributionsAnalyzer.populateModelInterfaces(item,
+							staticContext, item.getClass().getInterfaces());
+					try {
+						((MHandledMenuItem) element).setEnabled(handlerService
+								.canExecute(cmd, staticContext));
+					} finally {
+						staticContext.dispose();
+					}
+				}
+			} else if (updateEnablement && element instanceof MDirectMenuItem) {
+				MDirectMenuItem contrib = (MDirectMenuItem) element;
+				if (contrib.getObject() == null) {
+					IContributionFactory icf = evalContext
+							.get(IContributionFactory.class);
+
+					contrib.setObject(icf.create(contrib.getContributionURI(),
+							evalContext, EclipseContextFactory.create()));
+				}
+				if (contrib.getObject() == null) {
+					continue;
+				}
+				MDirectMenuItem item = (MDirectMenuItem) element;
+				IEclipseContext staticContext = EclipseContextFactory
+						.create(MMRF_STATIC_CONTEXT);
+				ContributionsAnalyzer.populateModelInterfaces(item,
+						staticContext, item.getClass().getInterfaces());
+				try {
+					Object rc = ContextInjectionFactory.invoke(
+							contrib.getObject(), CanExecute.class, evalContext,
+							staticContext, Boolean.TRUE);
+					if (rc instanceof Boolean) {
+						contrib.setEnabled((Boolean) rc);
+					}
+				} finally {
+					staticContext.dispose();
+				}
+			}
+		}
+	}
+
+	void setEnabled(MHandledMenuItem item) {
+		if (!item.isToBeRendered() || !item.isVisible()
+				|| item.getWidget() == null) {
+			return;
+		}
+		ParameterizedCommand cmd = item.getWbCommand();
+		if (cmd == null) {
+			return;
+		}
+		final IEclipseContext lclContext = renderer.getContext(item);
+		EHandlerService service = lclContext.get(EHandlerService.class);
+		final IEclipseContext staticContext = EclipseContextFactory
+				.create(MMRF_STATIC_CONTEXT);
+		ContributionsAnalyzer.populateModelInterfaces(item, staticContext, item
+				.getClass().getInterfaces());
+		try {
+			item.setEnabled(service.canExecute(cmd, staticContext));
+		} finally {
+			staticContext.dispose();
+		}
+	}
+
+	public void cleanUp(final Menu menu, MMenu menuModel,
+			MenuManager menuManager) {
+		trace("cleanUp", menu, null); //$NON-NLS-1$
+		if (pendingCleanup.isEmpty()) {
+			return;
+		}
+		Runnable cleanUp = pendingCleanup.remove(menu);
+		if (cleanUp != null) {
+			trace("cleanUp.run()", menu, null); //$NON-NLS-1$
+			cleanUp.run();
+		}
+	}
+
+	public void dispose() {
+		Menu[] keys = pendingCleanup.keySet().toArray(
+				new Menu[pendingCleanup.size()]);
+		for (Menu menu : keys) {
+			cleanUp(menu, null, null);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerServiceFilter.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerServiceFilter.java
new file mode 100644
index 0000000..48c61a2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerServiceFilter.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import java.lang.reflect.Method;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.Policy;
+import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Widget;
+
+public class MenuManagerServiceFilter implements Listener {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	public static final String NUL_MENU_ITEM = "(None Applicable)"; //$NON-NLS-1$
+
+	private static final String TMP_ORIGINAL_CONTEXT = "MenuServiceFilter.original.context"; //$NON-NLS-1$
+
+	private static void trace(String msg, Widget menu, MMenu menuModel) {
+		WorkbenchSWTActivator.trace(Policy.MENUS, msg + ": " + menu + ": " //$NON-NLS-1$ //$NON-NLS-2$
+				+ menuModel, null);
+	}
+
+	private static Method aboutToShow;
+
+	public static Method getAboutToShow() {
+		if (aboutToShow == null) {
+			try {
+				aboutToShow = MenuManager.class
+						.getDeclaredMethod("handleAboutToShow"); //$NON-NLS-1$
+				aboutToShow.setAccessible(true);
+			} catch (SecurityException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (NoSuchMethodException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		return aboutToShow;
+	}
+
+	@Inject
+	private Logger logger;
+
+	@Inject
+	EModelService modelService;
+
+	@Override
+	public void handleEvent(final Event event) {
+		// wrap the handling in a SafeRunner so that exceptions do not prevent
+		// the menu from being shown
+		SafeRunner.run(new ISafeRunnable() {
+			@Override
+			public void handleException(Throwable e) {
+				if (e instanceof Error) {
+					// errors are deadly, we shouldn't ignore these
+					throw (Error) e;
+				} else {
+					// log exceptions otherwise
+					if (logger != null) {
+						logger.error(e);
+					}
+				}
+			}
+
+			@Override
+			public void run() throws Exception {
+				safeHandleEvent(event);
+			}
+		});
+	}
+
+	private void safeHandleEvent(Event event) {
+		if (!(event.widget instanceof Menu)) {
+			return;
+		}
+		final Menu menu = (Menu) event.widget;
+		if (event.type == SWT.Dispose) {
+			trace("handleMenu.Dispose", menu, null); //$NON-NLS-1$
+			cleanUp(menu);
+		}
+		Object obj = menu.getData(AbstractPartRenderer.OWNING_ME);
+		if (obj == null && menu.getParentItem() != null) {
+			obj = menu.getParentItem().getData(AbstractPartRenderer.OWNING_ME);
+		}
+		if (obj instanceof MPopupMenu) {
+			handleContextMenu(event, menu, (MPopupMenu) obj);
+		} else if (obj instanceof MMenu) {
+			handleMenu(event, menu, (MMenu) obj);
+		}
+	}
+
+	private void handleMenu(final Event event, final Menu menu,
+			final MMenu menuModel) {
+		if ((menu.getStyle() & SWT.BAR) != 0) {
+			// don't process the menu bar, it's not fair :-)
+			return;
+		}
+		switch (event.type) {
+		case SWT.Show:
+			cleanUp(menu);
+			showMenu(event, menu, menuModel);
+			break;
+		case SWT.Hide:
+			// TODO we'll clean up on show
+			break;
+		}
+	}
+
+	public void showMenu(final Event event, final Menu menu,
+			final MMenu menuModel) {
+		// System.err.println("showMenu: " + menuModel + "\n\t" + menu);
+	}
+
+	private void handleContextMenu(final Event event, final Menu menu,
+			final MPopupMenu menuModel) {
+		switch (event.type) {
+		case SWT.Show:
+			cleanUp(menu);
+			showPopup(event, menu, menuModel);
+			break;
+		case SWT.Hide:
+			hidePopup(event, menu, menuModel);
+			break;
+		}
+	}
+
+	public void hidePopup(Event event, Menu menu, MPopupMenu menuModel) {
+		// System.err.println("hidePopup: " + menuModel + "\n\t" + menu);
+		final IEclipseContext popupContext = menuModel.getContext();
+		final IEclipseContext originalChild = (IEclipseContext) popupContext
+				.get(TMP_ORIGINAL_CONTEXT);
+		popupContext.remove(TMP_ORIGINAL_CONTEXT);
+		if (!menu.isDisposed()) {
+			menu.getDisplay().asyncExec(new Runnable() {
+				@Override
+				public void run() {
+					if (originalChild == null) {
+						popupContext.deactivate();
+					} else {
+						originalChild.activate();
+					}
+				}
+			});
+		}
+	}
+
+	public void showPopup(final Event event, final Menu menu,
+			final MPopupMenu menuModel) {
+		// System.err.println("showPopup: " + menuModel + "\n\t" + menu);
+		// we need some context foolery here
+		final IEclipseContext popupContext = menuModel.getContext();
+		final IEclipseContext parentContext = popupContext.getParent();
+		final IEclipseContext originalChild = parentContext.getActiveChild();
+		popupContext.activate();
+		popupContext.set(TMP_ORIGINAL_CONTEXT, originalChild);
+
+	}
+
+	public void cleanUp(final Menu menu) {
+		// System.err.println("cleanUp: " + menu);
+	}
+
+	public void dispose() {
+		// System.err.println("dispose");
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerShowProcessor.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerShowProcessor.java
new file mode 100644
index 0000000..c45d9d2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerShowProcessor.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * 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
+ *     Marco Descher <marco@descher.at> - Bug 389063,398865,398866,403081,403083
+ *     Bruce Skingle <Bruce.Skingle@immutify.com> - Bug 442570
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.AboutToShow;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.Policy;
+import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.menu.MDynamicMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
+import org.eclipse.jface.action.IMenuListener2;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * <code>MenuManagerShowProcessor</code> provides hooks for renderer processing
+ * before and after the <code>MenuManager</code> calls out to its
+ * <code>IMenuManagerListener2</code> for the <code>menuAboutToShow</code>
+ * events.
+ */
+public class MenuManagerShowProcessor implements IMenuListener2 {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private static void trace(String msg, Widget menu, MMenu menuModel) {
+		WorkbenchSWTActivator.trace(Policy.MENUS, msg + ": " + menu + ": " //$NON-NLS-1$ //$NON-NLS-2$
+				+ menuModel, null);
+	}
+
+	@Inject
+	private EModelService modelService;
+
+	@Inject
+	private IRendererFactory rendererFactory;
+
+	@Inject
+	private MenuManagerRenderer renderer;
+
+	@Inject
+	private IContributionFactory contributionFactory;
+
+	@Inject
+	@Optional
+	private Logger logger;
+
+	private HashMap<Menu, Runnable> pendingCleanup = new HashMap<Menu, Runnable>();
+
+	@Override
+	public void menuAboutToShow(IMenuManager manager) {
+		if (!(manager instanceof MenuManager)) {
+			return;
+		}
+		MenuManager menuManager = (MenuManager) manager;
+		final MMenu menuModel = renderer.getMenuModel(menuManager);
+		final Menu menu = menuManager.getMenu();
+
+		if (menuModel != null && menuManager != null) {
+			cleanUp(menu, menuModel, menuManager);
+		}
+		if (menuModel instanceof MPopupMenu) {
+			showPopup(menu, (MPopupMenu) menuModel, menuManager);
+		}
+		AbstractPartRenderer obj = rendererFactory.getRenderer(menuModel,
+				menu.getParent());
+		if (!(obj instanceof MenuManagerRenderer)) {
+			trace("Not the correct renderer: " + obj, menu, menuModel); //$NON-NLS-1$
+			return;
+		}
+		MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
+		if (menuModel.getWidget() == null) {
+			renderer.bindWidget(menuModel, menuManager.getMenu());
+		}
+	}
+
+	@Override
+	public void menuAboutToHide(IMenuManager manager) {
+		if (!(manager instanceof MenuManager)) {
+			return;
+		}
+		MenuManager menuManager = (MenuManager) manager;
+		final MMenu menuModel = renderer.getMenuModel(menuManager);
+		final Menu menu = menuManager.getMenu();
+		if (menuModel != null) {
+			processDynamicElements(menuModel, menuManager);
+			showMenu(menu, menuModel, menuManager);
+		}
+	}
+
+	/**
+	 * HashMap key for storage of {@link MDynamicMenuContribution} elements used
+	 * in {@link #processDynamicElements(MMenu, MenuManager)}
+	 */
+	protected static final String DYNAMIC_ELEMENT_STORAGE_KEY = MenuManagerShowProcessor.class
+			.getSimpleName() + ".dynamicElements"; //$NON-NLS-1$
+
+	/**
+	 * Process dynamic menu contributions provided by
+	 * {@link MDynamicMenuContribution} application model elements
+	 *
+	 * @param menuModel
+	 * @param menuManager
+	 *
+	 */
+	private void processDynamicElements(MMenu menuModel, MenuManager menuManager) {
+		MMenuElement[] ml = menuModel.getChildren().toArray(
+				new MMenuElement[menuModel.getChildren().size()]);
+		for (int i = 0; i < ml.length; i++) {
+
+			MMenuElement currentMenuElement = ml[i];
+			if (currentMenuElement instanceof MDynamicMenuContribution) {
+				Object contribution = ((MDynamicMenuContribution) currentMenuElement)
+						.getObject();
+				if (contribution == null) {
+					IEclipseContext context = modelService
+							.getContainingContext(menuModel);
+					contribution = contributionFactory.create(
+							((MDynamicMenuContribution) currentMenuElement)
+									.getContributionURI(), context);
+					((MDynamicMenuContribution) currentMenuElement)
+							.setObject(contribution);
+				}
+
+				IEclipseContext dynamicMenuContext = EclipseContextFactory
+						.create();
+				ArrayList<MMenuElement> mel = new ArrayList<MMenuElement>();
+				dynamicMenuContext.set(List.class, mel);
+				IEclipseContext parentContext = modelService
+						.getContainingContext(currentMenuElement);
+				Object rc = ContextInjectionFactory.invoke(contribution,
+						AboutToShow.class, parentContext, dynamicMenuContext,
+						this);
+				dynamicMenuContext.dispose();
+				if (rc == this) {
+					if (logger != null) {
+						logger.error("Missing @AboutToShow method in " + contribution); //$NON-NLS-1$
+					}
+					continue;
+				}
+
+				if (mel.size() > 0) {
+
+					int position = 0;
+					while (position < menuModel.getChildren().size()) {
+						if (currentMenuElement == menuModel.getChildren().get(
+								position)) {
+							position++;
+							break;
+						}
+						position++;
+					}
+
+					// ensure that each element of the list has a valid element
+					// id
+					// and set the parent of the entries
+					for (int j = 0; j < mel.size(); j++) {
+						MMenuElement menuElement = mel.get(j);
+						if (menuElement.getElementId() == null
+								|| menuElement.getElementId().length() < 1) {
+							menuElement.setElementId(currentMenuElement
+									.getElementId() + "." + j); //$NON-NLS-1$
+						}
+						menuModel.getChildren().add(position++, menuElement);
+						renderer.modelProcessSwitch(menuManager, menuElement);
+					}
+					currentMenuElement.getTransientData().put(DYNAMIC_ELEMENT_STORAGE_KEY, mel);
+				}
+			}
+		}
+	}
+
+	private void cleanUp(final Menu menu, MMenu menuModel,
+			MenuManager menuManager) {
+		trace("cleanUp", menu, null); //$NON-NLS-1$
+		if (pendingCleanup.isEmpty()) {
+			return;
+		}
+		Runnable cleanUp = pendingCleanup.remove(menu);
+		if (cleanUp != null) {
+			trace("cleanUp.run()", menu, null); //$NON-NLS-1$
+			cleanUp.run();
+		}
+	}
+
+	private void showPopup(final Menu menu, final MPopupMenu menuModel,
+			MenuManager menuManager) {
+		// System.err.println("showPopup: " + menuModel + "\n\t" + menu);
+		// we need some context foolery here
+		final IEclipseContext popupContext = menuModel.getContext();
+		final IEclipseContext parentContext = popupContext.getParent();
+		final IEclipseContext originalChild = parentContext.getActiveChild();
+		popupContext.activate();
+		popupContext.set(MenuManagerRendererFilter.TMP_ORIGINAL_CONTEXT,
+				originalChild);
+	}
+
+	private void showMenu(final Menu menu, final MMenu menuModel,
+			MenuManager menuManager) {
+
+		final IEclipseContext evalContext;
+		if (menuModel instanceof MContext) {
+			evalContext = ((MContext) menuModel).getContext();
+		} else {
+			evalContext = modelService.getContainingContext(menuModel);
+		}
+		MenuManagerRendererFilter.updateElementVisibility(menuModel, renderer,
+				menuManager, evalContext, 2, true);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/Messages.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/Messages.java
new file mode 100644
index 0000000..86b392c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/Messages.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 vogella GmbH 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:
+ *     Lars Vogel <Lars.Vogel@vogella.com> - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+
+	public static String ToolBarManagerRenderer_MenuCloseText;
+	public static String ToolBarManagerRenderer_MenuRestoreText;
+
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.workbench.renderers.swt.messages";//$NON-NLS-1$
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveRenderer.java
new file mode 100644
index 0000000..a392897
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveRenderer.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ *
+ */
+public class PerspectiveRenderer extends SWTPartRenderer {
+
+
+	@Override
+	public Widget createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MPerspective)
+				|| !(parent instanceof Composite))
+			return null;
+
+		Composite perspArea = new Composite((Composite) parent, SWT.NONE);
+		perspArea.setLayout(new FillLayout());
+		IStylingEngine stylingEngine = (IStylingEngine) getContext(element)
+				.get(IStylingEngine.SERVICE_NAME);
+		stylingEngine.setClassname(perspArea, "perspectiveLayout"); //$NON-NLS-1$
+
+		return perspArea;
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		super.processContents(container);
+
+		IPresentationEngine renderer = (IPresentationEngine) context
+				.get(IPresentationEngine.class.getName());
+
+		MPerspective persp = (MPerspective) ((MUIElement) container);
+		Shell shell = ((Composite) persp.getWidget()).getShell();
+		for (MWindow dw : persp.getWindows()) {
+			renderer.createGui(dw, shell, persp.getContext());
+		}
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement element) {
+		if (!(element instanceof MWindow))
+			return super.getUIContainer(element);
+
+		MPerspective persp = (MPerspective) ((EObject) element).eContainer();
+		if (persp.getWidget() instanceof Composite) {
+			Composite comp = (Composite) persp.getWidget();
+			return comp.getShell();
+		}
+
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveStackRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveStackRenderer.java
new file mode 100644
index 0000000..aec4885
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/PerspectiveStackRenderer.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ *
+ */
+public class PerspectiveStackRenderer extends LazyStackRenderer {
+
+	@Inject
+	private IPresentationEngine renderer;
+
+	@Inject
+	private IEventBroker eventBroker;
+
+	@PostConstruct
+	public void init() {
+		super.init(eventBroker);
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MPerspectiveStack)
+				|| !(parent instanceof Composite))
+			return null;
+
+		Composite perspStack = new Composite((Composite) parent, SWT.NONE);
+		IStylingEngine stylingEngine = (IStylingEngine) getContext(element)
+				.get(IStylingEngine.SERVICE_NAME);
+		stylingEngine.setClassname(perspStack, "perspectiveLayout"); //$NON-NLS-1$
+		perspStack.setLayout(new StackLayout());
+
+		return perspStack;
+	}
+
+	@Override
+	public void postProcess(MUIElement element) {
+		super.postProcess(element);
+
+		MPerspectiveStack ps = (MPerspectiveStack) element;
+		if (ps.getSelectedElement() != null
+				&& ps.getSelectedElement().getWidget() != null) {
+			Control ctrl = (Control) ps.getSelectedElement().getWidget();
+			Composite psComp = (Composite) ps.getWidget();
+			StackLayout sl = (StackLayout) psComp.getLayout();
+			sl.topControl = ctrl;
+			psComp.layout();
+		}
+	}
+
+	@Override
+	protected void showTab(MUIElement tabElement) {
+		MPerspective persp = (MPerspective) tabElement;
+
+		Control ctrl = (Control) tabElement.getWidget();
+		if (ctrl == null) {
+			ctrl = (Control) renderer.createGui(tabElement);
+		} else if (ctrl.getParent() != tabElement.getParent().getWidget()) {
+			Composite parent = (Composite) tabElement.getParent().getWidget();
+			ctrl.setParent(parent);
+		}
+
+		super.showTab(tabElement);
+
+		// relayout the perspective
+		Composite psComp = ctrl.getParent();
+		StackLayout sl = (StackLayout) psComp.getLayout();
+		if (sl != null) {
+			sl.topControl = ctrl;
+			psComp.layout();
+		}
+
+		ctrl.moveAbove(null);
+
+		// Force a context switch
+		if (tabElement instanceof MPerspective) {
+			MPerspective selected = (MPerspective) tabElement.getParent()
+					.getSelectedElement();
+			if (selected != null) {
+				IEclipseContext context = selected.getContext();
+				context.get(EPartService.class).switchPerspective(selected);
+			}
+		}
+
+		// Move any other controls to 'limbo'
+		Control[] kids = ctrl.getParent().getChildren();
+		Shell limbo = (Shell) persp.getContext().get("limbo"); //$NON-NLS-1$
+		for (Control child : kids) {
+			if (child != ctrl) {
+				child.setParent(limbo);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java
new file mode 100644
index 0000000..7a0f64e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java
@@ -0,0 +1,395 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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
+ *     Ragnar Nevries <r.eclipse@nevri.es> - Bug 443514
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+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.graphics.Image;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+public abstract class SWTPartRenderer extends AbstractPartRenderer {
+	private static final String ICON_URI_FOR_PART = "IconUriForPart"; //$NON-NLS-1$
+
+	private Map<String, Image> imageMap = new HashMap<String, Image>();
+
+	private String pinURI = "platform:/plugin/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/ovr16/pinned_ovr.gif"; //$NON-NLS-1$
+	private Image pinImage;
+
+	private ISWTResourceUtilities resUtils;
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		// EMF gives us null lists if empty
+		if (container == null)
+			return;
+
+		// Process any contents of the newly created ME
+		List<MUIElement> parts = container.getChildren();
+		if (parts != null) {
+			// loading a legacy app will add children to the window while it is
+			// being rendered.
+			// this is *not* the correct place for this
+			// hope that the ADD event will pick up the new part.
+			IPresentationEngine renderer = (IPresentationEngine) context
+					.get(IPresentationEngine.class.getName());
+			MUIElement[] plist = parts.toArray(new MUIElement[parts.size()]);
+			for (int i = 0; i < plist.length; i++) {
+				MUIElement childME = plist[i];
+				renderer.createGui(childME);
+			}
+		}
+	}
+
+	public void styleElement(MUIElement element, boolean active) {
+		if (!active)
+			element.getTags().remove(CSSConstants.CSS_ACTIVE_CLASS);
+		else
+			element.getTags().add(CSSConstants.CSS_ACTIVE_CLASS);
+
+		if (element.getWidget() != null)
+			setCSSInfo(element, element.getWidget());
+	}
+
+	public void setCSSInfo(MUIElement me, Object widget) {
+		// No SWT widget, nothing to style...
+		if (widget == null)
+			return;
+
+		// Set up the CSS Styling parameters; id & class
+		IEclipseContext ctxt = getContext(me);
+		if (ctxt == null) {
+			return;
+		}
+
+		final IStylingEngine engine = (IStylingEngine) ctxt
+				.get(IStylingEngine.SERVICE_NAME);
+		if (engine == null)
+			return;
+
+		// Put all the tags into the class string
+		EObject eObj = (EObject) me;
+		String cssClassStr = 'M' + eObj.eClass().getName();
+		for (String tag : me.getTags())
+			cssClassStr += ' ' + tag;
+
+		// this will trigger style()
+		String id = me.getElementId();
+		if (id != null) {
+			id = id.replace(".", "-"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		engine.setClassnameAndId(widget, cssClassStr, id);
+	}
+
+	@SuppressWarnings("restriction")
+	protected void reapplyStyles(Widget widget) {
+		// FIXME RAP does not support CSS
+		// CSSEngine engine = WidgetElement.getEngine(widget);
+		// if (engine != null) {
+		// engine.applyStyles(widget, false);
+		// }
+	}
+
+	@Override
+	public void bindWidget(MUIElement me, Object widget) {
+		if (widget instanceof Widget) {
+			((Widget) widget).setData(OWNING_ME, me);
+
+			// Set up the CSS Styling parameters; id & class
+			setCSSInfo(me, widget);
+
+			// Ensure that disposed widgets are unbound form the model
+			Widget swtWidget = (Widget) widget;
+			swtWidget.addDisposeListener(new DisposeListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					MUIElement element = (MUIElement) e.widget
+							.getData(OWNING_ME);
+					if (element != null)
+						unbindWidget(element);
+				}
+			});
+		}
+
+		// Create a bi-directional link between the widget and the model
+		me.setWidget(widget);
+	}
+
+	public Object unbindWidget(MUIElement me) {
+		Widget widget = (Widget) me.getWidget();
+		if (widget != null) {
+			me.setWidget(null);
+			if (!widget.isDisposed())
+				widget.setData(OWNING_ME, null);
+		}
+
+		// Clear the factory reference
+		me.setRenderer(null);
+
+		return widget;
+	}
+
+	@Override
+	protected Widget getParentWidget(MUIElement element) {
+		return (Widget) element.getParent().getWidget();
+	}
+
+	@Override
+	public void disposeWidget(MUIElement element) {
+
+		if (element.getWidget() instanceof Widget) {
+			Widget curWidget = (Widget) element.getWidget();
+
+			if (curWidget != null && !curWidget.isDisposed()) {
+				unbindWidget(element);
+				try {
+					curWidget.dispose();
+				} catch (Exception e) {
+					Logger logService = context.get(Logger.class);
+					if (logService != null) {
+						String msg = "Error disposing widget for : " + element.getClass().getName(); //$NON-NLS-1$
+						if (element instanceof MUILabel) {
+							msg += ' ' + ((MUILabel) element)
+									.getLocalizedLabel();
+						}
+						logService.error(e, msg);
+					}
+				}
+			}
+		}
+		element.setWidget(null);
+	}
+
+	@Override
+	public void hookControllerLogic(final MUIElement me) {
+		Object widget = me.getWidget();
+
+		// add an accessibility listener (not sure if this is in the wrong place
+		// (factory?)
+		if (widget instanceof Control && me instanceof MUILabel) {
+			((Control) widget).getAccessible().addAccessibleListener(
+					new AccessibleAdapter() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+						@Override
+						public void getName(AccessibleEvent e) {
+							e.result = ((MUILabel) me).getLocalizedLabel();
+						}
+					});
+		}
+	}
+
+	protected String getToolTip(MUILabel element) {
+		String overrideTip = (String) ((MUIElement) element).getTransientData()
+				.get(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY);
+		return overrideTip == null ? element.getLocalizedTooltip() : overrideTip;
+	}
+
+	protected Image getImageFromURI(String iconURI) {
+		if (iconURI == null || iconURI.length() == 0)
+			return null;
+
+		Image image = imageMap.get(iconURI);
+		if (image == null) {
+			image = resUtils.imageDescriptorFromURI(URI.createURI(iconURI))
+					.createImage();
+			imageMap.put(iconURI, image);
+		}
+		return image;
+	}
+
+	@Override
+	public Image getImage(MUILabel element) {
+		Image image = (Image) ((MUIElement) element).getTransientData().get(
+				IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY);
+		if (image == null || image.isDisposed()) {
+			image = getImageFromURI(getIconURI(element));
+		}
+
+		if (image != null) {
+			image = adornImage((MUIElement) element, image);
+		}
+
+		return image;
+	}
+
+	private String getIconURI(MUILabel element) {
+		if (element instanceof MPart) {
+			MPart part = (MPart) element;
+			String iconURI = (String) part.getTransientData().get(ICON_URI_FOR_PART);
+			if (iconURI != null) {
+				return iconURI;
+			}
+
+			MPartDescriptor desc = modelService.getPartDescriptor(part.getElementId());
+			iconURI = desc != null && desc.getIconURI() != null ? desc.getIconURI() : element.getIconURI();
+			part.getTransientData().put(ICON_URI_FOR_PART, iconURI);
+
+			return iconURI;
+		}
+		return element.getIconURI();
+	}
+
+	/**
+	 * @param element
+	 * @param image
+	 * @return
+	 */
+	private Image adornImage(MUIElement element, Image image) {
+		// Remove and dispose any previous adorned image
+		Image previouslyAdornedImage = (Image) element.getTransientData().get(
+				"previouslyAdorned"); //$NON-NLS-1$
+		if (previouslyAdornedImage != null
+				&& !previouslyAdornedImage.isDisposed())
+			previouslyAdornedImage.dispose();
+		element.getTransientData().remove(IPresentationEngine.ADORNMENT_PIN);
+
+		Image adornedImage = image;
+		if (element.getTags().contains(IPresentationEngine.ADORNMENT_PIN)) {
+			adornedImage = resUtils.adornImage(image, pinImage);
+			if (adornedImage != image)
+				element.getTransientData().put(
+						"previouslyAdorned", adornedImage); //$NON-NLS-1$
+		}
+
+		return adornedImage;
+	}
+
+	/**
+	 * Calculates the index of the element in terms of the other <b>rendered</b>
+	 * elements. This is useful when 'inserting' elements in the middle of
+	 * existing, rendered parents.
+	 *
+	 * @param element
+	 *            The element to get the index for
+	 * @return The visible index or -1 if the element is not a child of the
+	 *         parent
+	 */
+	protected int calcVisibleIndex(MUIElement element) {
+		MElementContainer<MUIElement> parent = element.getParent();
+
+		int curIndex = 0;
+		for (MUIElement child : parent.getChildren()) {
+			if (child == element) {
+				return curIndex;
+			}
+
+			if (child.getWidget() != null)
+				curIndex++;
+		}
+		return -1;
+	}
+
+	protected int calcIndex(MUIElement element) {
+		MElementContainer<MUIElement> parent = element.getParent();
+		return parent.getChildren().indexOf(element);
+	}
+
+	@Override
+	public void childRendered(MElementContainer<MUIElement> parentElement,
+			MUIElement element) {
+	}
+
+	@Override
+	public void init(IEclipseContext context) {
+		super.init(context);
+
+		resUtils = (ISWTResourceUtilities) context.get(IResourceUtilities.class
+				.getName());
+		pinImage = getImageFromURI(pinURI);
+
+		Display.getCurrent().disposeExec(new Runnable() {
+			@Override
+			public void run() {
+				for (Image image : imageMap.values()) {
+					image.dispose();
+				}
+			}
+		});
+	}
+
+	@Override
+	protected boolean requiresFocus(MPart element) {
+		MUIElement focussed = getModelElement(Display.getDefault()
+				.getFocusControl());
+		if (focussed == null) {
+			return true;
+		}
+		// we ignore menus
+		do {
+			if (focussed == element || focussed == element.getToolbar()) {
+				return false;
+			}
+			focussed = focussed.getParent();
+		} while (focussed != null);
+		return true;
+	}
+
+	static protected MUIElement getModelElement(Control ctrl) {
+		if (ctrl == null)
+			return null;
+
+		MUIElement element = (MUIElement) ctrl
+				.getData(AbstractPartRenderer.OWNING_ME);
+		if (element != null) {
+			return element;
+			// FIXME: DndUtil.getModelElement() has the following check;
+			// do we need this?
+			// if (modelService.getTopLevelWindowFor(element) == topLevelWindow)
+			// {
+			// return element;
+			// }
+			// return null;
+		}
+
+		return getModelElement(ctrl.getParent());
+	}
+
+	@Override
+	public void forceFocus(MUIElement element) {
+		if (element.getWidget() instanceof Control) {
+			// Have SWT set the focus
+			Control ctrl = (Control) element.getWidget();
+			if (!ctrl.isDisposed())
+				ctrl.forceFocus();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashLayout.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashLayout.java
new file mode 100644
index 0000000..3b0b70b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashLayout.java
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.ui.model.application.ui.MGenericTile;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.widgets.Shell;
+
+public class SashLayout extends Layout {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	// The minimum value (as a percentage) that a sash can be dragged to
+	int minSashPercent = 10;
+
+	int marginLeft = 0;
+	int marginRight = 0;
+	int marginTop = 0;
+	int marginBottom = 0;
+	int sashWidth = 4;
+
+	MUIElement root;
+	private Composite host;
+
+	class SashRect {
+		Rectangle rect;
+		MGenericTile<?> container;
+		MUIElement left;
+		MUIElement right;
+
+		public SashRect(Rectangle rect, MGenericTile<?> container,
+				MUIElement left, MUIElement right) {
+			this.container = container;
+			this.rect = rect;
+			this.left = left;
+			this.right = right;
+		}
+	}
+
+	List<SashRect> sashes = new ArrayList<SashRect>();
+
+	boolean draggingSashes = false;
+	List<SashRect> sashesToDrag;
+
+	public boolean layoutUpdateInProgress = false;
+
+	public SashLayout(final Composite host, MUIElement root) {
+		this.root = root;
+		this.host = host;
+		// RAP does not support mouse track/move listeners
+		// host.addMouseTrackListener(new MouseTrackListener() {
+		// @Override
+		// public void mouseHover(MouseEvent e) {
+		// }
+		//
+		// @Override
+		// public void mouseExit(MouseEvent e) {
+		// host.setCursor(null);
+		// }
+		//
+		// @Override
+		// public void mouseEnter(MouseEvent e) {
+		// }
+		// });
+		//
+		// host.addMouseMoveListener(new MouseMoveListener() {
+		// @Override
+		// public void mouseMove(final MouseEvent e) {
+		// if (!draggingSashes) {
+		// // Set the cursor feedback
+		// List<SashRect> sashList = getSashRects(e.x, e.y);
+		// if (sashList.size() == 0) {
+		// host.setCursor(host.getDisplay().getSystemCursor(
+		// SWT.CURSOR_ARROW));
+		// } else if (sashList.size() == 1) {
+		// if (sashList.get(0).container.isHorizontal())
+		// host.setCursor(host.getDisplay().getSystemCursor(
+		// SWT.CURSOR_SIZEWE));
+		// else
+		// host.setCursor(host.getDisplay().getSystemCursor(
+		// SWT.CURSOR_SIZENS));
+		// } else {
+		// host.setCursor(host.getDisplay().getSystemCursor(
+		// SWT.CURSOR_SIZEALL));
+		// }
+		// } else {
+		// try {
+		// layoutUpdateInProgress = true;
+		// adjustWeights(sashesToDrag, e.x, e.y);
+		// host.layout();
+		// host.update();
+		// } finally {
+		// layoutUpdateInProgress = false;
+		// }
+		// }
+		// }
+		// });
+		//
+		// host.addMouseListener(new MouseListener() {
+		// @Override
+		// public void mouseUp(MouseEvent e) {
+		// host.setCapture(false);
+		// draggingSashes = false;
+		// }
+		//
+		// @Override
+		// public void mouseDown(MouseEvent e) {
+		// if (e.button != 1) {
+		// return;
+		// }
+		//
+		// sashesToDrag = getSashRects(e.x, e.y);
+		// if (sashesToDrag.size() > 0) {
+		// draggingSashes = true;
+		// host.setCapture(true);
+		// }
+		// }
+		//
+		// @Override
+		// public void mouseDoubleClick(MouseEvent e) {
+		// }
+		// });
+		//
+		// host.addPaintListener(new PaintListener() {
+		// @Override
+		// public void paintControl(PaintEvent e) {
+		// // for (SashRect sr : sashes) {
+		// // Color color;
+		// // if (sr.container.isHorizontal())
+		// // color = e.display.getSystemColor(SWT.COLOR_MAGENTA);
+		// // else
+		// // color = e.display.getSystemColor(SWT.COLOR_CYAN);
+		// // e.gc.setForeground(color);
+		// // e.gc.setBackground(color);
+		// // e.gc.fillRectangle(sr.rect);
+		// // }
+		// }
+		// });
+	}
+
+	@Override
+	protected void layout(Composite composite, boolean flushCache) {
+		if (root == null)
+			return;
+
+		Rectangle bounds = composite.getBounds();
+		if (composite instanceof Shell)
+			bounds = ((Shell) composite).getClientArea();
+		else {
+			bounds.x = 0;
+			bounds.y = 0;
+		}
+
+		bounds.width -= (marginLeft + marginRight);
+		bounds.height -= (marginTop + marginBottom);
+		bounds.x += marginLeft;
+		bounds.y += marginTop;
+
+		sashes.clear();
+		tileSubNodes(bounds, root);
+		// RAP: Use real Sash widgets instead of mouse track/move listeners
+		updateSashWidgets();
+		// RAPEND
+	}
+
+	// RAP: Use real Sash widgets instead of mouse track/move listeners
+	List<Sash> sashWidgets = new ArrayList<Sash>();
+	private static final String SELECTION_LISTENER_ID = "selListener"; //$NON-NLS-1$
+
+	private void updateSashWidgets() {
+		for (int i = 0; i < sashes.size(); i++) {
+			SashRect sashRect = sashes.get(i);
+			if (i < sashWidgets.size()) {
+				Sash sashWidget = sashWidgets.get(i);
+				if (isSameOrientation(sashWidget, sashRect)) {
+					sashWidget.setBounds(sashRect.rect);
+					sashWidget.removeListener(SWT.Selection, (Listener) sashWidget.getData(SELECTION_LISTENER_ID));
+
+					SelectionListener selListener = new SelectionListener(sashRect, sashWidget);
+					sashWidget.setData(SELECTION_LISTENER_ID, selListener);
+					sashWidget.addListener(SWT.Selection, selListener);
+				} else {
+					sashWidgets.set(i, createSash(sashRect)).dispose();
+				}
+			} else {
+				sashWidgets.add(createSash(sashRect));
+			}
+		}
+		while (sashWidgets.size() > sashes.size()) {
+			sashWidgets.remove(sashWidgets.size() - 1).dispose();
+		}
+	}
+
+	class SelectionListener implements Listener {
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		SashRect sashRect;
+		Sash sash;
+
+		public SelectionListener(SashRect sr, Sash sash) {
+			sashRect = sr;
+			this.sash = sash;
+		}
+
+		@Override
+		public void handleEvent(Event event) {
+			Display display = host.getDisplay();
+			Point cursorLocation = display.getCursorLocation();
+			Point mapped = display.map(null, host, cursorLocation);
+			List<SashRect> sashesToDrag = new ArrayList<SashLayout.SashRect>();
+			sashesToDrag.add(sashRect);
+			adjustWeights(sashesToDrag, mapped.x, mapped.y);
+			host.layout();
+			host.update();
+		}
+	}
+
+	private Sash createSash(final SashRect sashRect) {
+		boolean horizontal = !sashRect.container.isHorizontal();
+		Sash sash = new Sash(host, horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
+		sash.setBounds(sashRect.rect);
+
+		SelectionListener selListener = new SelectionListener(sashRect, sash);
+		sash.setData(SELECTION_LISTENER_ID, selListener);
+		sash.addListener(SWT.Selection, selListener);
+		return sash;
+	}
+
+	private boolean isSameOrientation(Sash sash, SashRect sashRect) {
+		boolean isSashHorizontal = (sash.getStyle() & SWT.HORIZONTAL) != 0;
+		boolean isSashContainerHorizontal = sashRect.container.isHorizontal();
+		return isSashHorizontal != isSashContainerHorizontal;
+	}
+	// RAPEND
+
+	protected void adjustWeights(List<SashRect> sashes, int curX, int curY) {
+		for (SashRect sr : sashes) {
+			int totalWeight = getWeight(sr.left) + getWeight(sr.right);
+			int minSashValue = (int) (((totalWeight / 100.0) * minSashPercent) + 0.5);
+
+			Rectangle leftRect = getRectangle(sr.left);
+			Rectangle rightRect = getRectangle(sr.right);
+			if (leftRect == null || rightRect == null)
+				continue;
+
+			int leftWeight;
+			int rightWeight;
+
+			if (sr.container.isHorizontal()) {
+				double left = leftRect.x;
+				double right = rightRect.x + rightRect.width;
+				double pct = (curX - left) / (right - left);
+				leftWeight = (int) ((totalWeight * pct) + 0.5);
+				if (leftWeight < minSashValue)
+					leftWeight = minSashValue;
+				if (leftWeight > (totalWeight - minSashValue))
+					leftWeight = totalWeight - minSashValue;
+				rightWeight = totalWeight - leftWeight;
+			} else {
+				double top = leftRect.y;
+				double bottom = rightRect.y + rightRect.height;
+				double pct = (curY - top) / (bottom - top);
+				leftWeight = (int) ((totalWeight * pct) + 0.5);
+				if (leftWeight < minSashValue)
+					leftWeight = minSashValue;
+				if (leftWeight > (totalWeight - minSashValue))
+					leftWeight = totalWeight - minSashValue;
+				rightWeight = totalWeight - leftWeight;
+			}
+
+			setWeight(sr.left, leftWeight);
+			setWeight(sr.right, rightWeight);
+		}
+	}
+
+	private void setWeight(MUIElement element, int weight) {
+		element.setContainerData(Integer.toString(weight));
+	}
+
+	private Rectangle getRectangle(MUIElement element) {
+		if (element.getWidget() instanceof Rectangle)
+			return (Rectangle) element.getWidget();
+		else if (element.getWidget() instanceof Control)
+			return ((Control) (element.getWidget())).getBounds();
+		return null;
+	}
+
+	protected List<SashRect> getSashRects(int x, int y) {
+		List<SashRect> srs = new ArrayList<SashRect>();
+		Rectangle target = new Rectangle(x - 5, y - 5, 10, 10);
+		for (SashRect sr : sashes) {
+			if (!sr.container.getTags().contains(IPresentationEngine.NO_MOVE)
+					&& sr.rect.intersects(target))
+				srs.add(sr);
+		}
+		return srs;
+	}
+
+	@Override
+	protected Point computeSize(Composite composite, int wHint, int hHint,
+			boolean flushCache) {
+		return new Point(600, 400);
+	}
+
+	private int totalWeight(MGenericTile<?> node) {
+		int total = 0;
+		for (MUIElement subNode : node.getChildren()) {
+			if (subNode.isToBeRendered() && subNode.isVisible())
+				total += getWeight(subNode);
+		}
+		return total;
+	}
+
+	private void tileSubNodes(Rectangle bounds, MUIElement node) {
+		if (node != root)
+			setRectangle(node, bounds);
+
+		if (!(node instanceof MGenericTile<?>))
+			return;
+
+		MGenericTile<?> sashContainer = (MGenericTile<?>) node;
+		List<MUIElement> visibleChildren = getVisibleChildren(sashContainer);
+		int childCount = visibleChildren.size();
+
+		// How many pixels do we have?
+		int availableWidth = sashContainer.isHorizontal() ? bounds.width
+				: bounds.height;
+
+		// Subtract off the room for the sashes
+		availableWidth -= ((childCount - 1) * sashWidth);
+
+		// Get the total of the weights
+		double totalWeight = totalWeight(sashContainer);
+		int tilePos = sashContainer.isHorizontal() ? bounds.x : bounds.y;
+
+		MUIElement prev = null;
+		for (MUIElement subNode : visibleChildren) {
+			// Add a 'sash' between this node and the 'prev'
+			if (prev != null) {
+				Rectangle sashRect = sashContainer.isHorizontal() ? new Rectangle(
+						tilePos, bounds.y, sashWidth, bounds.height)
+						: new Rectangle(bounds.x, tilePos, bounds.width,
+								sashWidth);
+				sashes.add(new SashRect(sashRect, sashContainer, prev, subNode));
+				host.redraw(sashRect.x, sashRect.y, sashRect.width,
+						sashRect.height, false);
+				tilePos += sashWidth;
+			}
+
+			// Calc the new size as a %'age of the total
+			double ratio = getWeight(subNode) / totalWeight;
+			int newSize = (int) ((availableWidth * ratio) + 0.5);
+
+			Rectangle subBounds = sashContainer.isHorizontal() ? new Rectangle(
+					tilePos, bounds.y, newSize, bounds.height) : new Rectangle(
+					bounds.x, tilePos, bounds.width, newSize);
+			tilePos += newSize;
+
+			tileSubNodes(subBounds, subNode);
+			prev = subNode;
+		}
+	}
+
+	/**
+	 * @param node
+	 * @param bounds
+	 */
+	private void setRectangle(MUIElement node, Rectangle bounds) {
+		if (node.getWidget() instanceof Control) {
+			Control ctrl = (Control) node.getWidget();
+			ctrl.setBounds(bounds);
+		} else if (node.getWidget() instanceof Rectangle) {
+			Rectangle theRect = (Rectangle) node.getWidget();
+			theRect.x = bounds.x;
+			theRect.y = bounds.y;
+			theRect.width = bounds.width;
+			theRect.height = bounds.height;
+		}
+	}
+
+	private List<MUIElement> getVisibleChildren(MGenericTile<?> sashContainer) {
+		List<MUIElement> visKids = new ArrayList<MUIElement>();
+		for (MUIElement child : sashContainer.getChildren()) {
+			if (child.isToBeRendered() && child.isVisible())
+				visKids.add(child);
+		}
+		return visKids;
+	}
+
+	private static int getWeight(MUIElement element) {
+		String info = element.getContainerData();
+		if (info == null || info.length() == 0) {
+			return 0;
+		}
+
+		try {
+			int value = Integer.parseInt(info);
+			return value;
+		} catch (NumberFormatException e) {
+			return 0;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java
new file mode 100644
index 0000000..eebebe7
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SashRenderer.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 441150, 441120
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.osgi.service.event.Event;
+
+/**
+ * Default SWT renderer responsible for a MPartSashContainer. See
+ * {@link WorkbenchRendererFactory}
+ */
+public class SashRenderer extends SWTPartRenderer {
+
+	private static final int UNDEFINED_WEIGHT = -1;
+	private static final int DEFAULT_WEIGHT = 5000;
+
+	private int processedContent = 0;
+
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void subscribeTopicOrientationChanged(@UIEventTopic(UIEvents.GenericTile.TOPIC_HORIZONTAL) Event event) {
+		// Ensure that this event is for a MPartSashContainer
+		MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (element.getRenderer() != SashRenderer.this) {
+			return;
+		}
+		forceLayout((MElementContainer<MUIElement>) element);
+	}
+
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void subscribeTopicSashWeightChanged(@UIEventTopic(UIEvents.UIElement.TOPIC_CONTAINERDATA) Event event) {
+		// Ensure that this event is for a MPartSashContainer
+		MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (element.getRenderer() != SashRenderer.this) {
+			return;
+		}
+		forceLayout((MElementContainer<MUIElement>) element);
+	}
+
+	/**
+	 * @param pscModel
+	 */
+	protected void forceLayout(MElementContainer<MUIElement> pscModel) {
+		if (processedContent != 0) {
+			return;
+		}
+		// layout the containing Composite
+		while (!(pscModel.getWidget() instanceof Composite))
+			pscModel = pscModel.getParent();
+
+		Composite s = (Composite) pscModel.getWidget();
+		Layout layout = s.getLayout();
+		if (layout instanceof SashLayout) {
+			if (((SashLayout) layout).layoutUpdateInProgress) {
+				return;
+			}
+		}
+		s.layout(true, true);
+	}
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		MUIElement elementParent = element.getParent();
+		if (elementParent == null && element.getCurSharedRef() != null)
+			elementParent = element.getCurSharedRef();
+
+		if (elementParent != null && elementParent.getRenderer() == this) {
+			Rectangle newRect = new Rectangle(0, 0, 0, 0);
+
+			// If my layout's container gets disposed 'unbind' the sash elements
+			if (parent instanceof Composite) {
+				((Composite) parent).addDisposeListener(new DisposeListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						element.setWidget(null);
+						element.setRenderer(null);
+					}
+				});
+			}
+			return newRect;
+		}
+
+		// Check to see if this is a new PSC added 'above' the previous 'root'
+		// sash
+		Composite sashComposite = null;
+		MPartSashContainer psc = (MPartSashContainer) element;
+		for (MPartSashContainerElement psce : psc.getChildren()) {
+			if (psce instanceof MPartSashContainer
+					&& psce.getWidget() instanceof Composite) {
+				// 'Adopt' the previous root's layout / composite
+				sashComposite = (Composite) psce.getWidget();
+				bindWidget(psce, new Rectangle(0, 0, 0, 0));
+			}
+		}
+		// This is a 'root' sash container, create a composite
+		if (sashComposite == null)
+			sashComposite = new Composite((Composite) parent, SWT.NONE);
+		sashComposite.setLayout(new SashLayout(sashComposite, element));
+
+		return sashComposite;
+	}
+
+	@Override
+	public void childRendered(MElementContainer<MUIElement> parentElement,
+			MUIElement element) {
+		super.childRendered(parentElement, element);
+
+		// Ensure that the element's 'containerInfo' is initialized
+		int weight = getWeight(element);
+		if (weight == UNDEFINED_WEIGHT) {
+			element.setContainerData(Integer.toString(DEFAULT_WEIGHT));
+		}
+
+		forceLayout(parentElement);
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		try {
+			processedContent++;
+			super.processContents(container);
+		} finally {
+			processedContent--;
+			if (processedContent == 0) {
+				forceLayout(container);
+			}
+		}
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		forceLayout(parentElement);
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement element) {
+		// OK, find the 'root' of the sash container
+		MUIElement parentElement = element.getParent();
+		while (parentElement.getRenderer() == this
+				&& !(parentElement.getWidget() instanceof Composite))
+			parentElement = parentElement.getParent();
+
+		if (parentElement.getWidget() instanceof Composite)
+			return parentElement.getWidget();
+
+		return null;
+	}
+
+	private static int getWeight(MUIElement element) {
+		String info = element.getContainerData();
+		if (info == null || info.length() == 0) {
+			element.setContainerData(Integer.toString(10000));
+			info = element.getContainerData();
+		}
+
+		try {
+			int value = Integer.parseInt(info);
+			return value;
+		} catch (NumberFormatException e) {
+			return UNDEFINED_WEIGHT;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SeparatorRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SeparatorRenderer.java
new file mode 100644
index 0000000..e635497
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SeparatorRenderer.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import java.util.List;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Create a contribute part.
+ */
+public class SeparatorRenderer extends SWTPartRenderer {
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		Widget newSep = null;
+		if (!element.isVisible()) {
+			return null;
+		}
+		int objIndex = calcIndex(element);
+		int addIndex = calcVisibleIndex(element);
+		MUIElement nextVisibleChild = getNextVisibleChild(element, objIndex);
+		if (addIndex == 0) {
+			return null;
+		}
+		if (nextVisibleChild == null) {
+			return null;
+		}
+		if (nextVisibleChild.isVisible()
+				&& (nextVisibleChild instanceof MToolBarSeparator)) {
+			return null;
+		}
+		if (element instanceof MToolBarSeparator) {
+			ToolBar tb = parent instanceof ToolBar ? (ToolBar) parent
+					: (ToolBar) element.getParent().getWidget();
+			newSep = new ToolItem(tb, SWT.SEPARATOR, addIndex);
+		}
+
+		return newSep;
+	}
+
+	MUIElement getNextVisibleChild(final MUIElement element, int objIndex) {
+		List<MUIElement> children = element.getParent().getChildren();
+		for (int i = objIndex + 1; i < children.size(); i++) {
+			MUIElement child = children.get(i);
+			if (child.isVisible()) {
+				return child;
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java
new file mode 100644
index 0000000..e30f823
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java
@@ -0,0 +1,1865 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2015 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@vogella.com> - Bug 429728, 430166, 441150, 442285
+ *     Andrey Loskutov <loskutov@gmx.de> - Bug 337588, 388476, 461573
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.extensions.Preference;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil;
+import org.eclipse.e4.ui.internal.workbench.renderers.swt.BasicPartList;
+import org.eclipse.e4.ui.internal.workbench.renderers.swt.SWTRenderersMessages;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.LegacyActionTools;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabFolder2Adapter;
+import org.eclipse.swt.custom.CTabFolderEvent;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MenuDetectListener;
+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.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Monitor;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * SWT default renderer for a MPartStack model elements
+ *
+ * Style bits for the underlying CTabFolder can be set via the
+ * IPresentation.STYLE_OVERRIDE_KEY key
+ *
+ */
+public class StackRenderer extends LazyStackRenderer implements IPreferenceChangeListener {
+	/**
+	 *
+	 */
+	private static final String THE_PART_KEY = "thePart"; //$NON-NLS-1$
+
+	/**
+	 * Key to control the default default value of the "most recently used"
+	 * order enablement
+	 */
+	public static final String MRU_KEY_DEFAULT = "enableMRUDefault"; //$NON-NLS-1$
+
+	/**
+	 * Key to control the actual boolean preference of the "most recently used"
+	 * order enablement
+	 */
+	public static final String MRU_KEY = "enableMRU"; //$NON-NLS-1$
+
+	/**
+	 * Key to switch if the "most recently used" behavior controlled via CSS or
+	 * preferences
+	 */
+	public static final String MRU_CONTROLLED_BY_CSS_KEY = "MRUControlledByCSS"; //$NON-NLS-1$
+
+	/**
+	 * Default default value for MRU behavior.
+	 */
+	public static final boolean MRU_DEFAULT = true;
+
+	/*
+	 * org.eclipse.ui.internal.dialogs.ViewsPreferencePage controls currently
+	 * the MRU behavior via IEclipsePreferences, so that CSS values from the
+	 * themes aren't used.
+	 *
+	 * TODO once we can use preferences from CSS (and update the value on the
+	 * fly) we can switch this default to true, see discussion on bug 388476.
+	 */
+	// private static final boolean MRU_CONTROLLED_BY_CSS_DEFAULT = false;
+
+	@Inject
+	@Preference(nodePath = "org.eclipse.e4.ui.workbench.renderers.swt")
+	private IEclipsePreferences preferences;
+
+	@Inject
+	@Named(WorkbenchRendererFactory.SHARED_ELEMENTS_STORE)
+	Map<MUIElement, Set<MPlaceholder>> renderedMap;
+
+	public static final String TAG_VIEW_MENU = "ViewMenu"; //$NON-NLS-1$
+	private static final String SHELL_CLOSE_EDITORS_MENU = "shell_close_editors_menu"; //$NON-NLS-1$
+	private static final String STACK_SELECTED_PART = "stack_selected_part"; //$NON-NLS-1$
+
+	/**
+	 * Add this tag to prevent the next tab's activation from granting focus
+	 * toac the part. This is used to keep the focus on the CTF when traversing
+	 * the tabs using the keyboard.
+	 */
+	private static final String INHIBIT_FOCUS = "InhibitFocus"; //$NON-NLS-1$
+
+	// Minimum characters in for stacks outside the shared area
+	private static int MIN_VIEW_CHARS = 1;
+
+	// Minimum characters in for stacks inside the shared area
+	private static int MIN_EDITOR_CHARS = 15;
+
+	private Image viewMenuImage;
+
+	@Inject
+	private IEventBroker eventBroker;
+
+	@Inject
+	private IPresentationEngine renderer;
+
+	private EventHandler itemUpdater;
+
+	private EventHandler dirtyUpdater;
+
+	/**
+	 * An event handler for listening to changes to the state of view menus and
+	 * its child menu items. Depending on what state these items are in, the
+	 * view menu should or should not be rendered in the tab folder.
+	 */
+	private EventHandler viewMenuUpdater;
+
+	/**
+	 * An event handler for listening to changes to the children of an element
+	 * container. The tab folder may need to layout itself again if a part's
+	 * toolbar has been changed.
+	 */
+	// private EventHandler tabStateHandler;
+
+	// Manages CSS styling based on active part changes
+	private EventHandler stylingHandler;
+
+	private boolean ignoreTabSelChanges;
+
+	List<CTabItem> getItemsToSet(MPart part) {
+		List<CTabItem> itemsToSet = new ArrayList<CTabItem>();
+
+		MUIElement partParent = part.getParent();
+		if (partParent instanceof MPartStack) {
+			CTabItem item = findItemForPart(part);
+			if (item != null) {
+				itemsToSet.add(findItemForPart(part));
+			}
+		} else if (part.getCurSharedRef() != null) {
+			MWindow topWin = modelService.getTopLevelWindowFor(part);
+			List<MPlaceholder> partRefs = modelService.findElements(topWin,
+					part.getElementId(), MPlaceholder.class, null);
+			for (MPlaceholder ref : partRefs) {
+				CTabItem item = findItemForPart(ref, null);
+				if (item != null) {
+					itemsToSet.add(item);
+				}
+			}
+		}
+
+		return itemsToSet;
+	}
+
+
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void subscribeTopicTransientDataChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TRANSIENTDATA) org.osgi.service.event.Event event) {
+		Object changedElement = event.getProperty(UIEvents.EventTags.ELEMENT);
+
+		if (!(changedElement instanceof MPart))
+			return;
+
+		String key;
+		if (UIEvents.isREMOVE(event)) {
+			key = ((Entry<String, Object>) event
+					.getProperty(UIEvents.EventTags.OLD_VALUE)).getKey();
+		} else {
+			key = ((Entry<String, Object>) event
+					.getProperty(UIEvents.EventTags.NEW_VALUE)).getKey();
+		}
+
+		if (!IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY.equals(key)
+				&& !IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY.equals(key))
+			return;
+
+		MPart part = (MPart) changedElement;
+		List<CTabItem> itemsToSet = getItemsToSet(part);
+		for (CTabItem item : itemsToSet) {
+			if (key.equals(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY)) {
+				item.setImage(getImage(part));
+			} else if (key
+					.equals(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY)) {
+				String newTip = getToolTip(part);
+				item.setToolTipText(getToolTip(newTip));
+			}
+		}
+	}
+
+	/**
+	 * Handles changes in tags
+	 *
+	 * @param event
+	 */
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MPart))
+			return;
+
+		final MPart part = (MPart) changedObj;
+		CTabItem item = findItemForPart(part);
+		if (item == null || item.isDisposed())
+			return;
+
+		if (UIEvents.isADD(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE,
+					IPresentationEngine.ADORNMENT_PIN)) {
+				item.setImage(getImage(part));
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE,
+					IPresentationEngine.ADORNMENT_PIN)) {
+				item.setImage(getImage(part));
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicChildrenChanged(@UIEventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
+
+		Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+		// only interested in changes to toolbars
+		if (!(changedObj instanceof MToolBar)) {
+			return;
+		}
+
+		MUIElement container = modelService.getContainer((MUIElement) changedObj);
+		// check if this is a part's toolbar
+		if (container instanceof MPart) {
+			MElementContainer<?> parent = ((MPart) container).getParent();
+			// only relayout if this part is the selected element and we
+			// actually rendered this element
+			if (parent instanceof MPartStack && parent.getSelectedElement() == container
+					&& parent.getRenderer() == StackRenderer.this) {
+				Object widget = parent.getWidget();
+				if (widget instanceof CTabFolder) {
+					adjustTopRight((CTabFolder) widget);
+				}
+			}
+		}
+	}
+
+	@Override
+	protected boolean requiresFocus(MPart element) {
+		MUIElement inStack = element.getCurSharedRef() != null ? element
+				.getCurSharedRef() : element;
+		if (inStack.getParent() != null
+				&& inStack.getParent().getTransientData()
+						.containsKey(INHIBIT_FOCUS)) {
+			inStack.getParent().getTransientData().remove(INHIBIT_FOCUS);
+			return false;
+		}
+
+		return super.requiresFocus(element);
+	}
+
+	@PostConstruct
+	public void init() {
+		super.init(eventBroker);
+
+		preferences.addPreferenceChangeListener(this);
+		preferenceChange(null);
+
+		// TODO: Refactor using findItemForPart(MPart) method
+		itemUpdater = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				MUIElement element = (MUIElement) event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+				if (!(element instanceof MPart))
+					return;
+
+				MPart part = (MPart) element;
+
+				String attName = (String) event
+						.getProperty(UIEvents.EventTags.ATTNAME);
+				Object newValue = event
+						.getProperty(UIEvents.EventTags.NEW_VALUE);
+
+				// is this a direct child of the stack?
+				if (element.getParent() != null
+						&& element.getParent().getRenderer() == StackRenderer.this) {
+					CTabItem cti = findItemForPart(element, element.getParent());
+					if (cti != null) {
+						updateTab(cti, part, attName, newValue);
+					}
+					return;
+				}
+
+				// Do we have any stacks with place holders for the element
+				// that's changed?
+				MWindow win = modelService.getTopLevelWindowFor(part);
+				List<MPlaceholder> refs = modelService.findElements(win, null,
+						MPlaceholder.class, null);
+				if (refs != null) {
+					for (MPlaceholder ref : refs) {
+						if (ref.getRef() != part)
+							continue;
+
+						MElementContainer<MUIElement> refParent = ref
+								.getParent();
+						// can be null, see bug 328296
+						if (refParent != null
+								&& refParent.getRenderer() instanceof StackRenderer) {
+							CTabItem cti = findItemForPart(ref, refParent);
+							if (cti != null) {
+								updateTab(cti, part, attName, newValue);
+							}
+						}
+					}
+				}
+			}
+		};
+
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
+
+		// TODO: Refactor using findItemForPart(MPart) method
+		dirtyUpdater = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				Object objElement = event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+
+				// Ensure that this event is for a MMenuItem
+				if (!(objElement instanceof MPart)) {
+					return;
+				}
+
+				// Extract the data bits
+				MPart part = (MPart) objElement;
+
+				String attName = (String) event
+						.getProperty(UIEvents.EventTags.ATTNAME);
+				Object newValue = event
+						.getProperty(UIEvents.EventTags.NEW_VALUE);
+
+				// Is the part directly under the stack?
+				MElementContainer<MUIElement> parent = part.getParent();
+				if (parent != null
+						&& parent.getRenderer() == StackRenderer.this) {
+					CTabItem cti = findItemForPart(part, parent);
+					if (cti != null) {
+						updateTab(cti, part, attName, newValue);
+					}
+					return;
+				}
+
+				// Do we have any stacks with place holders for the element
+				// that's changed?
+				Set<MPlaceholder> refs = renderedMap.get(part);
+				if (refs != null) {
+					for (MPlaceholder ref : refs) {
+						MElementContainer<MUIElement> refParent = ref
+								.getParent();
+						if (refParent.getRenderer() instanceof StackRenderer) {
+							CTabItem cti = findItemForPart(ref, refParent);
+							if (cti != null) {
+								updateTab(cti, part, attName, newValue);
+							}
+						}
+					}
+				}
+			}
+		};
+
+		eventBroker.subscribe(UIEvents.buildTopic(UIEvents.Dirtyable.TOPIC,
+				UIEvents.Dirtyable.DIRTY), dirtyUpdater);
+
+		viewMenuUpdater = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				Object objElement = event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+
+				// Ensure that this event is for a MMenuItem
+				if (!(objElement instanceof MMenuElement)) {
+					return;
+				}
+
+				// Ensure that it's a View part's menu
+				MMenuElement menuModel = (MMenuElement) objElement;
+				MUIElement menuParent = modelService.getContainer(menuModel);
+				if (!(menuParent instanceof MPart))
+					return;
+
+				MPart element = (MPart) menuParent;
+				MUIElement parentElement = element.getParent();
+				if (parentElement == null) {
+					MPlaceholder placeholder = element.getCurSharedRef();
+					if (placeholder == null) {
+						return;
+					}
+
+					parentElement = placeholder.getParent();
+					if (parentElement == null) {
+						return;
+					}
+				}
+
+				Object widget = parentElement.getWidget();
+				if (widget instanceof CTabFolder) {
+					adjustTopRight((CTabFolder) widget);
+				}
+			}
+		};
+		eventBroker
+				.subscribe(UIEvents.UIElement.TOPIC_VISIBLE, viewMenuUpdater);
+		eventBroker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED,
+				viewMenuUpdater);
+
+
+		stylingHandler = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				MUIElement changed = (MUIElement) event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+				if (!(changed instanceof MPart))
+					return;
+
+				MPart newActivePart = (MPart) changed;
+				MUIElement partParent = newActivePart.getParent();
+				if (partParent == null
+						&& newActivePart.getCurSharedRef() != null)
+					partParent = newActivePart.getCurSharedRef().getParent();
+
+				// Skip sash containers
+				while (partParent != null
+						&& partParent instanceof MPartSashContainer)
+					partParent = partParent.getParent();
+
+				// Ensure the stack of a split part gets updated when one
+				// of its internal parts gets activated
+				if (partParent instanceof MCompositePart) {
+					partParent = partParent.getParent();
+				}
+
+				MPartStack pStack = (MPartStack) (partParent instanceof MPartStack ? partParent
+						: null);
+
+				List<String> tags = new ArrayList<String>();
+				tags.add(CSSConstants.CSS_ACTIVE_CLASS);
+				List<MUIElement> activeElements = modelService
+						.findElements(modelService.getTopLevelWindowFor(newActivePart), null,
+						MUIElement.class, tags);
+				for (MUIElement element : activeElements) {
+					if (element instanceof MPartStack && element != pStack) {
+						styleElement(element, false);
+					} else if (element instanceof MPart
+							&& element != newActivePart) {
+						styleElement(element, false);
+					}
+				}
+
+				if (pStack != null)
+					styleElement(pStack, true);
+				styleElement(newActivePart, true);
+			}
+		};
+		eventBroker.subscribe(UIEvents.UILifeCycle.ACTIVATE, stylingHandler);
+
+		// tabStateHandler = new TabStateHandler();
+		// eventBroker.subscribe(UIEvents.ApplicationElement.TOPIC_TAGS,
+		// tabStateHandler);
+		// eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT,
+		// tabStateHandler);
+	}
+
+	protected void updateTab(CTabItem cti, MPart part, String attName,
+			Object newValue) {
+		if (UIEvents.UILabel.LABEL.equals(attName)
+				|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+			String newName = (String) newValue;
+			cti.setText(getLabel(part, newName));
+		} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+			cti.setImage(getImage(part));
+		} else if (UIEvents.UILabel.TOOLTIP.equals(attName)
+				|| UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
+			String newTTip = (String) newValue;
+			cti.setToolTipText(getToolTip(newTTip));
+		} else if (UIEvents.Dirtyable.DIRTY.equals(attName)) {
+			Boolean dirtyState = (Boolean) newValue;
+			String text = cti.getText();
+			boolean hasAsterisk = text.length() > 0 && text.charAt(0) == '*';
+			if (dirtyState.booleanValue()) {
+				if (!hasAsterisk) {
+					cti.setText('*' + text);
+				}
+			} else if (hasAsterisk) {
+				cti.setText(text.substring(1));
+			}
+		}
+	}
+
+	@PreDestroy
+	public void contextDisposed() {
+		super.contextDisposed(eventBroker);
+
+		eventBroker.unsubscribe(itemUpdater);
+		eventBroker.unsubscribe(dirtyUpdater);
+		eventBroker.unsubscribe(viewMenuUpdater);
+		eventBroker.unsubscribe(stylingHandler);
+		// eventBroker.unsubscribe(tabStateHandler);
+	}
+
+	private String getLabel(MUILabel itemPart, String newName) {
+		if (newName == null) {
+			newName = ""; //$NON-NLS-1$
+		} else {
+			newName = LegacyActionTools.escapeMnemonics(newName);
+		}
+
+		if (itemPart instanceof MDirtyable && ((MDirtyable) itemPart).isDirty()) {
+			newName = '*' + newName;
+		}
+		return newName;
+	}
+
+	private String getToolTip(String newToolTip) {
+		return newToolTip == null || newToolTip.length() == 0 ? null
+				: LegacyActionTools.escapeMnemonics(newToolTip);
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MPartStack) || !(parent instanceof Composite))
+			return null;
+
+		MPartStack pStack = (MPartStack) element;
+
+		Composite parentComposite = (Composite) parent;
+
+		// Ensure that all rendered PartStacks have an Id
+		if (element.getElementId() == null
+				|| element.getElementId().length() == 0) {
+			String generatedId = "PartStack@" + Integer.toHexString(element.hashCode()); //$NON-NLS-1$
+			element.setElementId(generatedId);
+		}
+
+		int styleOverride = getStyleOverride(pStack);
+		int style = styleOverride == -1 ? SWT.BORDER : styleOverride;
+		final CTabFolder ctf = new CTabFolder(parentComposite, style);
+		ctf.setMRUVisible(getMRUValue(ctf));
+
+		// Adjust the minimum chars based on the location
+		int location = modelService.getElementLocation(element);
+		if ((location & EModelService.IN_SHARED_AREA) != 0) {
+			ctf.setMinimumCharacters(MIN_EDITOR_CHARS);
+			ctf.setUnselectedCloseVisible(true);
+		} else {
+			ctf.setMinimumCharacters(MIN_VIEW_CHARS);
+			ctf.setUnselectedCloseVisible(false);
+		}
+
+		bindWidget(element, ctf); // ?? Do we need this ?
+
+		// Add a composite to manage the view's TB and Menu
+		addTopRight(ctf);
+
+		return ctf;
+	}
+
+	// private boolean getInitialMRUValue(Control control) {
+	// CSSRenderingUtils util = context.get(CSSRenderingUtils.class);
+	// if (util == null) {
+	// return getMRUValueFromPreferences();
+	// }
+	//
+	// CSSValue value = util.getCSSValue(control,
+	// "MPartStack", "swt-mru-visible"); //$NON-NLS-1$ //$NON-NLS-2$
+	//
+	// if (value == null) {
+	// value = util.getCSSValue(control, "MPartStack", "mru-visible");
+	// //$NON-NLS-1$ //$NON-NLS-2$
+	// }
+	// if (value == null) {
+	// return getMRUValueFromPreferences();
+	// }
+	// return Boolean.parseBoolean(value.getCssText());
+	// }
+
+	private boolean getMRUValue(Control control) {
+		// if (CSSPropertyMruVisibleSWTHandler.isMRUControlledByCSS()) {
+		// return getInitialMRUValue(control);
+		// }
+		return getMRUValueFromPreferences();
+	}
+
+	private boolean getMRUValueFromPreferences() {
+		boolean initialMRUValue = preferences.getBoolean(MRU_KEY_DEFAULT, MRU_DEFAULT);
+		boolean actualValue = preferences.getBoolean(MRU_KEY, initialMRUValue);
+		return actualValue;
+	}
+
+	private void updateMRUValue(CTabFolder ctf) {
+		boolean actualMRUValue = getMRUValue(ctf);
+		ctf.setMRUVisible(actualMRUValue);
+	}
+
+	@Override
+	public void preferenceChange(PreferenceChangeEvent event) {
+		// boolean mruControlledByCSS =
+		// preferences.getBoolean(MRU_CONTROLLED_BY_CSS_KEY,
+		// MRU_CONTROLLED_BY_CSS_DEFAULT);
+		// CSSPropertyMruVisibleSWTHandler.setMRUControlledByCSS(mruControlledByCSS);
+	}
+
+	/**
+	 * @param ctf
+	 */
+	private void addTopRight(CTabFolder ctf) {
+		Composite trComp = new Composite(ctf, SWT.NONE);
+		// trComp.setBackground(Display.getCurrent().getSystemColor(
+		// SWT.COLOR_DARK_CYAN));
+		RowLayout rl = new RowLayout();
+		trComp.setLayout(rl);
+		rl.marginBottom = rl.marginTop = rl.marginRight = rl.marginLeft = 0;
+		ctf.setTopRight(trComp, SWT.RIGHT/* | SWT.WRAP */);
+
+		// Initially it's not visible
+		trComp.setVisible(false);
+
+		// Create a TB for the view's drop-down menu
+		ToolBar menuTB = new ToolBar(trComp, SWT.FLAT | SWT.RIGHT);
+		menuTB.setData(TAG_VIEW_MENU);
+		RowData rd = new RowData();
+		menuTB.setLayoutData(rd);
+		ToolItem ti = new ToolItem(menuTB, SWT.PUSH);
+		ti.setImage(getViewMenuImage());
+		ti.setHotImage(null);
+		ti.setToolTipText(SWTRenderersMessages.viewMenu);
+
+		// Initially it's not visible
+		rd.exclude = true;
+		menuTB.setVisible(false);
+
+		ti.addSelectionListener(new SelectionListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				showMenu((ToolItem) e.widget);
+			}
+
+			@Override
+			public void widgetDefaultSelected(SelectionEvent e) {
+				showMenu((ToolItem) e.widget);
+			}
+		});
+		menuTB.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void getName(AccessibleEvent e) {
+				if (e.childID != ACC.CHILDID_SELF) {
+					Accessible accessible = (Accessible) e.getSource();
+					ToolBar toolBar = (ToolBar) accessible.getControl();
+					if (0 <= e.childID && e.childID < toolBar.getItemCount()) {
+						ToolItem item = toolBar.getItem(e.childID);
+						if (item != null) {
+							e.result = item.getToolTipText();
+						}
+					}
+				}
+			}
+		});
+
+		// Set an initial bounds
+		trComp.pack();
+	}
+
+	boolean adjusting = false;
+
+	public void adjustTopRight(final CTabFolder ctf) {
+		if (adjusting)
+			return;
+
+		adjusting = true;
+
+		try {
+			// Gather the parameters...old part, new part...
+			MPartStack stack = (MPartStack) ctf.getData(OWNING_ME);
+			MUIElement element = stack.getSelectedElement();
+			MPart curPart = (MPart) ctf.getTopRight().getData(THE_PART_KEY);
+			MPart part = null;
+			if (element != null) {
+				part = (MPart) ((element instanceof MPart) ? element
+						: ((MPlaceholder) element).getRef());
+			}
+
+			// Hide the old TB if we're changing
+			if (part != curPart && curPart != null
+ && curPart.getToolbar() != null) {
+				curPart.getToolbar().setVisible(false);
+			}
+
+			Composite trComp = (Composite) ctf.getTopRight();
+			Control[] kids = trComp.getChildren();
+
+			boolean needsTB = part != null && part.getToolbar() != null
+ && part.getToolbar().isToBeRendered();
+
+			// View menu (if any)
+			MMenu viewMenu = getViewMenu(part);
+			boolean needsMenu = viewMenu != null
+					&& hasVisibleMenuItems(viewMenu, part);
+
+			// Check the current state of the TB's
+			ToolBar menuTB = (ToolBar) kids[kids.length - 1];
+
+			// We need to modify the 'exclude' bit based on if the menuTB is
+			// visible or not
+			RowData rd = (RowData) menuTB.getLayoutData();
+			if (needsMenu) {
+				menuTB.getItem(0).setData(THE_PART_KEY, part);
+				menuTB.moveBelow(null);
+				menuTB.pack();
+				rd.exclude = false;
+				menuTB.setVisible(true);
+			} else {
+				menuTB.getItem(0).setData(THE_PART_KEY, null);
+				rd.exclude = true;
+				menuTB.setVisible(false);
+			}
+
+			ToolBar newViewTB = null;
+			if (needsTB && part != null && part.getObject() != null) {
+				part.getToolbar().setVisible(true);
+				newViewTB = (ToolBar) renderer.createGui(part.getToolbar(),
+						ctf.getTopRight(), part.getContext());
+				// We can get calls during shutdown in which case the
+				// rendering engine will return 'null' because you can't
+				// render anything while a removeGui is taking place...
+				if (newViewTB == null) {
+					adjusting = false;
+					return;
+				}
+				newViewTB.moveAbove(null);
+				newViewTB.pack();
+			}
+
+			if (needsMenu || needsTB) {
+				ctf.getTopRight().setData(THE_PART_KEY, part);
+				ctf.getTopRight().pack(true);
+				ctf.getTopRight().setVisible(true);
+			} else {
+				ctf.getTopRight().setData(THE_PART_KEY, null);
+				ctf.getTopRight().setVisible(false);
+			}
+
+			// Pack the result
+			trComp.pack();
+		} finally {
+			adjusting = false;
+		}
+		updateMRUValue(ctf);
+	}
+
+	@Override
+	protected void createTab(MElementContainer<MUIElement> stack,
+			MUIElement element) {
+		MPart part = null;
+		if (element instanceof MPart)
+			part = (MPart) element;
+		else if (element instanceof MPlaceholder) {
+			part = (MPart) ((MPlaceholder) element).getRef();
+			if (part != null) {
+				part.setCurSharedRef((MPlaceholder) element);
+			}
+		}
+
+		CTabFolder ctf = (CTabFolder) stack.getWidget();
+
+		CTabItem cti = findItemForPart(element, stack);
+		if (cti != null) {
+			if (element.getWidget() != null
+					&& cti.getControl() != element.getWidget())
+				cti.setControl((Control) element.getWidget());
+			return;
+		}
+		updateMRUValue(ctf);
+		int createFlags = SWT.NONE;
+		if (part != null && isClosable(part)) {
+			createFlags |= SWT.CLOSE;
+		}
+
+		// Create the tab; we may have more visible tabs than currently shown
+		// (e.g., a result of calling partStack.getChildren().addAll(partList))
+		int index = Math.min(calcIndexFor(stack, element), ctf.getItemCount());
+		cti = new CTabItem(ctf, createFlags, index);
+
+		cti.setData(OWNING_ME, element);
+		cti.setText(getLabel(part, part.getLocalizedLabel()));
+		cti.setImage(getImage(part));
+
+		String toolTip = getToolTip(part);
+		if (toolTip == null)
+			toolTip = part.getLocalizedTooltip();
+		cti.setToolTipText(getToolTip(toolTip));
+		if (element.getWidget() != null) {
+			// The part might have a widget but may not yet have been placed
+			// under this stack, check this
+			Control ctrl = (Control) element.getWidget();
+			if (ctrl.getParent() == ctf)
+				cti.setControl((Control) element.getWidget());
+		}
+	}
+
+	private int calcIndexFor(MElementContainer<MUIElement> stack,
+			final MUIElement part) {
+		int index = 0;
+
+		// Find the -visible- part before this element
+		for (MUIElement mPart : stack.getChildren()) {
+			if (mPart == part)
+				return index;
+			if (mPart.isToBeRendered() && mPart.isVisible())
+				index++;
+		}
+		return index;
+	}
+
+	@Override
+	public void childRendered(
+			final MElementContainer<MUIElement> parentElement,
+			MUIElement element) {
+		super.childRendered(parentElement, element);
+
+		if (!(((MUIElement) parentElement) instanceof MPartStack)
+				|| !(element instanceof MStackElement))
+			return;
+
+		createTab(parentElement, element);
+	}
+
+	private CTabItem findItemForPart(MUIElement element,
+			MElementContainer<MUIElement> stack) {
+		if (stack == null)
+			stack = element.getParent();
+		if (!(stack.getWidget() instanceof CTabFolder))
+			return null;
+		CTabFolder ctf = (CTabFolder) stack.getWidget();
+		if (ctf == null || ctf.isDisposed())
+			return null;
+
+		CTabItem[] items = ctf.getItems();
+		for (int i = 0; i < items.length; i++) {
+			if (items[i].getData(OWNING_ME) == element)
+				return items[i];
+		}
+		return null;
+	}
+
+	public CTabItem findItemForPart(MPart part) {
+		// Invisible parts don't have items
+		if (!part.isToBeRendered())
+			return null;
+
+		// is this a direct child of the stack?
+		if (part.getParent() != null
+				&& part.getParent().getRenderer() == StackRenderer.this) {
+			CTabItem cti = findItemForPart(part, part.getParent());
+			if (cti != null) {
+				return cti;
+			}
+		}
+
+		// Do we have any stacks with place holders for the element
+		// that's changed?
+		MWindow win = modelService.getTopLevelWindowFor(part);
+
+		if (win == null)
+			return null;
+
+		List<MPlaceholder> refs = modelService.findElements(win, null,
+				MPlaceholder.class, null);
+		if (refs != null) {
+			for (MPlaceholder ref : refs) {
+				if (ref.getRef() != part)
+					continue;
+
+				MElementContainer<MUIElement> refParent = ref.getParent();
+				// can be null, see bug 328296
+				if (refParent != null
+						&& refParent.getRenderer() instanceof StackRenderer) {
+					CTabItem cti = findItemForPart(ref, refParent);
+					if (cti != null) {
+						return cti;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		CTabFolder ctf = (CTabFolder) parentElement.getWidget();
+		if (ctf == null)
+			return;
+
+		// Check if we have to reset the currently active child for the stack
+		CTabItem cti = findItemForPart(child, parentElement);
+		if (cti == ctf.getSelection()) {
+			// If we're the only part we need to clear the top right...
+			if (ctf.getItemCount() == 1) {
+				adjustTopRight(ctf);
+			}
+		}
+
+		// find the 'stale' tab for this element and dispose it
+		if (cti != null && !cti.isDisposed()) {
+			cti.setControl(null);
+			cti.dispose();
+		}
+	}
+
+	@Override
+	public void hookControllerLogic(final MUIElement me) {
+		super.hookControllerLogic(me);
+
+		if (!(me instanceof MElementContainer<?>))
+			return;
+
+		@SuppressWarnings("unchecked")
+		final MElementContainer<MUIElement> stack = (MElementContainer<MUIElement>) me;
+
+		// Match the selected TabItem to its Part
+		final CTabFolder ctf = (CTabFolder) me.getWidget();
+
+		// Handle traverse events for accessibility
+		ctf.addTraverseListener(new TraverseListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void keyTraversed(TraverseEvent e) {
+				// FIXME RAP traverse ARROW not supported
+				// if (e.detail == SWT.TRAVERSE_ARROW_NEXT || e.detail ==
+				// SWT.TRAVERSE_ARROW_PREVIOUS) {
+				// me.getTransientData().put(INHIBIT_FOCUS, true);
+				// } else
+				if (e.detail == SWT.TRAVERSE_RETURN) {
+					me.getTransientData().remove(INHIBIT_FOCUS);
+					CTabItem cti = ctf.getSelection();
+					if (cti != null) {
+						MUIElement stackElement = (MUIElement) cti.getData(OWNING_ME);
+						if (stackElement instanceof MPlaceholder)
+							stackElement = ((MPlaceholder) stackElement).getRef();
+						if ((stackElement instanceof MPart) && (ctf.isFocusControl())) {
+							MPart thePart = (MPart) stackElement;
+							renderer.focusGui(thePart);
+						}
+					}
+				}
+			}
+		});
+
+		// Detect activation...picks up cases where the user clicks on the
+		// (already active) tab
+		ctf.addListener(SWT.Activate, new org.eclipse.swt.widgets.Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(org.eclipse.swt.widgets.Event event) {
+				if (event.detail == SWT.MouseDown) {
+					CTabFolder ctf = (CTabFolder) event.widget;
+					if (ctf.getSelection() == null)
+						return;
+
+					// get the item under the cursor
+					Point cp = event.display.getCursorLocation();
+					cp = event.display.map(null, ctf, cp);
+					CTabItem overItem = ctf.getItem(cp);
+
+					// If the item we're over is *not* the current one do
+					// nothing (it'll get activated when the tab changes)
+					if (overItem == null || overItem == ctf.getSelection()) {
+						MUIElement uiElement = (MUIElement) ctf.getSelection()
+								.getData(OWNING_ME);
+						if (uiElement instanceof MPlaceholder)
+							uiElement = ((MPlaceholder) uiElement).getRef();
+						if (uiElement instanceof MPart)
+							activate((MPart) uiElement);
+					}
+				}
+			}
+		});
+
+		ctf.addSelectionListener(new SelectionListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDefaultSelected(SelectionEvent e) {
+			}
+
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				// prevent recursions
+				if (ignoreTabSelChanges)
+					return;
+
+				MUIElement ele = (MUIElement) e.item.getData(OWNING_ME);
+				ele.getParent().setSelectedElement(ele);
+				if (ele instanceof MPlaceholder)
+					ele = ((MPlaceholder) ele).getRef();
+				if (ele instanceof MPart)
+					activate((MPart) ele);
+			}
+		});
+
+		MouseListener mouseListener = new MouseAdapter() {
+
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void mouseDoubleClick(MouseEvent e) {
+				CTabItem item = ctf.getSelection();
+				if (item != null) {
+					MUIElement ele = (MUIElement) item.getData(OWNING_ME);
+					if (ele.getParent().getSelectedElement() == ele) {
+						Control ctrl = (Control) ele.getWidget();
+						if (ctrl != null) {
+							ctrl.setFocus();
+						}
+					}
+				}
+			}
+
+			@Override
+			public void mouseUp(MouseEvent e) {
+				CTabItem item = ctf.getItem(new Point(e.x, e.y));
+
+				// If the user middle clicks on a tab, close it
+				if (item != null && e.button == 2) {
+					closePart(item, false);
+				}
+
+				// If the user clicks on the tab or empty stack space, call
+				// setFocus()
+				if (e.button == 1) {
+					if (item == null) {
+						Rectangle clientArea = ctf.getClientArea();
+						if (!clientArea.contains(e.x, e.y)) {
+							// User clicked in empty space
+							item = ctf.getSelection();
+						}
+					}
+
+					if (item != null) {
+						MUIElement ele = (MUIElement) item.getData(OWNING_ME);
+						if (ele.getParent().getSelectedElement() == ele) {
+							Control ctrl = (Control) ele.getWidget();
+							if (ctrl != null) {
+								ctrl.setFocus();
+							}
+						}
+					}
+				}
+			}
+		};
+		ctf.addMouseListener(mouseListener);
+
+		CTabFolder2Adapter closeListener = new CTabFolder2Adapter() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void close(CTabFolderEvent event) {
+				event.doit = closePart(event.item, true);
+			}
+
+			@Override
+			public void showList(CTabFolderEvent event) {
+				event.doit = false;
+				showAvailableItems(stack, ctf);
+			}
+		};
+		ctf.addCTabFolder2Listener(closeListener);
+
+		ctf.addMenuDetectListener(new MenuDetectListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void menuDetected(MenuDetectEvent e) {
+				Point absolutePoint = new Point(e.x, e.y);
+				Point relativePoint = ctf.getDisplay().map(null, ctf,
+						absolutePoint);
+				CTabItem eventTabItem = ctf.getItem(relativePoint);
+
+				// If click happened in empty area, still show the menu
+				if (eventTabItem == null) {
+					Rectangle clientArea = ctf.getClientArea();
+					if (!clientArea.contains(relativePoint)) {
+						eventTabItem = ctf.getSelection();
+					}
+				}
+
+				if (eventTabItem != null) {
+					MUIElement uiElement = (MUIElement) eventTabItem
+							.getData(AbstractPartRenderer.OWNING_ME);
+					MPart tabPart = (MPart) ((uiElement instanceof MPart) ? uiElement
+							: ((MPlaceholder) uiElement).getRef());
+					openMenuFor(tabPart, ctf, absolutePoint);
+				}
+			}
+		});
+
+		ctf.addControlListener(new ControlAdapter() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void controlResized(ControlEvent e) {
+				updateMRUValue(ctf);
+			}
+		});
+	}
+
+	public void showAvailableItems(MElementContainer<?> stack, CTabFolder ctf) {
+		IEclipseContext ctxt = getContext(stack);
+		final BasicPartList editorList = new BasicPartList(ctf.getShell(),
+				SWT.ON_TOP, SWT.V_SCROLL | SWT.H_SCROLL,
+				ctxt.get(EPartService.class), stack, this,
+ getMRUValueFromPreferences());
+		editorList.setInput();
+
+		Point size = editorList.computeSizeHint();
+		editorList.setSize(size.x, size.y);
+
+		Point location = ctf.toDisplay(getChevronLocation(ctf));
+		Monitor mon = ctf.getMonitor();
+		Rectangle bounds = mon.getClientArea();
+		if (location.x + size.x > bounds.x + bounds.width) {
+			location.x = bounds.x + bounds.width - size.x;
+		}
+		if (location.y + size.y > bounds.y + bounds.height) {
+			location.y = bounds.y + bounds.height - size.y;
+		}
+		editorList.setLocation(location);
+
+		editorList.setVisible(true);
+		editorList.setFocus();
+		editorList.getShell().addListener(SWT.Deactivate, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(org.eclipse.swt.widgets.Event event) {
+				editorList.getShell().getDisplay().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						editorList.dispose();
+					}
+				});
+			}
+		});
+	}
+
+	private Point getChevronLocation(CTabFolder tabFolder) {
+		// get the last visible item
+		int numItems = tabFolder.getItemCount();
+		CTabItem item = null;
+		for (int i = 0; i < numItems; i++) {
+			CTabItem tempItem = tabFolder.getItem(i);
+			if (tempItem.isShowing()) {
+				item = tempItem;
+			}
+		}
+
+		// if we have no visible tabs, abort.
+		if (item == null) {
+			return new Point(0, 0);
+		}
+
+		Rectangle itemBounds = item.getBounds();
+		int x = itemBounds.x + itemBounds.width;
+		int y = itemBounds.y + itemBounds.height;
+		return new Point(x, y);
+	}
+
+	/**
+	 * Closes the part that's backed by the given widget.
+	 *
+	 * @param widget
+	 *            the part that owns this widget
+	 * @param check
+	 *            <tt>true</tt> if the part should be checked to see if it has
+	 *            been defined as being not closeable for users, <tt>false</tt>
+	 *            if this check should not be performed
+	 * @return <tt>true</tt> if the part was closed, <tt>false</tt> otherwise
+	 */
+	private boolean closePart(Widget widget, boolean check) {
+		MUIElement uiElement = (MUIElement) widget
+				.getData(AbstractPartRenderer.OWNING_ME);
+		MPart part = (MPart) ((uiElement instanceof MPart) ? uiElement
+				: ((MPlaceholder) uiElement).getRef());
+		if (!check && !isClosable(part)) {
+			return false;
+		}
+
+		IEclipseContext partContext = part.getContext();
+		IEclipseContext parentContext = getContextForParent(part);
+		// a part may not have a context if it hasn't been rendered
+		IEclipseContext context = partContext == null ? parentContext
+				: partContext;
+		// Allow closes to be 'canceled'
+		EPartService partService = (EPartService) context
+				.get(EPartService.class.getName());
+		if (partService.savePart(part, true)) {
+			partService.hidePart(part);
+			return true;
+		}
+		// the user has canceled out of the save operation, so don't close the
+		// part
+		return false;
+	}
+
+	@Override
+	protected void showTab(MUIElement element) {
+		super.showTab(element);
+
+		// an invisible element won't have the correct widget hierarchy
+		if (!element.isVisible()) {
+			return;
+		}
+
+		final CTabFolder ctf = (CTabFolder) getParentWidget(element);
+		CTabItem cti = findItemForPart(element, null);
+		if (cti == null) {
+			createTab(element.getParent(), element);
+			cti = findItemForPart(element, element.getParent());
+		}
+		Control ctrl = (Control) element.getWidget();
+		if (ctrl != null && ctrl.getParent() != ctf) {
+			ctrl.setParent(ctf);
+			cti.setControl(ctrl);
+		} else if (element.getWidget() == null) {
+			Control tabCtrl = (Control) renderer.createGui(element);
+			cti.setControl(tabCtrl);
+		}
+
+		ignoreTabSelChanges = true;
+		// Ensure that the newly selected control is correctly sized
+		if (cti.getControl() instanceof Composite) {
+			Composite ctiComp = (Composite) cti.getControl();
+			// see bug 461573: call below is still needed to make view
+			// descriptions visible after unhiding the view with changed bounds
+			ctiComp.layout(false, true);
+		}
+		ctf.setSelection(cti);
+		ignoreTabSelChanges = false;
+
+		// Show the new state
+		adjustTopRight(ctf);
+	}
+
+	/**
+	 * @param item
+	 */
+	protected void showMenu(ToolItem item) {
+		MPart part = (MPart) item.getData(THE_PART_KEY);
+		if (part == null) {
+			return;
+		}
+		Control ctrl = (Control) part.getWidget();
+		MMenu menuModel = getViewMenu(part);
+		if (menuModel == null || !menuModel.isToBeRendered())
+			return;
+
+		final Menu swtMenu = (Menu) renderer.createGui(menuModel,
+				ctrl.getShell(), part.getContext());
+		if (swtMenu == null)
+			return;
+
+		ctrl.addDisposeListener(new DisposeListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				if (!swtMenu.isDisposed()) {
+					swtMenu.dispose();
+				}
+			}
+		});
+
+		// ...and Show it...
+		Rectangle ib = item.getBounds();
+		Point displayAt = item.getParent().toDisplay(ib.x, ib.y + ib.height);
+		swtMenu.setLocation(displayAt);
+		swtMenu.setVisible(true);
+
+		Display display = swtMenu.getDisplay();
+		while (!swtMenu.isDisposed() && swtMenu.isVisible()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+		if (!swtMenu.isDisposed()
+				&& !(swtMenu.getData() instanceof MenuManager)) {
+			swtMenu.dispose();
+		}
+	}
+
+	private Image getViewMenuImage() {
+		// FIXME RAP can not draw on GC
+		if (viewMenuImage == null) {
+			viewMenuImage = new Image(Display.getCurrent(),
+					getClass().getClassLoader().getResourceAsStream("/icons/viewMenu.png")); //$NON-NLS-1$
+		}
+		return viewMenuImage;
+
+	}
+
+	private void openMenuFor(MPart part, CTabFolder folder, Point point) {
+		Menu tabMenu = createTabMenu(folder, part);
+		tabMenu.setData(STACK_SELECTED_PART, part);
+		tabMenu.setLocation(point.x, point.y);
+		tabMenu.setVisible(true);
+	}
+
+	protected boolean isClosable(MPart part) {
+		// if it's a shared part check its current ref
+		if (part.getCurSharedRef() != null) {
+			return !(part.getCurSharedRef().getTags()
+					.contains(IPresentationEngine.NO_CLOSE));
+		}
+
+		return part.isCloseable();
+	}
+
+	private Menu createTabMenu(CTabFolder folder, MPart part) {
+		Shell shell = folder.getShell();
+		Menu cachedMenu = (Menu) shell.getData(SHELL_CLOSE_EDITORS_MENU);
+		if (cachedMenu == null) {
+			cachedMenu = new Menu(folder);
+			shell.setData(SHELL_CLOSE_EDITORS_MENU, cachedMenu);
+		} else {
+			for (MenuItem item : cachedMenu.getItems()) {
+				item.dispose();
+			}
+		}
+
+		final Menu menu = cachedMenu;
+		populateTabMenu(menu, part);
+		return menu;
+	}
+
+	/**
+	 * Populate the tab's context menu for the given part.
+	 *
+	 * @param menu
+	 *            the menu to be populated
+	 * @param part
+	 *            the relevant part
+	 */
+	protected void populateTabMenu(final Menu menu, MPart part) {
+		int closeableElements = 0;
+		if (isClosable(part)) {
+			MenuItem menuItemClose = new MenuItem(menu, SWT.NONE);
+			menuItemClose.setText(SWTRenderersMessages.menuClose);
+			menuItemClose.addSelectionListener(new SelectionAdapter() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
+					EPartService partService = getContextForParent(part).get(
+							EPartService.class);
+					if (partService.savePart(part, true))
+						partService.hidePart(part);
+
+				}
+			});
+			closeableElements++;
+		}
+
+		MElementContainer<MUIElement> parent = getParent(part);
+		if (parent != null) {
+			closeableElements += getCloseableSiblingParts(part).size();
+
+			if (closeableElements >= 2) {
+				MenuItem menuItemOthers = new MenuItem(menu, SWT.NONE);
+				menuItemOthers.setText(SWTRenderersMessages.menuCloseOthers);
+				menuItemOthers.addSelectionListener(new SelectionAdapter() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
+						closeSiblingParts(part, true);
+					}
+				});
+
+				int leftFrom = getCloseableSideParts(part, true).size();
+				if (leftFrom > 0) {
+					MenuItem menuItemLeft = new MenuItem(menu, SWT.NONE);
+					menuItemLeft.setText(SWTRenderersMessages.menuCloseLeft);
+					menuItemLeft.addSelectionListener(new SelectionAdapter() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetSelected(SelectionEvent e) {
+							MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
+							closeSideParts(part, true);
+						}
+					});
+				}
+
+				int rightFrom = getCloseableSideParts(part, false).size();
+				if (rightFrom > 0) {
+					MenuItem menuItemRight = new MenuItem(menu, SWT.NONE);
+					menuItemRight.setText(SWTRenderersMessages.menuCloseRight);
+					menuItemRight.addSelectionListener(new SelectionAdapter() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetSelected(SelectionEvent e) {
+							MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
+							closeSideParts(part, false);
+						}
+					});
+				}
+
+				new MenuItem(menu, SWT.SEPARATOR);
+
+				MenuItem menuItemAll = new MenuItem(menu, SWT.NONE);
+				menuItemAll.setText(SWTRenderersMessages.menuCloseAll);
+				menuItemAll.addSelectionListener(new SelectionAdapter() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						MPart part = (MPart) menu.getData(STACK_SELECTED_PART);
+						closeSiblingParts(part, false);
+					}
+				});
+			}
+		}
+	}
+
+	private MElementContainer<MUIElement> getParent(MPart part) {
+		MElementContainer<MUIElement> parent = part.getParent();
+		if (parent == null) {
+			MPlaceholder placeholder = part.getCurSharedRef();
+			return placeholder == null ? null : placeholder.getParent();
+		}
+		return parent;
+	}
+
+	private List<MPart> getCloseableSideParts(MPart part, boolean left) {
+		MElementContainer<MUIElement> container = getParent(part);
+		if (container == null) {
+			return new ArrayList<MPart>();
+		}
+
+		int thisPartIdx = getPartIndex(part, container);
+		if (thisPartIdx == -1) {
+			return new ArrayList<MPart>();
+		}
+		List<MUIElement> children = container.getChildren();
+		final int start = left ? 0 : thisPartIdx + 1;
+		final int end = left ? thisPartIdx : children.size();
+
+		return getCloseableSiblingParts(part, children, start, end);
+	}
+
+	private int getPartIndex(MPart part, MElementContainer<MUIElement> container) {
+		List<MUIElement> children = container.getChildren();
+		for (int i = 0; i < children.size(); i++) {
+			MUIElement child = children.get(i);
+			MPart otherPart = null;
+			if (child instanceof MPart) {
+				otherPart = (MPart) child;
+			} else if (child instanceof MPlaceholder) {
+				MUIElement otherItem = ((MPlaceholder) child).getRef();
+				if (otherItem instanceof MPart) {
+					otherPart = (MPart) otherItem;
+				}
+			}
+			if (otherPart == part) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	private List<MPart> getCloseableSiblingParts(MPart part) {
+		MElementContainer<MUIElement> container = getParent(part);
+		if (container == null) {
+			return new ArrayList<MPart>();
+		}
+
+		List<MUIElement> children = container.getChildren();
+		return getCloseableSiblingParts(part, children, 0, children.size());
+	}
+
+	private List<MPart> getCloseableSiblingParts(MPart part, List<MUIElement> children, final int start,
+			final int end) {
+		// broken out from closeSiblingParts so it can be used to determine how
+		// many closeable siblings are available
+		List<MPart> closeableSiblings = new ArrayList<MPart>();
+		for (int i = start; i < end; i++) {
+			MUIElement child = children.get(i);
+			// If the element isn't showing skip it
+			if (!child.isToBeRendered())
+				continue;
+
+			MPart otherPart = null;
+			if (child instanceof MPart)
+				otherPart = (MPart) child;
+			else if (child instanceof MPlaceholder) {
+				MUIElement otherItem = ((MPlaceholder) child).getRef();
+				if (otherItem instanceof MPart)
+					otherPart = (MPart) otherItem;
+			}
+			if (otherPart == null)
+				continue;
+
+			if (part.equals(otherPart))
+				continue; // skip selected item
+			if (otherPart.isToBeRendered() && isClosable(otherPart))
+				closeableSiblings.add(otherPart);
+		}
+		return closeableSiblings;
+	}
+
+	private void closeSideParts(MPart part, boolean left) {
+		MElementContainer<MUIElement> container = getParent(part);
+		if (container == null) {
+			return;
+		}
+		List<MPart> others = getCloseableSideParts(part, left);
+		closeSiblingParts(part, others, true);
+	}
+
+	private void closeSiblingParts(MPart part, boolean skipThisPart) {
+		MElementContainer<MUIElement> container = getParent(part);
+		if (container == null) {
+			return;
+		}
+		List<MPart> others = getCloseableSiblingParts(part);
+		closeSiblingParts(part, others, skipThisPart);
+	}
+
+	private void closeSiblingParts(MPart part, List<MPart> others, boolean skipThisPart) {
+		MElementContainer<MUIElement> container = getParent(part);
+
+		// add the current part last so that we unrender obscured items first
+		if (!skipThisPart && part.isToBeRendered() && isClosable(part)) {
+			others.add(part);
+		}
+
+		// add the selected element of the stack at the end, else we may end up
+		// selecting another part when we hide it since it is the selected
+		// element
+		MUIElement selectedElement = container.getSelectedElement();
+		if (others.remove(selectedElement)) {
+			others.add((MPart) selectedElement);
+		} else if (selectedElement instanceof MPlaceholder) {
+			selectedElement = ((MPlaceholder) selectedElement).getRef();
+			if (others.remove(selectedElement)) {
+				others.add((MPart) selectedElement);
+			}
+		}
+
+		EPartService partService = getContextForParent(part).get(
+				EPartService.class);
+		// try using the ISaveHandler first... This gives better control of
+		// dialogs...
+		ISaveHandler saveHandler = getContextForParent(part).get(
+				ISaveHandler.class);
+		if (saveHandler != null) {
+			final List<MPart> toPrompt = new ArrayList<MPart>(others);
+			toPrompt.retainAll(partService.getDirtyParts());
+
+			boolean cancel = false;
+			if (toPrompt.size() > 1) {
+				cancel = !saveHandler.saveParts(toPrompt, true);
+			} else if (toPrompt.size() == 1) {
+				cancel = !saveHandler.save(toPrompt.get(0), true);
+			}
+			if (cancel) {
+				return;
+			}
+
+			for (MPart other : others) {
+				partService.hidePart(other);
+			}
+			return;
+		}
+
+		// No ISaveHandler, fall back to just using the part service...
+		for (MPart otherPart : others) {
+			if (partService.savePart(otherPart, true))
+				partService.hidePart(otherPart);
+		}
+	}
+
+	public static MMenu getViewMenu(MPart part) {
+		if (part == null || part.getMenus() == null) {
+			return null;
+		}
+		for (MMenu menu : part.getMenus()) {
+			if (menu.getTags().contains(TAG_VIEW_MENU)) {
+				return menu;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Determine whether the given view menu has any visible menu items.
+	 *
+	 * @param viewMenu
+	 *            the view menu to check
+	 * @param part
+	 *            the view menu's parent part
+	 * @return <tt>true</tt> if the specified view menu has visible children,
+	 *         <tt>false</tt> otherwise
+	 */
+	private boolean hasVisibleMenuItems(MMenu viewMenu, MPart part) {
+		if (!viewMenu.isToBeRendered() || !viewMenu.isVisible()) {
+			return false;
+		}
+
+		for (MMenuElement menuElement : viewMenu.getChildren()) {
+			if (menuElement.isToBeRendered() && menuElement.isVisible()) {
+				if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)
+						|| OpaqueElementUtil.isOpaqueMenuSeparator(menuElement)) {
+					IContributionItem item = (IContributionItem) OpaqueElementUtil
+							.getOpaqueItem(menuElement);
+					if (item != null && item.isVisible()) {
+						return true;
+					}
+				} else {
+					return true;
+				}
+			}
+		}
+
+		Object menuRenderer = viewMenu.getRenderer();
+		if (menuRenderer instanceof MenuManagerRenderer) {
+			MenuManager manager = ((MenuManagerRenderer) menuRenderer)
+					.getManager(viewMenu);
+			if (manager != null && manager.isVisible()) {
+				return true;
+			}
+		}
+
+		Control control = (Control) part.getWidget();
+		if (control != null) {
+			Menu menu = (Menu) renderer.createGui(viewMenu, control.getShell(),
+					part.getContext());
+			if (menu != null) {
+				menuRenderer = viewMenu.getRenderer();
+				if (menuRenderer instanceof MenuManagerRenderer) {
+					MenuManagerRenderer menuManagerRenderer = (MenuManagerRenderer) menuRenderer;
+					MenuManager manager = menuManagerRenderer
+							.getManager(viewMenu);
+					if (manager != null) {
+						// remark ourselves as dirty so that the menu will be
+						// reconstructed
+						manager.markDirty();
+					}
+				}
+				return menu.getItemCount() != 0;
+			}
+		}
+		return false;
+	}
+
+	// @SuppressWarnings("javadoc")
+	// public class TabStateHandler implements EventHandler {
+	// @Override
+	// public void handleEvent(Event event) {
+	// Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
+	// Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);
+	// Object oldValue = event.getProperty(UIEvents.EventTags.OLD_VALUE);
+	//
+	// if (!validateElement(element)
+	// || !validateValues(oldValue, newValue)) {
+	// return;
+	// }
+	//
+	// MPart part = newValue instanceof MPlaceholder ? (MPart) ((MPlaceholder)
+	// newValue)
+	// .getRef() : (MPart) element;
+	// CTabItem cti = findItemForPart(part);
+	//
+	// if (cti == null) {
+	// return;
+	// }
+	//
+	// if (CSSConstants.CSS_CONTENT_CHANGE_CLASS.equals(newValue)) {
+	// part.getTags().remove(CSSConstants.CSS_CONTENT_CHANGE_CLASS);
+	// if (cti != cti.getParent().getSelection()) {
+	// part.getTags().add(CSSConstants.CSS_HIGHLIGHTED_CLASS);
+	// }
+	// } else if (newValue instanceof MPlaceholder // part gets active
+	// && part.getTags().contains(
+	// CSSConstants.CSS_HIGHLIGHTED_CLASS)) {
+	// part.getTags().remove(CSSConstants.CSS_HIGHLIGHTED_CLASS);
+	// }
+	//
+	// String prevCssCls = WidgetElement.getCSSClass(cti);
+	// setCSSInfo(part, cti);
+	//
+	// if (prevCssCls == null ||
+	// !prevCssCls.equals(WidgetElement.getCSSClass(cti))) {
+	// reapplyStyles(cti.getParent());
+	// }
+	// }
+	//
+	// public boolean validateElement(Object element) {
+	// return element instanceof MPart || element instanceof MPartStack;
+	// }
+	//
+	// public boolean validateValues(Object oldValue, Object newValue) {
+	// return newValue instanceof MPlaceholder // part gets active
+	// || isTagAdded(CSSConstants.CSS_BUSY_CLASS, oldValue,
+	// newValue) // part gets busy
+	// || isTagRemoved(CSSConstants.CSS_BUSY_CLASS, oldValue,
+	// newValue) // part gets idle
+	// || isTagAdded(CSSConstants.CSS_CONTENT_CHANGE_CLASS,
+	// oldValue, newValue); // content of part changed
+	// }
+	//
+	// private boolean isTagAdded(String tagName, Object oldValue,
+	// Object newValue) {
+	// return oldValue == null && tagName.equals(newValue);
+	// }
+	//
+	// private boolean isTagRemoved(String tagName, Object oldValue,
+	// Object newValue) {
+	// return newValue == null && tagName.equals(oldValue);
+	// }
+	// }
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarContributionRecord.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarContributionRecord.java
new file mode 100644
index 0000000..72b7c37
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarContributionRecord.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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
+ *     Maxime Porhel <maxime.porhel@obeo.fr> Obeo - Bug 410426
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.action.ToolBarManager;
+
+public class ToolBarContributionRecord {
+	public static final String FACTORY = "ToolBarContributionFactory"; //$NON-NLS-1$
+	static final String STATIC_CONTEXT = "ToolBarContributionFactoryContext"; //$NON-NLS-1$
+
+	MToolBar toolbarModel;
+	MToolBarContribution toolbarContribution;
+	ArrayList<MToolBarElement> generatedElements = new ArrayList<MToolBarElement>();
+	HashSet<MToolBarElement> sharedElements = new HashSet<MToolBarElement>();
+	ToolBarManagerRenderer renderer;
+	boolean isVisible = true;
+	private IEclipseContext infoContext;
+	private Runnable factoryDispose;
+
+	public ToolBarContributionRecord(MToolBar model,
+			MToolBarContribution contribution, ToolBarManagerRenderer renderer) {
+		this.toolbarModel = model;
+		this.toolbarContribution = contribution;
+		this.renderer = renderer;
+	}
+
+	public ToolBarManager getManagerForModel() {
+		return renderer.getManager(toolbarModel);
+	}
+
+	/**
+	 * @param context
+	 */
+	public void updateVisibility(IEclipseContext context) {
+		ExpressionContext exprContext = new ExpressionContext(context);
+		updateIsVisible(exprContext);
+		HashSet<ToolBarContributionRecord> recentlyUpdated = new HashSet<ToolBarContributionRecord>();
+		recentlyUpdated.add(this);
+		boolean changed = false;
+		for (MToolBarElement item : generatedElements) {
+			boolean currentVisibility = computeVisibility(recentlyUpdated,
+					item, exprContext);
+			if (item.isVisible() != currentVisibility) {
+				item.setVisible(currentVisibility);
+				changed = true;
+			}
+		}
+		for (MToolBarElement item : sharedElements) {
+			boolean currentVisibility = computeVisibility(recentlyUpdated,
+					item, exprContext);
+			if (item.isVisible() != currentVisibility) {
+				item.setVisible(currentVisibility);
+				changed = true;
+			}
+		}
+
+		if (changed) {
+			getManagerForModel().markDirty();
+		}
+	}
+
+	public void updateIsVisible(ExpressionContext exprContext) {
+		isVisible = ContributionsAnalyzer.isVisible(toolbarContribution,
+				exprContext);
+	}
+
+	public boolean computeVisibility(
+			HashSet<ToolBarContributionRecord> recentlyUpdated,
+			MToolBarElement item, ExpressionContext exprContext) {
+		boolean currentVisibility = isVisible;
+		if (item instanceof MToolBarSeparator) {
+			ArrayList<ToolBarContributionRecord> list = renderer.getList(item);
+			if (list != null) {
+				Iterator<ToolBarContributionRecord> cr = list.iterator();
+				while (!currentVisibility && cr.hasNext()) {
+					ToolBarContributionRecord rec = cr.next();
+					if (!recentlyUpdated.contains(rec)) {
+						rec.updateIsVisible(exprContext);
+						recentlyUpdated.add(rec);
+					}
+					currentVisibility |= rec.isVisible;
+				}
+			}
+		}
+		if (currentVisibility
+				&& item.getPersistedState().get(
+						MenuManagerRenderer.VISIBILITY_IDENTIFIER) != null) {
+			String identifier = item.getPersistedState().get(
+					MenuManagerRenderer.VISIBILITY_IDENTIFIER);
+			Object rc = exprContext.eclipseContext.get(identifier);
+			if (rc instanceof Boolean) {
+				currentVisibility = ((Boolean) rc).booleanValue();
+			}
+		}
+		if (currentVisibility
+				&& item.getVisibleWhen() instanceof MCoreExpression) {
+			boolean val = ContributionsAnalyzer.isVisible(
+					(MCoreExpression) item.getVisibleWhen(), exprContext);
+			currentVisibility = val;
+		}
+		return currentVisibility;
+	}
+
+	public void collectInfo(ExpressionInfo info) {
+		ContributionsAnalyzer.collectInfo(info,
+				toolbarContribution.getVisibleWhen());
+		for (MToolBarElement item : generatedElements) {
+			ContributionsAnalyzer.collectInfo(info, item.getVisibleWhen());
+		}
+		for (MToolBarElement item : sharedElements) {
+			ContributionsAnalyzer.collectInfo(info, item.getVisibleWhen());
+		}
+	}
+
+	public boolean anyVisibleWhen() {
+		if (toolbarContribution.getVisibleWhen() != null) {
+			return true;
+		}
+
+		List<MToolBarElement> childrenToInspect;
+		if (toolbarContribution.getTransientData().get(FACTORY) != null) {
+			// See mergeIntoModel
+			childrenToInspect = this.generatedElements;
+		} else {
+			childrenToInspect = toolbarContribution.getChildren();
+		}
+
+		for (MToolBarElement child : childrenToInspect) {
+			if (child.getVisibleWhen() != null
+					|| child.getPersistedState().get(
+							MenuManagerRenderer.VISIBILITY_IDENTIFIER) != null) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public boolean mergeIntoModel() {
+		int idx = getIndex(toolbarModel,
+				toolbarContribution.getPositionInParent());
+		if (idx == -1) {
+			return false;
+		}
+
+		final List<MToolBarElement> copyElements;
+		if (toolbarContribution.getTransientData().get(FACTORY) != null) {
+			copyElements = mergeFactoryIntoModel();
+		} else {
+			copyElements = new ArrayList<MToolBarElement>();
+			for (MToolBarElement item : toolbarContribution.getChildren()) {
+				MToolBarElement copy = (MToolBarElement) EcoreUtil
+						.copy((EObject) item);
+				copyElements.add(copy);
+			}
+		}
+		for (MToolBarElement copy : copyElements) {
+			// if a visibleWhen clause is defined, the item should not be
+			// visible until the clause has been evaluated and returned 'true'
+			copy.setVisible(!anyVisibleWhen());
+			if (copy instanceof MToolBarSeparator) {
+				MToolBarSeparator shared = findExistingSeparator(copy
+						.getElementId());
+				if (shared == null) {
+					shared = (MToolBarSeparator) copy;
+					renderer.linkElementToContributionRecord(copy, this);
+					toolbarModel.getChildren().add(idx++, copy);
+				} else {
+					copy = shared;
+				}
+				sharedElements.add(shared);
+			} else {
+				generatedElements.add(copy);
+				renderer.linkElementToContributionRecord(copy, this);
+				toolbarModel.getChildren().add(idx++, copy);
+			}
+			if (copy instanceof MToolBarSeparator) {
+				ArrayList<ToolBarContributionRecord> array = renderer
+						.getList(copy);
+				array.add(this);
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * @return
+	 */
+	private List<MToolBarElement> mergeFactoryIntoModel() {
+		Object obj = toolbarContribution.getTransientData().get(FACTORY);
+		if (!(obj instanceof IContextFunction)) {
+			return Collections.EMPTY_LIST;
+		}
+		IEclipseContext staticContext = getStaticContext();
+		staticContext.remove(List.class);
+		factoryDispose = (Runnable) ((IContextFunction) obj).compute(
+				staticContext, null);
+		return staticContext.get(List.class);
+	}
+
+	private IEclipseContext getStaticContext() {
+		if (infoContext == null) {
+			IEclipseContext parentContext = renderer.getContext(toolbarModel);
+			if (parentContext != null) {
+				infoContext = parentContext.createChild(STATIC_CONTEXT);
+			} else {
+				infoContext = EclipseContextFactory.create(STATIC_CONTEXT);
+			}
+			ContributionsAnalyzer.populateModelInterfaces(toolbarModel,
+					infoContext, toolbarModel.getClass().getInterfaces());
+			infoContext.set(ToolBarManagerRenderer.class, renderer);
+		}
+		return infoContext;
+	}
+
+	MToolBarSeparator findExistingSeparator(String id) {
+		if (id == null) {
+			return null;
+		}
+		for (MToolBarElement item : toolbarModel.getChildren()) {
+			if (item instanceof MToolBarSeparator
+					&& id.equals(item.getElementId())) {
+				return (MToolBarSeparator) item;
+			}
+		}
+		return null;
+	}
+
+	public void dispose() {
+		for (MToolBarElement copy : generatedElements) {
+			toolbarModel.getChildren().remove(copy);
+		}
+		for (MToolBarElement shared : sharedElements) {
+			ArrayList<ToolBarContributionRecord> array = renderer
+					.getList(shared);
+			array.remove(this);
+			if (array.isEmpty()) {
+				toolbarModel.getChildren().remove(shared);
+			}
+		}
+		if (factoryDispose != null) {
+			factoryDispose.run();
+			factoryDispose = null;
+		}
+	}
+
+	private static int getIndex(MElementContainer<?> model,
+			String positionInParent) {
+		String id = null;
+		String modifier = null;
+		if (positionInParent != null && positionInParent.length() > 0) {
+			String[] array = positionInParent.split("="); //$NON-NLS-1$
+			modifier = array[0];
+			id = array[1];
+		}
+		if (id == null) {
+			return model.getChildren().size();
+		}
+
+		int idx = 0;
+		int size = model.getChildren().size();
+		while (idx < size) {
+			if (id.equals(model.getChildren().get(idx).getElementId())) {
+				if ("after".equals(modifier)) { //$NON-NLS-1$
+					idx++;
+				} else if ("endof".equals(modifier)) { //$NON-NLS-1$
+					// Skip current menu item
+					idx++;
+
+					// Skip all menu items until next MenuSeparator is found
+					while (idx < size
+							&& !(model.getChildren().get(idx) instanceof MToolBarSeparator && model
+									.getChildren().get(idx).getElementId() != null)) {
+						idx++;
+					}
+				}
+				return idx;
+			}
+			idx++;
+		}
+		return id.equals("additions") ? model.getChildren().size() : -1; //$NON-NLS-1$
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarManagerRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarManagerRenderer.java
new file mode 100644
index 0000000..7aaacc0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarManagerRenderer.java
@@ -0,0 +1,981 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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
+ *     Maxime Porhel <maxime.porhel@obeo.fr> Obeo - Bug 410426
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 426535, 433234, 431868
+ *     Maxime Porhel <maxime.porhel@obeo.fr> Obeo - Bug 431778
+ *     Andrey Loskutov <loskutov@gmx.de> - Bugs 383569, 457198
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 431990
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSRenderingUtils;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.Selector;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.ElementContainer;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.action.AbstractGroupMarker;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IContributionManagerOverrides;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+
+/**
+ * Create a contribute part.
+ */
+public class ToolBarManagerRenderer extends SWTPartRenderer {
+
+	private static final Selector ALL_SELECTOR = new Selector() {
+
+		@Override
+		public boolean select(MApplicationElement element) {
+			return true;
+		}
+	};
+
+	/**	 */
+	public static final String POST_PROCESSING_FUNCTION = "ToolBarManagerRenderer.postProcess.func"; //$NON-NLS-1$
+	/**	 */
+	public static final String POST_PROCESSING_DISPOSE = "ToolBarManagerRenderer.postProcess.dispose"; //$NON-NLS-1$
+	/**	 */
+	public static final String UPDATE_VARS = "ToolBarManagerRenderer.updateVars"; //$NON-NLS-1$
+	private static final String DISPOSE_ADDED = "ToolBarManagerRenderer.disposeAdded"; //$NON-NLS-1$
+
+	private Map<MToolBar, ToolBarManager> modelToManager = new HashMap<MToolBar, ToolBarManager>();
+	private Map<ToolBarManager, MToolBar> managerToModel = new HashMap<ToolBarManager, MToolBar>();
+
+	private Map<MToolBarElement, IContributionItem> modelToContribution = new HashMap<MToolBarElement, IContributionItem>();
+	private Map<IContributionItem, MToolBarElement> contributionToModel = new HashMap<IContributionItem, MToolBarElement>();
+
+	private Map<MToolBarElement, ToolBarContributionRecord> modelContributionToRecord = new HashMap<MToolBarElement, ToolBarContributionRecord>();
+
+	private Map<MToolBarElement, ArrayList<ToolBarContributionRecord>> sharedElementToRecord = new HashMap<MToolBarElement, ArrayList<ToolBarContributionRecord>>();
+
+	private ToolItemUpdater enablementUpdater = new ToolItemUpdater();
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	EModelService modelService;
+
+	@Inject
+	@Optional
+	private void subscribeTopicUpdateItems(@UIEventTopic(UIEvents.UILabel.TOPIC_ALL) Event event) {
+		// Ensure that this event is for a MToolBarElement
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBarElement)) {
+			return;
+		}
+
+		MToolBarElement itemModel = (MToolBarElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+
+		IContributionItem ici = getContribution(itemModel);
+		if (ici == null) {
+			return;
+		}
+
+		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
+		if (UIEvents.UILabel.LABEL.equals(attName) || UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+			ici.update();
+		} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+			ici.update();
+		} else if (UIEvents.UILabel.TOOLTIP.equals(attName) || UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
+			ici.update();
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicUpdateToBeRendered(@UIEventTopic(UIEvents.UIElement.TOPIC_ALL) Event event) {
+		// Ensure that this event is for a MMenuItem
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBarElement)) {
+			return;
+		}
+
+		MToolBarElement itemModel = (MToolBarElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
+		if (UIEvents.UIElement.TOBERENDERED.equals(attName)) {
+			Object obj = itemModel.getParent();
+			if (!(obj instanceof MToolBar)) {
+				return;
+			}
+			ToolBarManager parent = getManager((MToolBar) obj);
+			if (itemModel.isToBeRendered()) {
+				if (parent != null) {
+					modelProcessSwitch(parent, itemModel);
+					parent.update(true);
+					ToolBar tb = parent.getControl();
+					if (tb != null && !tb.isDisposed()) {
+						tb.pack(true);
+						tb.getShell().layout(new Control[] { tb }, SWT.DEFER);
+					}
+				}
+			} else {
+				IContributionItem ici = modelToContribution.remove(itemModel);
+				if (ici != null && parent != null) {
+					parent.remove(ici);
+				}
+				if (ici != null) {
+					ici.dispose();
+				}
+			}
+		} else if (UIEvents.UIElement.VISIBLE.equals(attName)) {
+			IContributionItem ici = getContribution(itemModel);
+			if (ici == null) {
+				return;
+			}
+
+			ToolBarManager parent = null;
+			if (ici instanceof MenuManager) {
+				parent = (ToolBarManager) ((MenuManager) ici).getParent();
+			} else if (ici instanceof ContributionItem) {
+				parent = (ToolBarManager) ((ContributionItem) ici).getParent();
+			}
+
+			if (parent == null) {
+				ici.setVisible(itemModel.isVisible());
+				return;
+			}
+
+			IContributionManagerOverrides ov = parent.getOverrides();
+			// partial fix for bug 383569: only change state if there are no
+			// extra override mechanics controlling element visibility
+			if (ov == null) {
+				ici.setVisible(itemModel.isVisible());
+			} else {
+				Boolean visible = ov.getVisible(ici);
+				if (visible == null) {
+					// same as above: only change state if there are no extra
+					// override mechanics controlling element visibility
+					ici.setVisible(itemModel.isVisible());
+				}
+			}
+
+			parent.markDirty();
+			parent.update(true);
+			ToolBar tb = parent.getControl();
+			if (tb != null && !tb.isDisposed()) {
+				tb.pack(true);
+				if (tb.getParent() != null) {
+					tb.getParent().pack(true);
+				}
+				tb.getShell().layout(new Control[] { tb }, SWT.DEFER);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicUpdateSelection(@UIEventTopic(UIEvents.Item.TOPIC_SELECTED) Event event) {
+		// Ensure that this event is for a MToolBarElement
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBarElement)) {
+			return;
+		}
+
+		MToolBarElement itemModel = (MToolBarElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			ici.update();
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicUpdateEnablement(@UIEventTopic(UIEvents.Item.TOPIC_ENABLED) Event event) {
+		// Ensure that this event is for a MMenuItem
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBarElement)) {
+			return;
+		}
+
+		MToolBarElement itemModel = (MToolBarElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			ici.update();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Inject
+	@Optional
+	private void subscribeTopicChildAdded(@UIEventTopic(ElementContainer.TOPIC_CHILDREN) Event event) {
+		// Ensure that this event is for a MMenuItem
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBar)) {
+			return;
+		}
+		MToolBar toolbarModel = (MToolBar) event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (UIEvents.isADD(event)) {
+			Object obj = toolbarModel;
+			processContents((MElementContainer<MUIElement>) obj);
+		}
+	}
+
+	private HashSet<String> updateVariables = new HashSet<String>();
+
+	@Inject
+	@Optional
+	private void subscribeTopicDirtyChanged(@UIEventTopic(UIEvents.Dirtyable.TOPIC_DIRTY) Event eventData) {
+		getUpdater().updateContributionItems(ALL_SELECTOR);
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicUpdateToolbarEnablement(
+			@UIEventTopic(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC) Event eventData) {
+		final Object v = eventData != null ? eventData.getProperty(IEventBroker.DATA) : UIEvents.ALL_ELEMENT_ID;
+		Selector s;
+		if (v instanceof Selector) {
+			s = (Selector) v;
+		} else {
+			if (v == null || UIEvents.ALL_ELEMENT_ID.equals(v)) {
+				s = ALL_SELECTOR;
+			} else {
+				s = new Selector() {
+					@Override
+					public boolean select(MApplicationElement element) {
+						return v.equals(element.getElementId());
+					}
+				};
+			}
+		}
+
+		getUpdater().updateContributionItems(s);
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
+
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MToolBar)) {
+			return;
+		}
+
+		final MUIElement changedElement = (MUIElement) changedObj;
+
+		if (UIEvents.isADD(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				changedElement.setVisible(false);
+				changedElement.setToBeRendered(false);
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				changedElement.setVisible(true);
+				changedElement.setToBeRendered(true);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicAppStartup(@UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Event event) {
+		List<MToolBar> toolBars = modelService.findElements(application, null, MToolBar.class, null);
+		for (MToolBar mToolBar : toolBars) {
+			if (mToolBar.getTags().contains(IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				mToolBar.setVisible(false);
+				mToolBar.setToBeRendered(false);
+			}
+		}
+	}
+
+	/**
+	 *
+	 */
+	@PostConstruct
+	public void init() {
+		context.set(ToolBarManagerRenderer.class, this);
+
+		String[] vars = {
+				"org.eclipse.ui.internal.services.EvaluationService.evaluate", //$NON-NLS-1$
+				IServiceConstants.ACTIVE_CONTEXTS,
+				IServiceConstants.ACTIVE_PART,
+				IServiceConstants.ACTIVE_SELECTION,
+				IServiceConstants.ACTIVE_SHELL };
+		updateVariables.addAll(Arrays.asList(vars));
+		context.set(UPDATE_VARS, updateVariables);
+		RunAndTrack enablementUpdater = new RunAndTrack() {
+
+			@Override
+			public boolean changed(IEclipseContext context) {
+				for (String var : updateVariables) {
+					context.get(var);
+				}
+				getUpdater().updateContributionItems(ALL_SELECTOR);
+				return true;
+			}
+		};
+		context.runAndTrack(enablementUpdater);
+	}
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MToolBar) || !(parent instanceof Composite)) {
+			return null;
+		}
+
+		final MToolBar toolbarModel = (MToolBar) element;
+		ToolBar newTB = createToolbar(toolbarModel, (Composite) parent);
+		bindWidget(element, newTB);
+		processContribution(toolbarModel, toolbarModel.getElementId());
+
+		Control renderedCtrl = newTB;
+		MUIElement parentElement = element.getParent();
+		if (parentElement instanceof MTrimBar) {
+			element.getTags().add(IPresentationEngine.DRAGGABLE);
+
+			setCSSInfo(element, newTB);
+
+			boolean vertical = false;
+			MTrimBar bar = (MTrimBar) parentElement;
+			vertical = bar.getSide() == SideValue.LEFT || bar.getSide() == SideValue.RIGHT;
+			IEclipseContext parentContext = getContextForParent(element);
+			CSSRenderingUtils cssUtils = parentContext.get(CSSRenderingUtils.class);
+			if (cssUtils != null) {
+				renderedCtrl = cssUtils.frameMeIfPossible(newTB, null, vertical, true);
+			}
+		}
+
+		return renderedCtrl;
+	}
+
+	/**
+	 * @param toolbarModel
+	 * @param elementId
+	 */
+	public void processContribution(MToolBar toolbarModel, String elementId) {
+
+		ToolBarManager manager = getManager(toolbarModel);
+		if (manager != null && manager.getControl() != null) {
+			addCleanupDisposeListener(toolbarModel, manager.getControl());
+		}
+
+		final ArrayList<MToolBarContribution> toContribute = new ArrayList<MToolBarContribution>();
+		ContributionsAnalyzer.XXXgatherToolBarContributions(toolbarModel,
+				application.getToolBarContributions(), elementId, toContribute);
+		generateContributions(toolbarModel, toContribute);
+	}
+
+	private void addCleanupDisposeListener(final MToolBar toolbarModel, ToolBar control) {
+
+		final Map<String, Object> transientData = toolbarModel.getTransientData();
+		if (!transientData.containsKey(DISPOSE_ADDED)) {
+			transientData.put(DISPOSE_ADDED, Boolean.TRUE);
+			control.addDisposeListener(new DisposeListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					cleanUp(toolbarModel);
+					Object dispose = transientData.get(POST_PROCESSING_DISPOSE);
+					if (dispose instanceof Runnable) {
+						((Runnable) dispose).run();
+					}
+					transientData.remove(POST_PROCESSING_DISPOSE);
+					transientData.remove(DISPOSE_ADDED);
+				}
+			});
+		}
+
+	}
+
+	private void generateContributions(MToolBar toolbarModel, List<MToolBarContribution> toContribute) {
+
+		ToolBarManager manager = getManager(toolbarModel);
+		boolean done = toContribute.size() == 0;
+		while (!done) {
+			ArrayList<MToolBarContribution> curList = new ArrayList<MToolBarContribution>(toContribute);
+			int retryCount = toContribute.size();
+			toContribute.clear();
+
+			for (final MToolBarContribution contribution : curList) {
+				if (!processAddition(toolbarModel, manager, contribution)) {
+					toContribute.add(contribution);
+				}
+			}
+			// We're done if the retryList is now empty (everything done) or
+			// if the list hasn't changed at all (no hope)
+			done = toContribute.size() == 0 || toContribute.size() == retryCount;
+		}
+	}
+
+	/**
+	 * @return <code>true</code> if the contribution was successfully processed
+	 */
+	private boolean processAddition(final MToolBar toolbarModel, final ToolBarManager manager,
+			MToolBarContribution contribution) {
+		final ToolBarContributionRecord record = new ToolBarContributionRecord(toolbarModel, contribution, this);
+		if (!record.mergeIntoModel()) {
+			return false;
+		}
+		if (record.anyVisibleWhen()) {
+			ExpressionInfo info = new ExpressionInfo();
+			record.collectInfo(info);
+			updateVariables.addAll(Arrays.asList(info.getAccessedVariableNames()));
+			final IEclipseContext parentContext = getContext(toolbarModel);
+			parentContext.runAndTrack(new RunAndTrack() {
+				@Override
+				public boolean changed(IEclipseContext context) {
+					if (getManager(toolbarModel) == null) {
+						// tool bar no longer being managed, ignore it
+						return false;
+					}
+
+					record.updateVisibility(parentContext.getActiveLeaf());
+					runExternalCode(new Runnable() {
+
+						@Override
+						public void run() {
+							manager.update(false);
+							getUpdater().updateContributionItems(ALL_SELECTOR);
+						}
+					});
+					return true;
+				}
+			});
+		}
+
+		return true;
+	}
+
+	private ToolBar createToolbar(final MUIElement element, Composite parent) {
+		int orientation = getOrientation(element);
+		int style = orientation | SWT.WRAP | SWT.FLAT | SWT.RIGHT;
+		ToolBarManager manager = getManager((MToolBar) element);
+		if (manager == null) {
+			manager = new ToolBarManager(style);
+			IContributionManagerOverrides overrides = null;
+			MApplicationElement parentElement = element.getParent();
+			if (parentElement == null) {
+				parentElement = (MApplicationElement) ((EObject) element).eContainer();
+			}
+
+			if (parentElement != null) {
+				overrides = (IContributionManagerOverrides) parentElement.getTransientData()
+						.get(IContributionManagerOverrides.class.getName());
+			}
+
+			manager.setOverrides(overrides);
+			linkModelToManager((MToolBar) element, manager);
+		} else {
+			ToolBar toolBar = manager.getControl();
+			if (toolBar != null && !toolBar.isDisposed() && (toolBar.getStyle() & orientation) == 0) {
+				toolBar.dispose();
+			}
+			// FIXME RAP ToolbarManager.setStyle() not available
+			// manager.setStyle(style);
+		}
+		ToolBar bar = manager.createControl(parent);
+		bar.setData(manager);
+		bar.setData(AbstractPartRenderer.OWNING_ME, element);
+		bar.getShell().layout(new Control[] { bar }, SWT.DEFER);
+		return bar;
+	}
+
+	protected void cleanUp(MToolBar toolbarModel) {
+		Collection<ToolBarContributionRecord> vals = modelContributionToRecord.values();
+		for (ToolBarContributionRecord record : vals.toArray(new ToolBarContributionRecord[vals.size()])) {
+			if (record.toolbarModel == toolbarModel) {
+				record.dispose();
+				for (MToolBarElement copy : record.generatedElements) {
+					cleanUpCopy(record, copy);
+				}
+				for (MToolBarElement copy : record.sharedElements) {
+					cleanUpCopy(record, copy);
+				}
+				record.generatedElements.clear();
+				record.sharedElements.clear();
+			}
+		}
+	}
+
+	/**
+	 * @param record
+	 * @param copy
+	 */
+	public void cleanUpCopy(ToolBarContributionRecord record, MToolBarElement copy) {
+		modelContributionToRecord.remove(copy);
+		IContributionItem ici = getContribution(copy);
+		clearModelToContribution(copy, ici);
+		if (ici != null) {
+			record.getManagerForModel().remove(ici);
+		}
+	}
+
+	int getOrientation(final MUIElement element) {
+		MUIElement theParent = element.getParent();
+		if (theParent instanceof MTrimBar) {
+			MTrimBar trimContainer = (MTrimBar) theParent;
+			SideValue side = trimContainer.getSide();
+			if (side.getValue() == SideValue.LEFT_VALUE || side.getValue() == SideValue.RIGHT_VALUE) {
+				return SWT.VERTICAL;
+			}
+		}
+		return SWT.HORIZONTAL;
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		// I can either simply stop processing, or we can walk the model
+		// ourselves like the "old" days
+		// EMF gives us null lists if empty
+		if (container == null) {
+			return;
+		}
+
+		Object obj = container;
+		ToolBarManager parentManager = getManager((MToolBar) obj);
+		if (parentManager == null) {
+			return;
+		}
+		// Process any contents of the newly created ME
+		List<MUIElement> parts = container.getChildren();
+		if (parts != null) {
+			MUIElement[] plist = parts.toArray(new MUIElement[parts.size()]);
+			for (int i = 0; i < plist.length; i++) {
+				MUIElement childME = plist[i];
+				modelProcessSwitch(parentManager, (MToolBarElement) childME);
+			}
+		}
+		parentManager.update(true);
+
+		ToolBar tb = getToolbarFrom(container.getWidget());
+		if (tb != null) {
+			tb.pack(true);
+			tb.getShell().layout(new Control[] { tb }, SWT.DEFER);
+		}
+	}
+
+	private ToolBar getToolbarFrom(Object widget) {
+		if (widget instanceof ToolBar) {
+			return (ToolBar) widget;
+		}
+		if (widget instanceof Composite) {
+			Composite intermediate = (Composite) widget;
+			if (!intermediate.isDisposed()) {
+				Control[] children = intermediate.getChildren();
+				for (Control control : children) {
+					if (control.getData() instanceof ToolBarManager) {
+						return (ToolBar) control;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	boolean hasOnlySeparators(ToolBar toolbar) {
+		ToolItem[] children = toolbar.getItems();
+		for (ToolItem toolItem : children) {
+			if ((toolItem.getStyle() & SWT.SEPARATOR) == 0) {
+				return false;
+			} else if (toolItem.getControl() != null
+					&& toolItem.getControl().getData(OWNING_ME) instanceof MToolControl) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement, MUIElement child) {
+		super.hideChild(parentElement, child);
+		// only handle the disposal of this element if it was actually rendered
+		// by the engine
+		if (child.getRenderer() != null) {
+			// Since there's no place to 'store' a child that's not in a menu
+			// we'll blow it away and re-create on an add
+			Widget widget = (Widget) child.getWidget();
+			if (widget != null && !widget.isDisposed()) {
+				widget.dispose();
+			}
+			ToolBar toolbar = (ToolBar) getUIContainer(child);
+			if (toolbar != null && !toolbar.isDisposed()) {
+				toolbar.pack(true);
+				toolbar.getShell().layout(new Control[] { toolbar }, SWT.DEFER);
+			}
+		}
+	}
+
+	@Override
+	public void childRendered(MElementContainer<MUIElement> parentElement, MUIElement element) {
+		super.childRendered(parentElement, element);
+		processContents(parentElement);
+		ToolBar toolbar = (ToolBar) getUIContainer(element);
+		if (toolbar != null && !toolbar.isDisposed()) {
+			toolbar.pack(true);
+			toolbar.getShell().layout(new Control[] { toolbar }, SWT.DEFER);
+		}
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement childElement) {
+		Composite intermediate = (Composite) super.getUIContainer(childElement);
+		if (intermediate == null || intermediate.isDisposed()) {
+			return null;
+		}
+		if (intermediate instanceof ToolBar) {
+			return intermediate;
+		}
+		ToolBar toolbar = findToolbar(intermediate);
+		if (toolbar == null) {
+			toolbar = createToolbar(childElement.getParent(), intermediate);
+		}
+		return toolbar;
+	}
+
+	private ToolBar findToolbar(Composite intermediate) {
+		for (Control child : intermediate.getChildren()) {
+			if (child.getData() instanceof ToolBarManager) {
+				return (ToolBar) child;
+			}
+		}
+		return null;
+	}
+
+	private void modelProcessSwitch(ToolBarManager parentManager,
+			MToolBarElement childME) {
+		if (OpaqueElementUtil.isOpaqueToolItem(childME)) {
+			MToolItem itemModel = (MToolItem) childME;
+			processOpaqueItem(parentManager, itemModel);
+		} else if (childME instanceof MHandledToolItem) {
+			MHandledToolItem itemModel = (MHandledToolItem) childME;
+			processHandledItem(parentManager, itemModel);
+		} else if (childME instanceof MDirectToolItem) {
+			MDirectToolItem itemModel = (MDirectToolItem) childME;
+			processDirectItem(parentManager, itemModel);
+		} else if (childME instanceof MToolBarSeparator) {
+			MToolBarSeparator itemModel = (MToolBarSeparator) childME;
+			processSeparator(parentManager, itemModel);
+		} else if (childME instanceof MToolControl) {
+			MToolControl itemModel = (MToolControl) childME;
+			processToolControl(parentManager, itemModel);
+		}
+	}
+
+	private void processSeparator(ToolBarManager parentManager, MToolBarSeparator itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		AbstractGroupMarker marker = null;
+		if (itemModel.isVisible() && !itemModel.getTags().contains(MenuManagerRenderer.GROUP_MARKER)) {
+			marker = new Separator();
+			marker.setId(itemModel.getElementId());
+		} else {
+			if (itemModel.getElementId() != null) {
+				marker = new GroupMarker(itemModel.getElementId());
+			}
+		}
+		if (marker != null) {
+			addToManager(parentManager, itemModel, marker);
+			linkModelToContribution(itemModel, marker);
+		}
+	}
+
+	private void processToolControl(ToolBarManager parentManager, MToolControl itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		final IEclipseContext lclContext = getContext(itemModel);
+		ToolControlContribution ci = ContextInjectionFactory.make(ToolControlContribution.class, lclContext);
+		ci.setModel(itemModel);
+		ci.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	private void processDirectItem(ToolBarManager parentManager, MDirectToolItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		final IEclipseContext lclContext = getContext(itemModel);
+		DirectContributionItem ci = ContextInjectionFactory.make(DirectContributionItem.class, lclContext);
+		ci.setModel(itemModel);
+		ci.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	private void processHandledItem(ToolBarManager parentManager, MHandledToolItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+		itemModel.setRenderer(this);
+		final IEclipseContext lclContext = getContext(itemModel);
+		HandledContributionItem ci = ContextInjectionFactory.make(HandledContributionItem.class, lclContext);
+		ci.setModel(itemModel);
+		ci.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ci);
+		linkModelToContribution(itemModel, ci);
+	}
+
+	void processOpaqueItem(ToolBarManager parentManager, MToolItem itemModel) {
+		IContributionItem ici = getContribution(itemModel);
+		if (ici != null) {
+			return;
+		}
+
+		itemModel.setRenderer(this);
+		Object obj = OpaqueElementUtil.getOpaqueItem(itemModel);
+		if (obj instanceof IContributionItem) {
+			ici = (IContributionItem) obj;
+		} else {
+			return;
+		}
+		ici.setVisible(itemModel.isVisible());
+		addToManager(parentManager, itemModel, ici);
+		linkModelToContribution(itemModel, ici);
+	}
+
+	private void addToManager(ToolBarManager parentManager,
+			MToolBarElement model, IContributionItem ci) {
+		MElementContainer<MUIElement> parent = model.getParent();
+		// technically this shouldn't happen
+		if (parent == null) {
+			parentManager.add(ci);
+		} else {
+			int index = parent.getChildren().indexOf(model);
+			// shouldn't be -1, but better safe than sorry
+			if (index > parentManager.getSize() || index == -1) {
+				parentManager.add(ci);
+			} else {
+				parentManager.insert(index, ci);
+			}
+		}
+	}
+
+	/**
+	 * @param model
+	 * @return mapped manager, if any
+	 */
+	public ToolBarManager getManager(MToolBar model) {
+		return modelToManager.get(model);
+	}
+
+	/**
+	 * @param manager
+	 * @return mapped model, if any
+	 */
+	public MToolBar getToolBarModel(ToolBarManager manager) {
+		return managerToModel.get(manager);
+	}
+
+	/**
+	 * @param model
+	 * @param manager
+	 */
+	public void linkModelToManager(MToolBar model, ToolBarManager manager) {
+		modelToManager.put(model, manager);
+		managerToModel.put(manager, model);
+	}
+
+	/**
+	 * @param model
+	 * @param manager
+	 */
+	public void clearModelToManager(MToolBar model, ToolBarManager manager) {
+		modelToManager.remove(model);
+		managerToModel.remove(manager);
+	}
+
+	/**
+	 * @param element
+	 * @return mapped contribution, if any
+	 */
+	public IContributionItem getContribution(MToolBarElement element) {
+		return modelToContribution.get(element);
+	}
+
+	/**
+	 * @param item
+	 * @return mapped toolbar element, if any
+	 */
+	public MToolBarElement getToolElement(IContributionItem item) {
+		return contributionToModel.get(item);
+	}
+
+	/**
+	 * @param model
+	 * @param item
+	 */
+	public void linkModelToContribution(MToolBarElement model, IContributionItem item) {
+		modelToContribution.put(model, item);
+		contributionToModel.put(item, model);
+	}
+
+	/**
+	 * @param model
+	 * @param item
+	 */
+	public void clearModelToContribution(MToolBarElement model, IContributionItem item) {
+		modelToContribution.remove(model);
+		contributionToModel.remove(item);
+	}
+
+	/**
+	 * @param item
+	 * @return non null records list
+	 */
+	public ArrayList<ToolBarContributionRecord> getList(MToolBarElement item) {
+		ArrayList<ToolBarContributionRecord> tmp = sharedElementToRecord.get(item);
+		if (tmp == null) {
+			tmp = new ArrayList<ToolBarContributionRecord>();
+			sharedElementToRecord.put(item, tmp);
+		}
+		return tmp;
+	}
+
+	/**
+	 * @param element
+	 * @param record
+	 */
+	public void linkElementToContributionRecord(MToolBarElement element, ToolBarContributionRecord record) {
+		modelContributionToRecord.put(element, record);
+	}
+
+	/**
+	 * @param element
+	 * @return mapped record, if any
+	 */
+	public ToolBarContributionRecord getContributionRecord(MToolBarElement element) {
+		return modelContributionToRecord.get(element);
+	}
+
+	/**
+	 * @param menuManager
+	 * @param toolBar
+	 */
+	public void reconcileManagerToModel(IToolBarManager menuManager, MToolBar toolBar) {
+		List<MToolBarElement> modelChildren = toolBar.getChildren();
+		HashSet<MToolItem> oldModelItems = new HashSet<MToolItem>();
+		for (MToolBarElement itemModel : modelChildren) {
+			if (OpaqueElementUtil.isOpaqueToolItem(itemModel)) {
+				oldModelItems.add((MToolItem) itemModel);
+			}
+		}
+
+		IContributionItem[] items = menuManager.getItems();
+		for (int src = 0, dest = 0; src < items.length; src++, dest++) {
+			IContributionItem item = items[src];
+			MToolBarElement element = getToolElement(item);
+			if (element == null) {
+				MToolItem legacyItem = OpaqueElementUtil.createOpaqueToolItem();
+				legacyItem.setElementId(item.getId());
+				legacyItem.setVisible(item.isVisible());
+				OpaqueElementUtil.setOpaqueItem(legacyItem, item);
+				linkModelToContribution(legacyItem, item);
+				modelChildren.add(dest, legacyItem);
+			} else if (OpaqueElementUtil.isOpaqueToolItem(element)) {
+				MToolItem legacyItem = (MToolItem) element;
+				oldModelItems.remove(legacyItem);
+				if (modelChildren.size() > dest) {
+					if (modelChildren.get(dest) != legacyItem) {
+						modelChildren.remove(legacyItem);
+						modelChildren.add(dest, legacyItem);
+					}
+				} else {
+					modelChildren.add(legacyItem);
+				}
+			}
+		}
+
+		if (!oldModelItems.isEmpty()) {
+			modelChildren.removeAll(oldModelItems);
+			for (MToolItem model : oldModelItems) {
+				Object obj = OpaqueElementUtil.getOpaqueItem(model);
+				clearModelToContribution(model, (IContributionItem) obj);
+			}
+		}
+	}
+
+	@Override
+	public void postProcess(MUIElement element) {
+		if (element instanceof MToolBar) {
+			MToolBar toolbarModel = (MToolBar) element;
+			if (toolbarModel.getTransientData().containsKey(POST_PROCESSING_FUNCTION)) {
+				Object obj = toolbarModel.getTransientData().get(POST_PROCESSING_FUNCTION);
+				if (obj instanceof IContextFunction) {
+					IContextFunction func = (IContextFunction) obj;
+					final IEclipseContext ctx = getContext(toolbarModel);
+					toolbarModel.getTransientData().put(POST_PROCESSING_DISPOSE, func.compute(ctx, null));
+				}
+			}
+		}
+	}
+
+	@Override
+	public IEclipseContext getContext(MUIElement el) {
+		return super.getContext(el);
+	}
+
+	ToolItemUpdater getUpdater() {
+		return enablementUpdater;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarRenderer.java
new file mode 100644
index 0000000..0ccb8a7
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolBarRenderer.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.jface.layout.RowLayoutFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Create a toolbar
+ */
+public class ToolBarRenderer extends SWTPartRenderer {
+	private MApplication application;
+
+	private HashMap<MToolBar, ArrayList<ArrayList<MToolBarElement>>> pendingCleanup = new HashMap<MToolBar, ArrayList<ArrayList<MToolBarElement>>>();
+
+	@Override
+	public void init(IEclipseContext context) {
+		super.init(context);
+		application = context.get(MApplication.class);
+	}
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MToolBar) || !(parent instanceof Composite))
+			return null;
+
+		// HACK!! This should be done using a separate renderer
+		Composite intermediate = new Composite((Composite) parent, SWT.NONE);
+		createToolbar(element, intermediate);
+		intermediate.addDisposeListener(new DisposeListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				cleanUp((MToolBar) element);
+			}
+		});
+
+		return intermediate;
+	}
+
+	ToolBar createToolbar(final MUIElement element, Composite intermediate) {
+		int orientation = getOrientation(element);
+		RowLayout layout = RowLayoutFactory.fillDefaults().wrap(false)
+				.spacing(0).type(orientation).create();
+		layout.marginLeft = 3;
+		layout.center = true;
+		intermediate.setLayout(layout);
+		ToolBar separatorToolBar = new ToolBar(intermediate, orientation
+				| SWT.WRAP | SWT.FLAT | SWT.RIGHT);
+		new ToolItem(separatorToolBar, SWT.SEPARATOR);
+		return new ToolBar(intermediate, orientation | SWT.WRAP | SWT.FLAT
+				| SWT.RIGHT);
+	}
+
+	int getOrientation(final MUIElement element) {
+		MUIElement theParent = element.getParent();
+		if (theParent instanceof MTrimBar) {
+			MTrimBar trimContainer = (MTrimBar) theParent;
+			SideValue side = trimContainer.getSide();
+			if (side.getValue() == SideValue.LEFT_VALUE
+					|| side.getValue() == SideValue.RIGHT_VALUE)
+				return SWT.VERTICAL;
+		}
+		return SWT.HORIZONTAL;
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement childElement) {
+		Composite intermediate = (Composite) super.getUIContainer(childElement);
+		if (intermediate == null || intermediate.isDisposed()) {
+			return null;
+		}
+		ToolBar toolbar = findToolbar(intermediate);
+		if (toolbar == null) {
+			toolbar = createToolbar(childElement.getParent(), intermediate);
+		}
+		return toolbar;
+	}
+
+	ToolBar findToolbar(Composite intermediate) {
+		if (!intermediate.isDisposed()) {
+			Control[] children = intermediate.getChildren();
+			int length = children.length;
+			if (length > 0 && children[length - 1] instanceof ToolBar) {
+				return (ToolBar) children[length - 1];
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		// Since there's no place to 'store' a child that's not in a menu
+		// we'll blow it away and re-create on an add
+		Widget widget = (Widget) child.getWidget();
+		if (widget != null && !widget.isDisposed()) {
+			widget.dispose();
+		}
+		ToolBar toolbar = (ToolBar) getUIContainer(child);
+		if (toolbar != null && !toolbar.isDisposed()) {
+			toolbar.getShell().layout(new Control[] { toolbar }, SWT.DEFER);
+		}
+		disposeToolbarIfNecessary(parentElement);
+	}
+
+	private void disposeToolbarIfNecessary(MUIElement element) {
+		Composite composite = (Composite) element.getWidget();
+		ToolBar toolbar = findToolbar(composite);
+		if (toolbar != null && hasOnlySeparators(toolbar)) {
+			toolbar.dispose();
+			if (composite.getChildren().length > 0) {
+				composite.getChildren()[0].dispose();
+			}
+		}
+	}
+
+	boolean hasOnlySeparators(ToolBar toolbar) {
+		ToolItem[] children = toolbar.getItems();
+		for (ToolItem toolItem : children) {
+			if ((toolItem.getStyle() & SWT.SEPARATOR) == 0) {
+				return false;
+			} else if (toolItem.getControl() != null
+					&& toolItem.getControl().getData(OWNING_ME) instanceof MToolControl) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public void childRendered(MElementContainer<MUIElement> parentElement,
+			MUIElement element) {
+		super.childRendered(parentElement, element);
+		ToolBar toolbar = (ToolBar) getUIContainer(element);
+		if (toolbar != null && !toolbar.isDisposed()) {
+			toolbar.getShell().layout(new Control[] { toolbar }, SWT.DEFER);
+		}
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> container) {
+		super.processContents(container);
+		IEclipseContext ctx = getContext(container);
+		ExpressionContext eContext = new ExpressionContext(ctx);
+		ArrayList<MToolBarContribution> toContribute = new ArrayList<MToolBarContribution>();
+		MElementContainer<?> toolbarObj = container;
+		MToolBar toolbarModel = (MToolBar) toolbarObj;
+		ContributionsAnalyzer.gatherToolBarContributions(toolbarModel,
+				application.getToolBarContributions(),
+				toolbarModel.getElementId(), toContribute, eContext);
+		addToolBarContributions(toolbarModel, toContribute, ctx, eContext,
+				pendingCleanup);
+	}
+
+	@Override
+	public void postProcess(MUIElement element) {
+		super.postProcess(element);
+		disposeToolbarIfNecessary(element);
+	}
+
+	public static void addToolBarContributions(
+			final MToolBar toolbarModel,
+			ArrayList<MToolBarContribution> toContribute,
+			IEclipseContext ctx,
+			final ExpressionContext eContext,
+			HashMap<MToolBar, ArrayList<ArrayList<MToolBarElement>>> pendingCleanup) {
+		HashSet<String> existingSeparatorNames = new HashSet<String>();
+		for (MToolBarElement child : toolbarModel.getChildren()) {
+			String elementId = child.getElementId();
+			if (child instanceof MToolBarSeparator && elementId != null) {
+				existingSeparatorNames.add(elementId);
+			}
+		}
+		boolean done = toContribute.size() == 0;
+		while (!done) {
+			ArrayList<MToolBarContribution> curList = new ArrayList<MToolBarContribution>(
+					toContribute);
+			int retryCount = toContribute.size();
+			toContribute.clear();
+
+			for (final MToolBarContribution contribution : curList) {
+				final ArrayList<MToolBarElement> toRemove = new ArrayList<MToolBarElement>();
+				if (!ContributionsAnalyzer.processAddition(toolbarModel,
+						contribution, toRemove, existingSeparatorNames)) {
+					toContribute.add(contribution);
+				} else {
+					if (contribution.getVisibleWhen() != null) {
+						ctx.runAndTrack(new RunAndTrack() {
+							@Override
+							public boolean changed(IEclipseContext context) {
+								if (!toolbarModel.isToBeRendered()
+										|| !toolbarModel.isVisible()
+										|| toolbarModel.getWidget() == null) {
+									return false;
+								}
+								boolean rc = ContributionsAnalyzer.isVisible(
+										contribution, eContext);
+								for (MToolBarElement child : toRemove) {
+									child.setToBeRendered(rc);
+								}
+								return true;
+							}
+						});
+					}
+					ArrayList<ArrayList<MToolBarElement>> lists = pendingCleanup
+							.get(toolbarModel);
+					if (lists == null) {
+						lists = new ArrayList<ArrayList<MToolBarElement>>();
+						pendingCleanup.put(toolbarModel, lists);
+					}
+					lists.add(toRemove);
+				}
+			}
+			// We're done if the retryList is now empty (everything done) or
+			// if the list hasn't changed at all (no hope)
+			done = (toContribute.size() == 0)
+					|| (toContribute.size() == retryCount);
+		}
+	}
+
+	protected void cleanUp(MToolBar element) {
+		ArrayList<ArrayList<MToolBarElement>> lists = pendingCleanup
+				.remove(element);
+		if (lists == null) {
+			return;
+		}
+		for (ArrayList<MToolBarElement> list : lists) {
+			for (MToolBarElement child : list) {
+				element.getChildren().remove(child);
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlContribution.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlContribution.java
new file mode 100644
index 0000000..d4323d9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlContribution.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.action.ControlContribution;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class ToolControlContribution extends ControlContribution {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private MToolControl model;
+
+	@Inject
+	private IContributionFactory contribFactory;
+
+	@Inject
+	private EModelService modelService;
+
+	// private IEclipseContext parentContext;
+
+	public ToolControlContribution() {
+		super(null);
+	}
+
+	@Override
+	protected Control createControl(Composite parent) {
+		IEclipseContext localContext = EclipseContextFactory.create();
+
+		final Composite newComposite = new Composite(parent, SWT.NONE);
+		newComposite.setLayout(new FillLayout());
+		localContext.set(Composite.class.getName(), newComposite);
+		localContext.set(MToolControl.class.getName(), model);
+
+		final IEclipseContext parentContext = modelService
+				.getContainingContext(model);
+		if (model.getObject() == null) {
+			final Object tcImpl = contribFactory.create(
+					model.getContributionURI(), parentContext, localContext);
+			model.setObject(tcImpl);
+			newComposite.addDisposeListener(new DisposeListener() {
+
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					ContextInjectionFactory.uninject(tcImpl, parentContext);
+					model.setObject(null);
+				}
+			});
+		}
+
+		model.setWidget(newComposite);
+		newComposite.setData(AbstractPartRenderer.OWNING_ME, model);
+		newComposite.setData(this);
+
+		return newComposite;
+	}
+
+	public void setModel(MToolControl c) {
+		model = c;
+		setId(model.getElementId());
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRenderer.java
new file mode 100644
index 0000000..d05f15c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolControlRenderer.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * 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
+ *     Sopot Cela <sopotcela@gmail.com> - Bug 431868
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 431868
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSRenderingUtils;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+
+/**
+ * Create a contribute part.
+ */
+public class ToolControlRenderer extends SWTPartRenderer {
+
+	/**
+	 * Will be published or removed in 4.5.
+	 */
+	private static final String HIDEABLE = "HIDEABLE"; //$NON-NLS-1$
+	/**
+	 * Will be published or removed in 4.5.
+	 */
+	private static final String SHOW_RESTORE_MENU = "SHOW_RESTORE_MENU"; //$NON-NLS-1$
+
+	@Inject
+	private MApplication application;
+	/**
+	 * The context menu for this trim stack's items.
+	 */
+	private Menu toolControlMenu;
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MToolControl)
+				|| !(parent instanceof ToolBar || parent instanceof Composite))
+			return null;
+		Composite parentComp = (Composite) parent;
+		MToolControl toolControl = (MToolControl) element;
+
+		if (((MUIElement) toolControl.getParent()) instanceof MToolBar) {
+			IRendererFactory factory = context.get(IRendererFactory.class);
+			AbstractPartRenderer renderer = factory.getRenderer(
+					toolControl.getParent(), parent);
+			if (renderer instanceof ToolBarManagerRenderer) {
+				return null;
+			}
+		}
+
+		Widget parentWidget = (Widget) parent;
+		IEclipseContext parentContext = getContextForParent(element);
+
+		ToolItem sep = null;
+		if (parent instanceof ToolBar) {
+			sep = new ToolItem((ToolBar) parentWidget, SWT.SEPARATOR);
+		}
+
+		// final Composite newComposite = new Composite((Composite)
+		// parentWidget,
+		// SWT.NONE);
+		// newComposite.setLayout(new FillLayout());
+		// bindWidget(element, newComposite);
+
+		// Create a context just to contain the parameters for injection
+		IContributionFactory contributionFactory = parentContext
+				.get(IContributionFactory.class);
+
+		IEclipseContext localContext = EclipseContextFactory.create();
+
+		localContext.set(Composite.class.getName(), parentComp);
+		localContext.set(MToolControl.class.getName(), toolControl);
+
+		Object tcImpl = contributionFactory.create(
+				toolControl.getContributionURI(), parentContext, localContext);
+		toolControl.setObject(tcImpl);
+		Control[] kids = parentComp.getChildren();
+
+		// No kids means that the trim failed curing creation
+		if (kids.length == 0)
+			return null;
+
+		// The new control is assumed to be the last child created
+		// We could safe this up even more by asserting that the
+		// number of children should go up by *one* during injection
+		Control newCtrl = kids[kids.length - 1];
+
+		if (sep != null && newCtrl != null) {
+			sep.setControl(newCtrl);
+			newCtrl.pack();
+			sep.setWidth(newCtrl.getSize().x);
+		}
+
+		setCSSInfo(toolControl, newCtrl);
+
+		boolean vertical = false;
+		MUIElement parentElement = element.getParent();
+		if (parentElement instanceof MTrimBar) {
+			MTrimBar bar = (MTrimBar) parentElement;
+			vertical = bar.getSide() == SideValue.LEFT
+					|| bar.getSide() == SideValue.RIGHT;
+		}
+		CSSRenderingUtils cssUtils = parentContext.get(CSSRenderingUtils.class);
+		newCtrl = cssUtils.frameMeIfPossible(newCtrl, null, vertical, true);
+
+		boolean hideable = isHideable(toolControl);
+		boolean showRestoreMenu = isRestoreMenuShowable(toolControl);
+		if (showRestoreMenu || hideable) {
+			createToolControlMenu(toolControl, newCtrl, hideable);
+		}
+
+		return newCtrl;
+	}
+
+	private boolean isRestoreMenuShowable(MToolControl toolControl) {
+		return toolControl.getTags().contains(SHOW_RESTORE_MENU);
+	}
+
+	private boolean isHideable(MToolControl toolControl) {
+		return toolControl.getTags().contains(HIDEABLE);
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicTagsChanged(
+			@UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
+
+		Object changedObj = event.getProperty(EventTags.ELEMENT);
+
+		if (!(changedObj instanceof MToolControl))
+			return;
+
+		final MToolControl changedElement = (MToolControl) changedObj;
+
+		if (UIEvents.isADD(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE,
+					IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				changedElement.setVisible(false);
+			} else {
+				boolean hideable = UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, HIDEABLE);
+				if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, SHOW_RESTORE_MENU) || hideable) {
+					Object obj = changedElement.getWidget();
+					if (obj instanceof Control) {
+						if (((Control) obj).getMenu() == null) {
+							createToolControlMenu(changedElement, (Control) obj, hideable);
+						}
+					}
+				}
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE,
+					IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				changedElement.setVisible(true);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicAppStartup(
+			@UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Event event) {
+		List<MToolControl> toolControls = modelService.findElements(
+				application, null, MToolControl.class, null);
+		for (MToolControl toolControl : toolControls) {
+			if (toolControl.getTags().contains(
+					IPresentationEngine.HIDDEN_EXPLICITLY)) {
+				toolControl.setVisible(false);
+			}
+		}
+	}
+
+	private void createToolControlMenu(final MToolControl toolControl,
+ Control renderedCtrl, boolean hideable) {
+		toolControlMenu = new Menu(renderedCtrl);
+
+		if (hideable) {
+			MenuItem hideItem = new MenuItem(toolControlMenu, SWT.NONE);
+			hideItem.setText(Messages.ToolBarManagerRenderer_MenuCloseText);
+			hideItem.addListener(SWT.Selection, new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(org.eclipse.swt.widgets.Event event) {
+					toolControl.getTags().add(IPresentationEngine.HIDDEN_EXPLICITLY);
+				}
+			});
+
+			new MenuItem(toolControlMenu, SWT.SEPARATOR);
+		}
+
+		MenuItem restoreHiddenItems = new MenuItem(toolControlMenu, SWT.NONE);
+		restoreHiddenItems
+				.setText(Messages.ToolBarManagerRenderer_MenuRestoreText);
+		restoreHiddenItems.addListener(SWT.Selection, new Listener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void handleEvent(org.eclipse.swt.widgets.Event event) {
+				removeHiddenTags(toolControl);
+			}
+		});
+		renderedCtrl.setMenu(toolControlMenu);
+
+	}
+
+	/**
+	 * Removes the IPresentationEngine.HIDDEN_EXPLICITLY from the trimbar
+	 * entries. Having a separate logic for toolbars and toolcontrols would be
+	 * confusing for the user, hence we remove this tag for both these types
+	 *
+	 * @param toolbarModel
+	 */
+	private void removeHiddenTags(MToolControl toolControl) {
+		MWindow mWindow = modelService.getTopLevelWindowFor(toolControl);
+		List<MTrimElement> trimElements = modelService.findElements(mWindow,
+				null, MTrimElement.class, null);
+		for (MTrimElement trimElement : trimElements) {
+			trimElement.getTags().remove(IPresentationEngine.HIDDEN_EXPLICITLY);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemRenderer.java
new file mode 100644
index 0000000..d2beca1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemRenderer.java
@@ -0,0 +1,497 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.MContribution;
+import org.eclipse.e4.ui.model.application.commands.MParameter;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Create a contribute part.
+ */
+public class ToolItemRenderer extends SWTPartRenderer {
+
+	private static final String TIR_STATIC_CONTEXT = "HCI-staticContext"; //$NON-NLS-1$
+
+	@Inject
+	private Logger logger;
+	@Inject
+	private IEventBroker eventBroker;
+
+	private EventHandler itemUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MToolItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolItem))
+				return;
+
+			MToolItem itemModel = (MToolItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			ToolItem toolItem = (ToolItem) itemModel.getWidget();
+
+			// No widget == nothing to update
+			if (toolItem == null)
+				return;
+
+			String attName = (String) event
+					.getProperty(UIEvents.EventTags.ATTNAME);
+			if (UIEvents.UILabel.LABEL.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+				setItemText(itemModel, toolItem);
+			} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+				toolItem.setImage(getImage(itemModel));
+			} else if (UIEvents.UILabel.TOOLTIP.equals(attName)
+					|| UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
+				toolItem.setToolTipText(getToolTipText(itemModel));
+				toolItem.setImage(getImage(itemModel));
+			}
+		}
+	};
+
+	private EventHandler selectionUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MToolItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolItem))
+				return;
+
+			MToolItem itemModel = (MToolItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			ToolItem toolItem = (ToolItem) itemModel.getWidget();
+			if (toolItem != null) {
+				toolItem.setSelection(itemModel.isSelected());
+			}
+		}
+	};
+
+	private EventHandler enabledUpdater = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// Ensure that this event is for a MToolItem
+			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolItem))
+				return;
+
+			MToolItem itemModel = (MToolItem) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			ToolItem toolItem = (ToolItem) itemModel.getWidget();
+			if (toolItem != null) {
+				toolItem.setEnabled(itemModel.isEnabled());
+			}
+		}
+	};
+
+	@PostConstruct
+	public void init() {
+		eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_SELECTED, selectionUpdater);
+		eventBroker.subscribe(UIEvents.Item.TOPIC_ENABLED, enabledUpdater);
+	}
+
+	@PreDestroy
+	public void contextDisposed() {
+		eventBroker.unsubscribe(itemUpdater);
+		eventBroker.unsubscribe(selectionUpdater);
+		eventBroker.unsubscribe(enabledUpdater);
+	}
+
+	private ParameterizedCommand generateParameterizedCommand(
+			final MHandledItem item, final IEclipseContext lclContext) {
+		ECommandService cmdService = (ECommandService) lclContext
+				.get(ECommandService.class.getName());
+		Map<String, Object> parameters = null;
+		List<MParameter> modelParms = item.getParameters();
+		if (modelParms != null && !modelParms.isEmpty()) {
+			parameters = new HashMap<String, Object>();
+			for (MParameter mParm : modelParms) {
+				parameters.put(mParm.getName(), mParm.getValue());
+			}
+		}
+		ParameterizedCommand cmd = cmdService.createCommand(item.getCommand()
+				.getElementId(), parameters);
+		item.setWbCommand(cmd);
+		return cmd;
+	}
+
+	private void setItemText(MToolItem model, ToolItem item) {
+		String text = model.getLocalizedLabel();
+		if (text == null) {
+			text = ""; //$NON-NLS-1$
+		}
+		item.setText(text);
+	}
+
+	private String getToolTipText(MItem item) {
+		String text = item.getLocalizedTooltip();
+		if (item instanceof MHandledItem) {
+			MHandledItem handledItem = (MHandledItem) item;
+			IEclipseContext context = getContext(item);
+			EBindingService bs = (EBindingService) context
+					.get(EBindingService.class.getName());
+			ParameterizedCommand cmd = handledItem.getWbCommand();
+			if (cmd == null) {
+				cmd = generateParameterizedCommand(handledItem, context);
+			}
+			TriggerSequence sequence = bs.getBestSequenceFor(handledItem
+					.getWbCommand());
+			if (sequence != null) {
+				if (text == null) {
+					try {
+						text = cmd.getName();
+					} catch (NotDefinedException e) {
+						return null;
+					}
+				}
+				text = text + " (" + sequence.format() + ')'; //$NON-NLS-1$
+			}
+			return text;
+		}
+		return text;
+	}
+
+	@Override
+	public Object createWidget(final MUIElement element, Object parent) {
+		if (!(element instanceof MToolItem) || !(parent instanceof ToolBar))
+			return null;
+
+		MToolItem itemModel = (MToolItem) element;
+
+		// determine the index at which we should create the new item
+		int addIndex = calcVisibleIndex(element);
+
+		// OK, it's a real menu item, what kind?
+		MMenu menu = itemModel.getMenu();
+		int flags = 0;
+		if (menu != null) {
+			flags |= SWT.DROP_DOWN;
+		} else if (itemModel.getType() == ItemType.PUSH)
+			flags |= SWT.PUSH;
+		else if (itemModel.getType() == ItemType.CHECK)
+			flags |= SWT.CHECK;
+		else if (itemModel.getType() == ItemType.RADIO)
+			flags |= SWT.RADIO;
+
+		ToolItem newItem = new ToolItem((ToolBar) parent, flags, addIndex);
+		if (itemModel.getLabel() != null)
+			newItem.setText(itemModel.getLocalizedLabel());
+
+		newItem.setToolTipText(getToolTipText(itemModel));
+
+		newItem.setImage(getImage((MUILabel) element));
+
+		newItem.setEnabled(itemModel.isEnabled());
+
+		newItem.setSelection(itemModel.isSelected());
+
+		return newItem;
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		// Since there's no place to 'store' a child that's not in a menu
+		// we'll blow it away and re-create on an add
+		Widget widget = (Widget) child.getWidget();
+		if (widget != null && !widget.isDisposed())
+			widget.dispose();
+	}
+
+	@Override
+	public void hookControllerLogic(MUIElement me) {
+		// If the item is a CHECK or RADIO update the model's state to match
+		if (me instanceof MItem) {
+			final MItem item = (MItem) me;
+			if (item.getType() == ItemType.CHECK
+					|| item.getType() == ItemType.RADIO) {
+				ToolItem ti = (ToolItem) me.getWidget();
+				ti.addSelectionListener(new SelectionListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						item.setSelected(((ToolItem) e.widget).getSelection());
+					}
+
+					@Override
+					public void widgetDefaultSelected(SelectionEvent e) {
+						item.setSelected(((ToolItem) e.widget).getSelection());
+					}
+				});
+			} else if (me instanceof MToolItem) {
+				final MMenu mmenu = ((MToolItem) me).getMenu();
+				if (mmenu != null) {
+					final ToolItem ti = (ToolItem) me.getWidget();
+					ti.addSelectionListener(new SelectionAdapter() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetSelected(SelectionEvent e) {
+							if (e.detail == SWT.ARROW) {
+								Menu menu = getMenu(mmenu, ti);
+
+								Rectangle itemBounds = ti.getBounds();
+								Point displayAt = ti.getParent().toDisplay(
+										itemBounds.x,
+										itemBounds.y + itemBounds.height);
+								menu.setLocation(displayAt);
+								menu.setVisible(true);
+
+								Display display = menu.getDisplay();
+								while (menu.isVisible()) {
+									if (!display.readAndDispatch()) {
+										display.sleep();
+									}
+								}
+							}
+						}
+					});
+				}
+			}
+		}
+
+		// 'Execute' the operation if possible
+		if (me instanceof MContribution
+				&& ((MContribution) me).getContributionURI() != null) {
+			final MToolItem item = (MToolItem) me;
+			final MContribution contrib = (MContribution) me;
+			final IEclipseContext lclContext = getContext(me);
+			ToolItem ti = (ToolItem) me.getWidget();
+			ti.addSelectionListener(new SelectionListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					if (contrib.getObject() == null) {
+						IContributionFactory cf = (IContributionFactory) lclContext
+								.get(IContributionFactory.class.getName());
+						contrib.setObject(cf.create(
+								contrib.getContributionURI(), lclContext));
+					}
+					lclContext.set(MItem.class.getName(), item);
+					ContextInjectionFactory.invoke(contrib.getObject(),
+							Execute.class, lclContext);
+					lclContext.remove(MItem.class.getName());
+				}
+
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+			});
+		} else if (me instanceof MHandledItem) {
+			final MHandledItem item = (MHandledItem) me;
+			final IEclipseContext lclContext = getContext(me);
+			final ToolItem ti = (ToolItem) me.getWidget();
+			final Display display = ti.getDisplay();
+			display.timerExec(500, new Runnable() {
+				boolean logged = false;
+
+				@Override
+				public void run() {
+					if (ti.isDisposed()) {
+						return;
+					}
+					SafeRunner.run(new ISafeRunnable() {
+						@Override
+						public void run() throws Exception {
+							EHandlerService service = lclContext
+									.get(EHandlerService.class);
+							if (service == null) {
+								// no localized handler service
+								return;
+							}
+							ParameterizedCommand cmd = item.getWbCommand();
+							if (cmd == null) {
+								cmd = generateParameterizedCommand(item,
+										lclContext);
+							}
+							if (cmd == null) {
+								return;
+							}
+							final IEclipseContext staticContext = EclipseContextFactory
+									.create(TIR_STATIC_CONTEXT);
+							ContributionsAnalyzer.populateModelInterfaces(item,
+									staticContext, item.getClass()
+											.getInterfaces());
+							try {
+								item.setEnabled(service.canExecute(cmd,
+										staticContext));
+							} finally {
+								staticContext.dispose();
+							}
+						}
+
+						@Override
+						public void handleException(Throwable exception) {
+							if (!logged) {
+								logged = true;
+								logger.error(
+										exception,
+										"Internal error during tool item enablement updating, this is only logged once per tool item."); //$NON-NLS-1$
+							}
+						}
+					});
+					// repeat until disposed
+					display.timerExec(500, this);
+				}
+			});
+			ti.addSelectionListener(new SelectionListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					if (e.detail != SWT.ARROW) {
+						EHandlerService service = (EHandlerService) lclContext
+								.get(EHandlerService.class.getName());
+						ParameterizedCommand cmd = item.getWbCommand();
+						if (cmd == null) {
+							cmd = generateParameterizedCommand(item, lclContext);
+						}
+						if (cmd == null) {
+							Activator.trace(Policy.DEBUG_MENUS,
+									"Failed to execute: " + item.getCommand(), //$NON-NLS-1$
+									null);
+							return;
+						}
+						final IEclipseContext staticContext = EclipseContextFactory
+								.create(TIR_STATIC_CONTEXT);
+						ContributionsAnalyzer.populateModelInterfaces(item,
+								staticContext, item.getClass().getInterfaces());
+						service.executeHandler(cmd, staticContext);
+					}
+				}
+
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+			});
+		}
+	}
+
+	/**
+	 * @param mmenu
+	 * @param shell
+	 * @return
+	 */
+	protected Menu getMenu(final MMenu mmenu, ToolItem toolItem) {
+		Object obj = mmenu.getWidget();
+		if (obj instanceof Menu) {
+			return (Menu) obj;
+		}
+		// this is a temporary passthrough of the IMenuCreator
+		if (RenderedElementUtil.isRenderedMenu(mmenu)) {
+			obj = RenderedElementUtil.getContributionManager(mmenu);
+			if (obj instanceof IContextFunction) {
+				final IEclipseContext lclContext = getContext(mmenu);
+				obj = ((IContextFunction) obj).compute(lclContext, null);
+				RenderedElementUtil.setContributionManager(mmenu, obj);
+			}
+			if (obj instanceof IMenuCreator) {
+				final IMenuCreator creator = (IMenuCreator) obj;
+				final Menu menu = creator.getMenu(toolItem.getParent()
+						.getShell());
+				if (menu != null) {
+					toolItem.addDisposeListener(new DisposeListener() {
+						/**
+						 *
+						 */
+						private static final long serialVersionUID = 1L;
+
+						@Override
+						public void widgetDisposed(DisposeEvent e) {
+							if (menu != null && !menu.isDisposed()) {
+								creator.dispose();
+								mmenu.setWidget(null);
+							}
+						}
+					});
+					mmenu.setWidget(menu);
+					menu.setData(AbstractPartRenderer.OWNING_ME, menu);
+					return menu;
+				}
+			}
+		} else {
+			final IEclipseContext lclContext = getContext(mmenu);
+			IPresentationEngine engine = lclContext
+					.get(IPresentationEngine.class);
+			obj = engine.createGui(mmenu, toolItem.getParent(), lclContext);
+			if (obj instanceof Menu) {
+				return (Menu) obj;
+			}
+			logger.debug("Rendering returned " + obj); //$NON-NLS-1$
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemUpdater.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemUpdater.java
new file mode 100644
index 0000000..c1beb62
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ToolItemUpdater.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.ui.workbench.Selector;
+
+public class ToolItemUpdater {
+
+	private List<HandledContributionItem> itemsToCheck = new ArrayList<HandledContributionItem>();
+	private final List<HandledContributionItem> orphanedToolItems = new ArrayList<HandledContributionItem>();
+
+	void registerItem(HandledContributionItem item) {
+		if (!itemsToCheck.contains(item)) {
+			itemsToCheck.add(item);
+		}
+	}
+
+	void removeItem(HandledContributionItem item) {
+		itemsToCheck.remove(item);
+	}
+
+	public void updateContributionItems(Selector selector) {
+		for (final HandledContributionItem hci : itemsToCheck) {
+			if (hci.getModel() != null && hci.getModel().getParent() != null && selector.select(hci.getModel())) {
+				hci.updateItemEnablement();
+			} else {
+				orphanedToolItems.add(hci);
+			}
+		}
+		if (!orphanedToolItems.isEmpty()) {
+			itemsToCheck.removeAll(orphanedToolItems);
+			orphanedToolItems.clear();
+		}
+
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarLayout.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarLayout.java
new file mode 100644
index 0000000..83e5032
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarLayout.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2015 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
+ *     Christian Walther (Indel AG) - Bug 399458: Fix layout overlap in line-wrapped trim bar
+ *     Christian Walther (Indel AG) - Bug 389012: Fix division by zero in TrimBarLayout
+ *     Marc-Andre Laperle (Ericsson) - Bug 466233: Toolbar items are wrongly rendered into a "drop-down"
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.ToolBar;
+
+public class TrimBarLayout extends Layout {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	class TrimLine {
+		Map<Control, Point> sizeMap = new HashMap<Control, Point>();
+		List<Control> ctrls = new ArrayList<Control>();
+		int spacerCount = 0;
+		int extraSpace = 0;
+		int major = 0;
+		int minor = 0;
+
+		public void addControl(Control ctrl) {
+			Point ctrlSize = computeSize(ctrl);
+			int ctrlMajor = horizontal ? ctrlSize.x : ctrlSize.y;
+			int ctrlMinor = horizontal ? ctrlSize.y : ctrlSize.x;
+
+			major += ctrlMajor;
+			if (ctrlMinor > minor)
+				minor = ctrlMinor;
+
+			sizeMap.put(ctrl, ctrlSize);
+			ctrls.add(ctrl);
+
+			if (isSpacer(ctrl))
+				spacerCount++;
+		}
+
+		public void mergeSegment(TrimLine segment) {
+			sizeMap.putAll(segment.sizeMap);
+			ctrls.addAll(segment.ctrls);
+
+			major += segment.major;
+			if (segment.minor > minor)
+				minor = segment.minor;
+
+			spacerCount += segment.spacerCount;
+		}
+	}
+
+	private List<TrimLine> lines = new ArrayList<TrimLine>();
+
+	public static String SPACER = "stretch"; //$NON-NLS-1$
+	public static String GLUE = "glue"; //$NON-NLS-1$
+
+	private boolean horizontal;
+
+	public int marginLeft = 0;
+	public int marginRight = 0;
+	public int marginTop = 0;
+	public int marginBottom = 0;
+	public int wrapSpacing = 0;
+
+	public TrimBarLayout(boolean horizontal) {
+		this.horizontal = horizontal;
+	}
+
+	@Override
+	protected Point computeSize(Composite composite, int wHint, int hHint,
+			boolean flushCache) {
+		if (flushCache) {
+			// Clear the current cache
+			lines.clear();
+		}
+
+		// First, hide any empty toolbars
+		MTrimBar bar = (MTrimBar) composite
+				.getData(AbstractPartRenderer.OWNING_ME);
+		for (MTrimElement te : bar.getChildren()) {
+			hideManagedTB(te);
+		}
+
+		int totalMajor = horizontal ? wHint - (marginLeft + marginRight)
+				: hHint - (marginTop + marginBottom);
+		int totalMinor = 0;
+		int spaceLeft = totalMajor;
+
+		TrimLine curLine = new TrimLine();
+		Control[] kids = composite.getChildren();
+		for (int i = 0; i < kids.length; i++) {
+			Control ctrl = kids[i];
+
+			// GLUE Handling; gather any glued controls up into a 'segment'
+			TrimLine segment = new TrimLine();
+			segment.addControl(ctrl);
+			while (i < (kids.length - 2) && isGlue(kids[i + 1])) {
+				segment.addControl(kids[i + 1]);
+				segment.addControl(kids[i + 2]);
+				i += 2;
+			}
+
+			// Do we have enough space ?
+			if (segment.major <= spaceLeft) {
+				// Yes, add the segment to the current line
+				curLine.mergeSegment(segment);
+				spaceLeft -= segment.major;
+			} else {
+				// No, cache the current line and start a new one
+				curLine.extraSpace = spaceLeft;
+				lines.add(curLine);
+				totalMinor += curLine.minor;
+
+				curLine = segment;
+				spaceLeft = totalMajor - segment.major;
+			}
+		}
+
+		if (curLine.ctrls.size() > 0) {
+			curLine.extraSpace = spaceLeft;
+			lines.add(curLine);
+			totalMinor += curLine.minor;
+		}
+
+		// Adjust the 'totalMinor' to account for the margins
+		int totalWrapSpacing = (lines.size() - 1) * wrapSpacing;
+		totalMinor += horizontal ? (marginTop + marginBottom)
+				+ totalWrapSpacing : (marginLeft + marginRight)
+				+ totalWrapSpacing;
+		Point calcSize = horizontal ? new Point(wHint, totalMinor) : new Point(
+				totalMinor, hHint);
+		return calcSize;
+	}
+
+	private Point computeSize(Control ctrl) {
+		Point ctrlSize = ctrl.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+		// Hack! the StatusLine doesn't compute a useable size
+		if (isStatusLine(ctrl)) {
+			ctrlSize.x = 375;
+			ctrlSize.y = 26;
+		}
+
+		return ctrlSize;
+	}
+
+	/**
+	 * This is a HACK ! Due to compatibility restrictions we have the case where
+	 * we <b>must</b> leave 'empty' toolbars in the trim. This code detects this
+	 * particular scenario and hides any TB's of this type...
+	 *
+	 * @param te
+	 *            The proposed trim element
+	 * @return <code>true</code> iff this element represents an empty managed
+	 *         TB.
+	 */
+	private boolean hideManagedTB(MTrimElement te) {
+		if (!(te instanceof MToolBar)
+				|| !(te.getRenderer() instanceof ToolBarManagerRenderer))
+			return false;
+
+		if (!(te.getWidget() instanceof Composite))
+			return false;
+
+		Composite teComp = (Composite) te.getWidget();
+		Control[] kids = teComp.getChildren();
+		if (kids.length != 1 || !(kids[0] instanceof ToolBar))
+			return false;
+
+		boolean barVisible = ((ToolBar) kids[0]).getItemCount() > 0;
+
+		// HACK! The trim dragging code uses the visible attribute as well
+		// this is a local 'lock' to prevent the layout from messing with it
+		if (!te.getTags().contains("LockVisibility")) { //$NON-NLS-1$
+			te.setVisible(barVisible);
+		}
+
+		return !barVisible;
+	}
+
+	@Override
+	protected void layout(Composite composite, boolean flushCache) {
+		if (flushCache) {
+			// Clear the current cache
+			lines.clear();
+		}
+		Rectangle bounds = composite.getBounds();
+
+		// offset the rectangle to allow for the margins
+		bounds.x = marginLeft;
+		bounds.y = marginTop;
+		bounds.width -= (marginLeft + marginRight);
+		bounds.height -= (marginTop + marginBottom);
+
+		// If we were called directly we need to fill the caches
+		if (lines.size() == 0) {
+			if (horizontal)
+				computeSize(composite, bounds.width, SWT.DEFAULT, true);
+			else
+				computeSize(composite, SWT.DEFAULT, bounds.height, true);
+		}
+		if (lines.size() == 0)
+			return;
+
+		for (TrimLine curLine : lines) {
+			tileLine(curLine, bounds);
+			if (horizontal)
+				bounds.y += curLine.minor + wrapSpacing;
+			else
+				bounds.x += curLine.minor + wrapSpacing;
+		}
+	}
+
+	/**
+	 * @param curLine
+	 * @param bounds
+	 */
+	private void tileLine(TrimLine curLine, Rectangle bounds) {
+		int curX = bounds.x;
+		int curY = bounds.y;
+		int remainingExtraSpace = curLine.extraSpace;
+		int remainingSpacerCount = curLine.spacerCount;
+		for (Control ctrl : curLine.ctrls) {
+			if (ctrl.isDisposed()) {
+				continue;
+			}
+			Point ctrlSize = curLine.sizeMap.get(ctrl);
+			int ctrlWidth = ctrlSize.x;
+			int ctrlHeight = ctrlSize.y;
+			boolean zeroSize = ctrlWidth == 0 && ctrlHeight == 0;
+
+			// If its a 'spacer' then add any available 'extra' space to it
+			if (isSpacer(ctrl)) {
+				int extra = remainingExtraSpace / remainingSpacerCount;
+				if (horizontal) {
+					ctrlWidth += extra;
+					// leave out 4 pixels at the bottom to avoid overlapping the
+					// 1px bottom border of the toolbar (bug 389941)
+					ctrl.setBounds(curX, curY, ctrlWidth, curLine.minor - 4);
+				} else {
+					ctrlHeight += extra;
+					ctrl.setBounds(curX, curY, curLine.minor, ctrlHeight);
+				}
+				zeroSize = false;
+				remainingExtraSpace -= extra;
+				remainingSpacerCount--;
+			}
+
+			if (horizontal) {
+				int offset = (curLine.minor - ctrlHeight) / 2;
+				if (!isSpacer(ctrl)) {
+					if (!zeroSize)
+						ctrl.setBounds(curX, curY + offset, ctrlWidth,
+								ctrlHeight);
+					else
+						ctrl.setBounds(curX, curY, 0, 0);
+				}
+				curX += ctrlWidth;
+			} else {
+				int offset = (curLine.minor - ctrlWidth) / 2;
+				ctrl.setBounds(curX + offset, curY, ctrlWidth, ctrlHeight);
+				curY += ctrlHeight;
+			}
+		}
+	}
+
+	private boolean isSpacer(Control ctrl) {
+		MUIElement element = (MUIElement) ctrl
+				.getData(AbstractPartRenderer.OWNING_ME);
+		if (element != null && element.getTags().contains(SPACER))
+			return true;
+
+		return false;
+	}
+
+	private boolean isGlue(Control ctrl) {
+		MUIElement element = (MUIElement) ctrl
+				.getData(AbstractPartRenderer.OWNING_ME);
+		if (element != null && element.getTags().contains(GLUE))
+			return true;
+
+		return false;
+	}
+
+	private boolean isStatusLine(Control ctrl) {
+		MUIElement element = (MUIElement) ctrl
+				.getData(AbstractPartRenderer.OWNING_ME);
+		if (element != null && element.getElementId() != null
+				&& element.getElementId().equals("org.eclipse.ui.StatusLine")) //$NON-NLS-1$
+			return true;
+
+		return false;
+	}
+
+	/**
+	 * @param trimPos
+	 * @return
+	 */
+	public Control ctrlFromPoint(Composite trimComp, Point trimPos) {
+		if (trimComp == null || trimComp.isDisposed() || lines == null
+				|| lines.size() == 0)
+			return null;
+
+		Control[] kids = trimComp.getChildren();
+		for (int i = 0; i < kids.length; i++) {
+			if (kids[i].isDisposed())
+				continue;
+			if (kids[i].getBounds().contains(trimPos))
+				return kids[i];
+		}
+
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java
new file mode 100644
index 0000000..54a11b1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Tristan Hume - <trishume@gmail.com> -
+ *     		Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting
+ *     		Implemented workbench auto-save to correctly restore state in case of crash.
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ *
+ */
+public class TrimBarRenderer extends SWTPartRenderer {
+	private MApplication application;
+
+	private class LayoutJob implements Runnable {
+		public List<MTrimBar> barsToLayout = new ArrayList<MTrimBar>();
+
+		@Override
+		public void run() {
+			layoutJob = null;
+			if (barsToLayout.size() == 0)
+				return;
+			for (MTrimBar bar : barsToLayout) {
+				Composite trimCtrl = (Composite) bar.getWidget();
+				if (trimCtrl != null && !trimCtrl.isDisposed())
+					trimCtrl.layout();
+			}
+		}
+	}
+
+	private LayoutJob layoutJob = null;
+
+	synchronized private void layoutTrim(MTrimBar trimBar) {
+		Composite comp = (Composite) trimBar.getWidget();
+		if (comp == null || comp.isDisposed())
+			return;
+
+		if (layoutJob == null) {
+			layoutJob = new LayoutJob();
+			layoutJob.barsToLayout.add(trimBar);
+			comp.getDisplay().asyncExec(layoutJob);
+		} else if (!layoutJob.barsToLayout.contains(trimBar)) {
+			layoutJob.barsToLayout.add(trimBar);
+		}
+	}
+
+	@Override
+	public void init(IEclipseContext context) {
+		super.init(context);
+		application = context.get(MApplication.class);
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		if (!(element instanceof MTrimBar) || !(parent instanceof Composite))
+			return null;
+
+		Composite parentComp = (Composite) parent;
+
+		Composite trimComposite = null;
+		final MTrimBar trimModel = (MTrimBar) element;
+		if (parentComp.getLayout() instanceof TrimmedPartLayout) {
+			TrimmedPartLayout tpl = (TrimmedPartLayout) parentComp.getLayout();
+
+			switch (trimModel.getSide().getValue()) {
+			case SideValue.TOP_VALUE:
+				trimComposite = tpl.getTrimComposite(parentComp, SWT.TOP);
+				break;
+			case SideValue.BOTTOM_VALUE:
+				trimComposite = tpl.getTrimComposite(parentComp, SWT.BOTTOM);
+				break;
+			case SideValue.LEFT_VALUE:
+				trimComposite = tpl.getTrimComposite(parentComp, SWT.LEFT);
+				break;
+			case SideValue.RIGHT_VALUE:
+				trimComposite = tpl.getTrimComposite(parentComp, SWT.RIGHT);
+				break;
+			default:
+				return null;
+			}
+			trimComposite.addDisposeListener(new DisposeListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					cleanUp(trimModel);
+				}
+			});
+		} else {
+			trimComposite = new Composite(parentComp, SWT.NONE);
+			trimComposite.setLayout(new TrimBarLayout(true));
+		}
+		return trimComposite;
+	}
+
+	@Override
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+		super.hideChild(parentElement, child);
+
+		Object downCast = parentElement;
+		layoutTrim((MTrimBar) downCast);
+	}
+
+	@Override
+	public void processContents(MElementContainer<MUIElement> me) {
+		if (!(((MUIElement) me) instanceof MTrimBar))
+			return;
+		super.processContents(me);
+		IEclipseContext ctx = getContext(me);
+		ExpressionContext eContext = new ExpressionContext(ctx);
+		MElementContainer<?> trimObj = me;
+		MTrimBar trimModel = (MTrimBar) trimObj;
+		ArrayList<MTrimContribution> toContribute = new ArrayList<MTrimContribution>();
+		ContributionsAnalyzer.gatherTrimContributions(trimModel,
+				application.getTrimContributions(), trimModel.getElementId(),
+				toContribute, eContext);
+		addTrimContributions(trimModel, toContribute, ctx, eContext);
+	}
+
+	private void addTrimContributions(final MTrimBar trimModel,
+			ArrayList<MTrimContribution> toContribute, IEclipseContext ctx,
+			final ExpressionContext eContext) {
+		HashSet<String> existingToolbarIds = new HashSet<String>();
+
+		MTrimmedWindow topWin = (MTrimmedWindow) modelService
+				.getTopLevelWindowFor(trimModel);
+		for (MTrimBar bar : topWin.getTrimBars()) {
+			for (MTrimElement item : bar.getChildren()) {
+				String id = item.getElementId();
+				if (id != null) {
+					existingToolbarIds.add(id);
+				}
+			}
+		}
+
+		boolean done = toContribute.size() == 0;
+		while (!done) {
+			ArrayList<MTrimContribution> curList = new ArrayList<MTrimContribution>(
+					toContribute);
+			int retryCount = toContribute.size();
+			toContribute.clear();
+
+			for (final MTrimContribution contribution : curList) {
+				final ArrayList<MTrimElement> toRemove = new ArrayList<MTrimElement>();
+				if (!ContributionsAnalyzer.processAddition(trimModel,
+						contribution, toRemove, existingToolbarIds)) {
+					toContribute.add(contribution);
+				} else {
+					if (contribution.getVisibleWhen() != null) {
+						ctx.runAndTrack(new RunAndTrack() {
+							@Override
+							public boolean changed(IEclipseContext context) {
+								if (!trimModel.isToBeRendered()
+										|| !trimModel.isVisible()
+										|| trimModel.getWidget() == null) {
+									return false;
+								}
+								boolean rc = ContributionsAnalyzer.isVisible(
+										contribution, eContext);
+								for (MTrimElement child : toRemove) {
+									child.setToBeRendered(rc);
+								}
+								return true;
+							}
+						});
+					}
+					trimModel.getPendingCleanup().addAll(toRemove);
+				}
+			}
+			// We're done if the retryList is now empty (everything done) or
+			// if the list hasn't changed at all (no hope)
+			done = (toContribute.size() == 0)
+					|| (toContribute.size() == retryCount);
+		}
+	}
+
+	/**
+	 * @param element
+	 *            the trimBar to be cleaned up
+	 */
+	protected void cleanUp(MTrimBar element) {
+		for (MTrimElement child : element.getPendingCleanup()) {
+			element.getChildren().remove(child);
+		}
+		element.getPendingCleanup().clear();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimUtil.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimUtil.java
new file mode 100644
index 0000000..be3f3f1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimUtil.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import org.eclipse.jface.layout.RowLayoutFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ *
+ */
+public class TrimUtil {
+	public static Composite wrapTrim(Control trim) {
+		int orientation = SWT.HORIZONTAL;
+		if (trim instanceof ToolBar)
+			orientation = (((ToolBar) trim).getStyle() & SWT.VERTICAL) == 0 ? SWT.HORIZONTAL
+					: SWT.VERTICAL;
+
+		Composite parentComp = trim.getParent();
+		Composite wrapper = new Composite(parentComp, SWT.NONE);
+		RowLayout layout = RowLayoutFactory.fillDefaults().wrap(false)
+				.spacing(0).type(orientation).create();
+		layout.marginLeft = 3;
+		layout.center = true;
+		wrapper.setLayout(layout);
+
+		// Separator (aka 'drag handle')
+		ToolBar separatorToolBar = new ToolBar(wrapper, orientation | SWT.WRAP
+				| SWT.FLAT | SWT.RIGHT);
+		new ToolItem(separatorToolBar, SWT.SEPARATOR);
+
+		// Put the trim under the wrapper and ensure it's last
+		trim.setParent(wrapper);
+		trim.moveBelow(null);
+
+		return wrapper;
+	}
+
+	public static Control getRealControl(Composite wrapper) {
+		Control[] kids = wrapper.getChildren();
+		if (kids.length == 2)
+			return kids[1];
+
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimmedPartLayout.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimmedPartLayout.java
new file mode 100644
index 0000000..82dc704
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimmedPartLayout.java
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Layout;
+
+/**
+ * This arranges its controls into 5 'slots' defined by its composite children
+ * <ol>
+ * <li>Top: spans the entire width and abuts the top of the container</li>
+ * <li>Bottom: spans the entire width and abuts the bottom of the container</li>
+ * <li>Left: spans the space between 'top' and 'bottom' and abuts the left of
+ * the container</li>
+ * <li>Right: spans the space between 'top' and 'bottom' and abuts the right of
+ * the container</li>
+ * <li>Center: fills the area remaining once the other controls have been
+ * positioned</li>
+ * </ol>
+ *
+ * <strong>NOTE:</strong> <i>All</i> the child controls must exist. Also,
+ * computeSize is not implemented because we expect this to be used in
+ * situations (i.e. shells) where the outer bounds are always 'set', not
+ * computed. Also, the interior structure of the center may contain overlapping
+ * controls so it may not be capable of performing the calculation.
+ *
+ * @author emoffatt
+ *
+ */
+public class TrimmedPartLayout extends Layout {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * gutterBottom specifies the number of pixels of vertical margin that will
+	 * be placed between the bottom trim component and the bottom edge of the
+	 * client area. If there is no bottom trim component, the gutter serves as a
+	 * margin.
+	 *
+	 * The default value is 0.
+	 */
+	public int gutterBottom = 0;
+
+	/**
+	 * gutterLeft specifies the number of pixels of horizontal margin that will
+	 * be placed between the left trim component and the left edge of the client
+	 * area. If there is no left trim component, the gutter serves as a margin.
+	 *
+	 * The default value is 0.
+	 */
+	public int gutterLeft = 0;
+
+	/**
+	 * gutterTop specifies the number of pixels of vertical margin that will be
+	 * placed between the top trim component and the top edge of the client
+	 * area. If there is no top trim component, the gutter serves as a margin.
+	 *
+	 * The default value is 0.
+	 */
+	public int gutterTop = 0;
+
+	/**
+	 * gutterRight specifies the number of pixels of horizontal margin that will
+	 * be placed between the right trim component and the right edge of the
+	 * client area. If there is no right trim component, the gutter serves as a
+	 * margin.
+	 *
+	 * The default value is 0.
+	 */
+	public int gutterRight = 0;
+
+	public Composite top;
+	public Composite bottom;
+	public Composite left;
+	public Composite right;
+	public Composite clientArea;
+
+	/**
+	 * This layout is used to support parts that want trim for their containing
+	 * composites.
+	 *
+	 * @param trimOwner
+	 */
+	public TrimmedPartLayout(Composite parent) {
+		clientArea = new Composite(parent, SWT.NONE);
+		clientArea.setLayout(new FillLayout());
+	}
+
+	@Override
+	protected Point computeSize(Composite composite, int wHint, int hHint,
+			boolean flushCache) {
+		// We can't actually compute a size so return a default
+		return new Point(SWT.DEFAULT, SWT.DEFAULT);
+	}
+
+	@Override
+	protected void layout(Composite composite, boolean flushCache) {
+		Rectangle ca = composite.getClientArea();
+		Rectangle caRect = new Rectangle(ca.x, ca.y, ca.width, ca.height);
+
+		// 'Top' spans the entire area
+		if (top != null && top.isVisible()) {
+			Point topSize = top.computeSize(caRect.width, SWT.DEFAULT, true);
+			caRect.y += topSize.y;
+			caRect.height -= topSize.y;
+
+			// Don't layout unless we've changed
+			Rectangle newBounds = new Rectangle(ca.x, ca.y, caRect.width,
+					topSize.y);
+			if (!newBounds.equals(top.getBounds())) {
+				top.setBounds(newBounds);
+			}
+		}
+		// Include the gutter whether there is a top area or not.
+		caRect.y += gutterTop;
+		caRect.height -= gutterTop;
+
+		// 'Bottom' spans the entire area
+		if (bottom != null && bottom.isVisible()) {
+			Point bottomSize = bottom.computeSize(caRect.width, SWT.DEFAULT,
+					true);
+			caRect.height -= bottomSize.y;
+
+			// Don't layout unless we've changed
+			Rectangle newBounds = new Rectangle(caRect.x, caRect.y
+					+ caRect.height, caRect.width, bottomSize.y);
+			if (!newBounds.equals(bottom.getBounds())) {
+				bottom.setBounds(newBounds);
+			}
+		}
+		caRect.height -= gutterBottom;
+
+		// 'Left' spans between 'top' and 'bottom'
+		if (left != null && left.isVisible()) {
+			Point leftSize = left.computeSize(SWT.DEFAULT, caRect.height, true);
+			caRect.x += leftSize.x;
+			caRect.width -= leftSize.x;
+
+			// Don't layout unless we've changed
+			Rectangle newBounds = new Rectangle(caRect.x - leftSize.x,
+					caRect.y, leftSize.x, caRect.height);
+			if (!newBounds.equals(left.getBounds())) {
+				left.setBounds(newBounds);
+			}
+		}
+		caRect.x += gutterLeft;
+		caRect.width -= gutterLeft;
+
+		// 'Right' spans between 'top' and 'bottom'
+		if (right != null && right.isVisible()) {
+			Point rightSize = right.computeSize(SWT.DEFAULT, caRect.height,
+					true);
+			caRect.width -= rightSize.x;
+
+			// Don't layout unless we've changed
+			Rectangle newBounds = new Rectangle(caRect.x + caRect.width,
+					caRect.y, rightSize.x, caRect.height);
+			if (!newBounds.equals(right.getBounds())) {
+				right.setBounds(newBounds);
+			}
+		}
+		caRect.width -= gutterRight;
+
+		// Don't layout unless we've changed
+		if (!caRect.equals(clientArea.getBounds())) {
+			clientArea.setBounds(caRect);
+		}
+	}
+
+	/**
+	 * @param top2
+	 * @param b
+	 * @return
+	 */
+	public Composite getTrimComposite(Composite parent, int side) {
+		if (side == SWT.TOP) {
+			if (top == null) {
+				top = new Composite(parent, SWT.NONE);
+				top.setLayout(new TrimBarLayout(true));
+				top.addDisposeListener(new DisposeListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						top = null;
+					}
+				});
+			}
+			return top;
+		} else if (side == SWT.BOTTOM) {
+			if (bottom == null) {
+				bottom = new Composite(parent, SWT.NONE);
+				bottom.setLayout(new TrimBarLayout(true));
+				bottom.addDisposeListener(new DisposeListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						bottom = null;
+					}
+				});
+			}
+			return bottom;
+		} else if (side == SWT.LEFT) {
+			if (left == null) {
+				left = new Composite(parent, SWT.NONE);
+				left.setLayout(new TrimBarLayout(false));
+				left.addDisposeListener(new DisposeListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						left = null;
+					}
+				});
+			}
+			return left;
+		} else if (side == SWT.RIGHT) {
+			if (right == null) {
+				right = new Composite(parent, SWT.NONE);
+				right.setLayout(new TrimBarLayout(false));
+				right.addDisposeListener(new DisposeListener() {
+					/**
+					 *
+					 */
+					private static final long serialVersionUID = 1L;
+
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						right = null;
+					}
+				});
+			}
+			return right;
+		}
+
+		// Unknown location
+		return null;
+	}
+
+	public Rectangle getTrimRect(int side) {
+		Rectangle caBounds = clientArea.getBounds();
+		caBounds = Display.getCurrent().map(clientArea.getParent(), null,
+				caBounds);
+
+		if (side == SWT.TOP) {
+			if (top != null) {
+				Rectangle b = top.getBounds();
+				b = top.getDisplay().map(top.getParent(), null, b);
+				return b;
+			}
+
+			// Fake one
+			caBounds.height = 25;
+			return caBounds;
+		}
+		if (side == SWT.BOTTOM) {
+			if (bottom != null) {
+				Rectangle b = bottom.getBounds();
+				b = bottom.getDisplay().map(bottom.getParent(), null, b);
+				return b;
+			}
+
+			// Fake one
+			caBounds.y = (caBounds.y + caBounds.height) - 25;
+			caBounds.height = 25;
+			return caBounds;
+		}
+		if (side == SWT.LEFT) {
+			if (left != null && left.getChildren().length > 0) {
+				Rectangle b = left.getBounds();
+				b = left.getDisplay().map(left.getParent(), null, b);
+				return b;
+			}
+
+			// Fake one
+			caBounds.width = 25;
+			return caBounds;
+		}
+		if (side == SWT.RIGHT) {
+			if (right != null && right.getChildren().length > 0) {
+				Rectangle b = right.getBounds();
+				b = right.getDisplay().map(right.getParent(), null, b);
+				return b;
+			}
+
+			// Fake one
+			caBounds.x = (caBounds.x + caBounds.width) - 25;
+			caBounds.width = 25;
+			return caBounds;
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java
new file mode 100644
index 0000000..6180a88
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java
@@ -0,0 +1,898 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2015 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@vogella.com> - Bug 429728, 441150, 444410
+ *     Simon Scholz <Lars.Vogel@vogella.com> - Bug 429729
+ *     Mike Leneweit <mike-le@web.de> - Bug 444410
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.renderers.swt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler;
+import org.eclipse.e4.ui.internal.workbench.renderers.swt.SWTRenderersMessages;
+import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
+import org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Rectangle;
+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.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+import org.osgi.service.event.Event;
+
+/**
+ * Default SWT renderer responsible for an instance of MWindow. See
+ * {@link WorkbenchRendererFactory}
+ */
+public class WBWRenderer extends SWTPartRenderer {
+
+	private static String ShellMinimizedTag = "shellMinimized"; //$NON-NLS-1$
+	private static String ShellMaximizedTag = "shellMaximized"; //$NON-NLS-1$
+
+	private class WindowSizeUpdateJob implements Runnable {
+		public List<MWindow> windowsToUpdate = new ArrayList<MWindow>();
+
+		@Override
+		public void run() {
+			boundsJob = null;
+			while (!windowsToUpdate.isEmpty()) {
+				MWindow window = windowsToUpdate.remove(0);
+				Shell shell = (Shell) window.getWidget();
+				if (shell == null || shell.isDisposed())
+					continue;
+				shell.setBounds(window.getX(), window.getY(),
+						window.getWidth(), window.getHeight());
+			}
+		}
+	}
+
+	WindowSizeUpdateJob boundsJob;
+
+	boolean ignoreSizeChanges = false;
+
+	@Inject
+	Logger logger;
+
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	private IPresentationEngine engine;
+
+	// private ThemeDefinitionChangedHandler themeDefinitionChanged;
+
+	@Inject
+	private EModelService modelService;
+
+	@Inject
+	private Display display;
+
+	@Inject
+	@Optional
+	private void subscribeTopicSelectedElementChanged(
+			@UIEventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
+		// Ensure that this event is for a MApplication
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MApplication))
+			return;
+		MWindow win = (MWindow) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+		if ((win == null) || !win.getTags().contains("topLevel")) //$NON-NLS-1$
+			return;
+		win.setToBeRendered(true);
+		if (!(win.getRenderer() == WBWRenderer.this))
+			return;
+		Shell shell = (Shell) win.getWidget();
+		if (shell.getMinimized()) {
+			shell.setMinimized(false);
+		}
+		shell.setActive();
+		shell.moveAbove(null);
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicLabelChanged(@UIEventTopic(UIEvents.UILabel.TOPIC_ALL) Event event) {
+		Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MWindow))
+			return;
+
+		// Is this listener interested ?
+		MWindow windowModel = (MWindow) objElement;
+		if (windowModel.getRenderer() != WBWRenderer.this)
+			return;
+
+		// No widget == nothing to update
+		Shell theShell = (Shell) windowModel.getWidget();
+		if (theShell == null)
+			return;
+
+		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
+
+		if (UIEvents.UILabel.LABEL.equals(attName) || UIEvents.UILabel.LOCALIZED_LABEL.equals(attName)) {
+			String newTitle = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+			theShell.setText(newTitle);
+		} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
+			theShell.setImage(getImage(windowModel));
+		} else if (UIEvents.UILabel.TOOLTIP.equals(attName) || UIEvents.UILabel.LOCALIZED_TOOLTIP.equals(attName)) {
+			String newTTip = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+			theShell.setToolTipText(newTTip);
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicWindowChanged(@UIEventTopic(UIEvents.Window.TOPIC_ALL) Event event) {
+		if (ignoreSizeChanges)
+			return;
+
+		// Ensure that this event is for a MMenuItem
+		Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(objElement instanceof MWindow)) {
+			return;
+		}
+
+		// Is this listener interested ?
+		MWindow windowModel = (MWindow) objElement;
+		if (windowModel.getRenderer() != WBWRenderer.this) {
+			return;
+		}
+
+		// No widget == nothing to update
+		Shell theShell = (Shell) windowModel.getWidget();
+		if (theShell == null) {
+			return;
+		}
+
+		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
+
+		if (UIEvents.Window.X.equals(attName) || UIEvents.Window.Y.equals(attName)
+				|| UIEvents.Window.WIDTH.equals(attName) || UIEvents.Window.HEIGHT.equals(attName)) {
+			if (boundsJob == null) {
+				boundsJob = new WindowSizeUpdateJob();
+				boundsJob.windowsToUpdate.add(windowModel);
+				theShell.getDisplay().asyncExec(boundsJob);
+			} else {
+				if (!boundsJob.windowsToUpdate.contains(windowModel))
+					boundsJob.windowsToUpdate.add(windowModel);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTopicVisibleChanged(@UIEventTopic(UIEvents.UIElement.TOPIC_VISIBLE) Event event) {
+		// Ensure that this event is for a MMenuItem
+		Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(objElement instanceof MWindow))
+			return;
+
+		// Is this listener interested ?
+		MWindow windowModel = (MWindow) objElement;
+		if (windowModel.getRenderer() != WBWRenderer.this)
+			return;
+
+		// No widget == nothing to update
+		Shell theShell = (Shell) windowModel.getWidget();
+		if (theShell == null)
+			return;
+
+		String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
+
+		if (UIEvents.UIElement.VISIBLE.equals(attName)) {
+			boolean isVisible = (Boolean) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+			theShell.setVisible(isVisible);
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeThemeDefinitionChanged(
+			@UIEventTopic(UIEvents.UILifeCycle.THEME_DEFINITION_CHANGED) Event event) {
+		// themeDefinitionChanged.handleEvent(event);
+	}
+
+	/**
+	 * Closes the provided detached window.
+	 *
+	 * @param window
+	 *            the detached window to close
+	 * @return <code>true</code> if the window should be closed,
+	 *         <code>false</code> otherwise
+	 */
+	private boolean closeDetachedWindow(MWindow window) {
+		EPartService partService = window.getContext().get(EPartService.class);
+		List<MPart> parts = modelService.findElements(window, null,
+				MPart.class, null);
+		// this saves one part at a time, not ideal but better than not saving
+		// at all
+		for (MPart part : parts) {
+			if (!partService.savePart(part, true)) {
+				// user cancelled the operation, return false
+				return false;
+			}
+		}
+
+		// hide every part individually, following 3.x behaviour
+		for (MPart part : parts) {
+			partService.hidePart(part);
+		}
+		return true;
+	}
+
+	@PostConstruct
+	protected void init() {
+		// themeDefinitionChanged = new ThemeDefinitionChangedHandler();
+	}
+
+	@Override
+	public Object createWidget(MUIElement element, Object parent) {
+		final Widget newWidget;
+
+		if (!(element instanceof MWindow)
+				|| (parent != null && !(parent instanceof Control)))
+			return null;
+
+		MWindow wbwModel = (MWindow) element;
+
+		// MApplication appModel =
+		// wbwModel.getContext().get(MApplication.class);
+		// Boolean rtlMode = (Boolean)
+		// appModel.getTransientData().get(E4Workbench.RTL_MODE);
+		// FIXME RAP
+		// int rtlStyle = (rtlMode != null && rtlMode.booleanValue()) ?
+		// SWT.RIGHT_TO_LEFT : 0;
+		int rtlStyle = 0;
+
+		Shell parentShell = parent == null ? null : ((Control) parent)
+				.getShell();
+
+		final Shell wbwShell;
+
+		int styleOverride = getStyleOverride(wbwModel) | rtlStyle;
+		if (parentShell == null) {
+			int style = styleOverride == -1 ? SWT.SHELL_TRIM | rtlStyle
+					: styleOverride;
+			wbwShell = new Shell(display, style);
+			wbwModel.getTags().add("topLevel"); //$NON-NLS-1$
+		} else {
+			int style = SWT.TITLE | SWT.RESIZE | SWT.MAX | SWT.CLOSE | rtlStyle;
+			style = styleOverride == -1 ? style : styleOverride;
+			if (wbwModel.getTags().contains(IPresentationEngine.WINDOW_TOP_LEVEL))
+				wbwShell = new Shell(display, style);
+			else
+				wbwShell = new Shell(parentShell, style);
+
+			// Prevent ESC from closing the DW
+			wbwShell.addTraverseListener(new TraverseListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void keyTraversed(TraverseEvent e) {
+					if (e.detail == SWT.TRAVERSE_ESCAPE) {
+						e.doit = false;
+					}
+				}
+			});
+		}
+
+		// RAP: Since the e4 theming is not supported yet by RAP, background colors aren't set
+		//      explictly. Global transparency will lead to transparent fast views.
+		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=472301
+		// wbwShell.setBackgroundMode(SWT.INHERIT_DEFAULT);
+
+		Rectangle modelBounds = wbwShell.getBounds();
+		if (wbwModel instanceof EObject) {
+			EObject wbw = (EObject) wbwModel;
+			EClass wbwclass = wbw.eClass();
+			// use eIsSet rather than embed sentinel values
+			if (wbw.eIsSet(wbwclass.getEStructuralFeature("x"))) { //$NON-NLS-1$
+				modelBounds.x = wbwModel.getX();
+			}
+			if (wbw.eIsSet(wbwclass.getEStructuralFeature("y"))) { //$NON-NLS-1$
+				modelBounds.y = wbwModel.getY();
+			}
+			if (wbw.eIsSet(wbwclass.getEStructuralFeature("height"))) { //$NON-NLS-1$
+				modelBounds.height = wbwModel.getHeight();
+			}
+			if (wbw.eIsSet(wbwclass.getEStructuralFeature("width"))) { //$NON-NLS-1$
+				modelBounds.width = wbwModel.getWidth();
+			}
+		}
+		// Force the shell onto the display if it would be invisible otherwise
+		Rectangle displayBounds = Display.getCurrent().getBounds();
+		if (!modelBounds.intersects(displayBounds)) {
+			Rectangle clientArea = Display.getCurrent().getClientArea();
+			modelBounds.x = clientArea.x;
+			modelBounds.y = clientArea.y;
+		}
+		wbwShell.setBounds(modelBounds);
+
+		setCSSInfo(wbwModel, wbwShell);
+
+		// set up context
+		IEclipseContext localContext = getContext(wbwModel);
+
+		// We need to retrieve specific CSS properties for our layout.
+		CSSEngineHelper helper = new CSSEngineHelper(localContext, wbwShell);
+		TrimmedPartLayout tl = new TrimmedPartLayout(wbwShell);
+		tl.gutterTop = helper.getMarginTop(0);
+		tl.gutterBottom = helper.getMarginBottom(0);
+		tl.gutterLeft = helper.getMarginLeft(0);
+		tl.gutterRight = helper.getMarginRight(0);
+
+		wbwShell.setLayout(tl);
+		newWidget = wbwShell;
+		bindWidget(element, newWidget);
+
+		// Add the shell into the WBW's context
+		localContext.set(Shell.class, wbwShell);
+		localContext.set(E4Workbench.LOCAL_ACTIVE_SHELL, wbwShell);
+		setCloseHandler(wbwModel);
+		localContext.set(IShellProvider.class, new IShellProvider() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Shell getShell() {
+				return wbwShell;
+			}
+		});
+		final PartServiceSaveHandler saveHandler = new PartServiceSaveHandler() {
+			@Override
+			public Save promptToSave(MPart dirtyPart) {
+				Shell shell = (Shell) context
+						.get(IServiceConstants.ACTIVE_SHELL);
+				Object[] elements = promptForSave(shell,
+						Collections.singleton(dirtyPart));
+				if (elements == null) {
+					return Save.CANCEL;
+				}
+				return elements.length == 0 ? Save.NO : Save.YES;
+			}
+
+			@Override
+			public Save[] promptToSave(Collection<MPart> dirtyParts) {
+				List<MPart> parts = new ArrayList<MPart>(dirtyParts);
+				Shell shell = (Shell) context
+						.get(IServiceConstants.ACTIVE_SHELL);
+				Save[] response = new Save[dirtyParts.size()];
+				Object[] elements = promptForSave(shell, parts);
+				if (elements == null) {
+					Arrays.fill(response, Save.CANCEL);
+				} else {
+					Arrays.fill(response, Save.NO);
+					for (int i = 0; i < elements.length; i++) {
+						response[parts.indexOf(elements[i])] = Save.YES;
+					}
+				}
+				return response;
+			}
+		};
+		saveHandler.logger = logger;
+		localContext.set(ISaveHandler.class, saveHandler);
+
+		if (wbwModel.getLabel() != null)
+			wbwShell.setText(wbwModel.getLocalizedLabel());
+
+		if (wbwModel.getIconURI() != null && wbwModel.getIconURI().length() > 0) {
+			wbwShell.setImage(getImage(wbwModel));
+		} else {
+			// TODO: This should be added to the model, see bug 308494
+			// it allows for a range of icon sizes that the platform gets to
+			// choose from
+			wbwShell.setImages(Window.getDefaultImages());
+		}
+
+		return newWidget;
+	}
+
+	private void setCloseHandler(MWindow window) {
+		IEclipseContext context = window.getContext();
+		// no direct model parent, must be a detached window
+		if (window.getParent() == null) {
+			context.set(IWindowCloseHandler.class,
+					new IWindowCloseHandler() {
+						@Override
+						public boolean close(MWindow window) {
+							return closeDetachedWindow(window);
+						}
+					});
+		} else {
+			context.set(IWindowCloseHandler.class,
+					new IWindowCloseHandler() {
+						@Override
+						public boolean close(MWindow window) {
+					EPartService partService = window.getContext().get(EPartService.class);
+							return partService.saveAll(true);
+						}
+					});
+		}
+	}
+
+	@Override
+	public void hookControllerLogic(MUIElement me) {
+		super.hookControllerLogic(me);
+
+		Widget widget = (Widget) me.getWidget();
+
+		if (widget instanceof Shell && me instanceof MWindow) {
+			final Shell shell = (Shell) widget;
+			final MWindow w = (MWindow) me;
+			shell.addControlListener(new ControlListener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void controlResized(ControlEvent e) {
+					// Don't store the maximized size in the model
+					if (shell.getMaximized())
+						return;
+
+					try {
+						ignoreSizeChanges = true;
+						w.setWidth(shell.getSize().x);
+						w.setHeight(shell.getSize().y);
+					} finally {
+						ignoreSizeChanges = false;
+					}
+				}
+
+				@Override
+				public void controlMoved(ControlEvent e) {
+					// Don't store the maximized size in the model
+					if (shell.getMaximized())
+						return;
+
+					try {
+						ignoreSizeChanges = true;
+						w.setX(shell.getLocation().x);
+						w.setY(shell.getLocation().y);
+					} finally {
+						ignoreSizeChanges = false;
+					}
+				}
+			});
+
+			shell.addShellListener(new ShellAdapter() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void shellClosed(ShellEvent e) {
+					// override the shell close event
+					e.doit = false;
+					MWindow window = (MWindow) e.widget.getData(OWNING_ME);
+					IWindowCloseHandler closeHandler = window.getContext().get(IWindowCloseHandler.class);
+					// if there's no handler or the handler permits the close
+					// request, clean-up as necessary
+					if (closeHandler == null || closeHandler.close(window)) {
+						cleanUp(window);
+					}
+				}
+			});
+			shell.addListener(SWT.Activate, new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(org.eclipse.swt.widgets.Event event) {
+					MUIElement parentME = w.getParent();
+					if (parentME instanceof MApplication) {
+						MApplication app = (MApplication) parentME;
+						app.setSelectedElement(w);
+						w.getContext().activate();
+					} else if (parentME == null) {
+						parentME = (MUIElement) ((EObject) w).eContainer();
+						if (parentME instanceof MContext) {
+							w.getContext().activate();
+						}
+					}
+					updateNonFocusState(SWT.Activate, w);
+				}
+			});
+
+			shell.addListener(SWT.Deactivate, new Listener() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void handleEvent(org.eclipse.swt.widgets.Event event) {
+					updateNonFocusState(SWT.Deactivate, w);
+				}
+			});
+		}
+	}
+
+	private void updateNonFocusState(int event, MWindow win) {
+		MPerspective perspective = modelService.getActivePerspective(win);
+		if (perspective == null) {
+			return;
+		}
+
+		List<MPartStack> stacks = modelService.findElements(perspective, null,
+				MPartStack.class, Arrays.asList(CSSConstants.CSS_ACTIVE_CLASS));
+		if (stacks.isEmpty()) {
+			return;
+		}
+
+		MPartStack stack = stacks.get(0);
+		int tagsCount = stack.getTags().size();
+		boolean hasNonFocusTag = stack.getTags().contains(
+				CSSConstants.CSS_NO_FOCUS_CLASS);
+
+		if (event == SWT.Activate && hasNonFocusTag) {
+			stack.getTags().remove(CSSConstants.CSS_NO_FOCUS_CLASS);
+		} else if (event == SWT.Deactivate && !hasNonFocusTag) {
+			stack.getTags().add(CSSConstants.CSS_NO_FOCUS_CLASS);
+		}
+		if (tagsCount != stack.getTags().size()) {
+			setCSSInfo(stack, stack.getWidget());
+		}
+	}
+
+	private void cleanUp(MWindow window) {
+		Object parent = ((EObject) window).eContainer();
+		if (parent instanceof MApplication) {
+			MApplication application = (MApplication) parent;
+			List<MWindow> children = application.getChildren();
+			if (children.size() > 1) {
+				// not the last window, destroy and remove
+				window.setToBeRendered(false);
+				children.remove(window);
+			} else {
+				// last window, just destroy without changing the model
+				engine.removeGui(window);
+			}
+		} else if (parent != null) {
+			window.setToBeRendered(false);
+			// this is a detached window, check for parts
+			if (modelService.findElements(window, null, MPart.class, null)
+					.isEmpty()) {
+				// if no parts, remove it
+				if (parent instanceof MWindow) {
+					((MWindow) parent).getWindows().remove(window);
+				} else if (parent instanceof MPerspective) {
+					((MPerspective) parent).getWindows().remove(window);
+				}
+			}
+		}
+	}
+
+	/*
+	 * Processing the contents of a Workbench window has to take into account
+	 * that there may be trim elements contained in its child list. Since the
+	 */
+	@Override
+	public void processContents(MElementContainer<MUIElement> me) {
+		if (!(((MUIElement) me) instanceof MWindow))
+			return;
+		MWindow wbwModel = (MWindow) ((MUIElement) me);
+		super.processContents(me);
+
+		// Populate the main menu
+		IPresentationEngine renderer = context.get(IPresentationEngine.class);
+		if (wbwModel.getMainMenu() != null) {
+			renderer.createGui(wbwModel.getMainMenu(), me.getWidget(), null);
+			Shell shell = (Shell) me.getWidget();
+			shell.setMenuBar((Menu) wbwModel.getMainMenu().getWidget());
+		}
+
+		// create Detached Windows
+		for (MWindow dw : wbwModel.getWindows()) {
+			renderer.createGui(dw, me.getWidget(), wbwModel.getContext());
+		}
+
+		// Populate the trim (if any)
+		if (wbwModel instanceof MTrimmedWindow) {
+			Shell shell = (Shell) wbwModel.getWidget();
+			MTrimmedWindow tWindow = (MTrimmedWindow) wbwModel;
+			List<MTrimBar> trimBars = new ArrayList<MTrimBar>(
+					tWindow.getTrimBars());
+			for (MTrimBar trimBar : trimBars) {
+				renderer.createGui(trimBar, shell, wbwModel.getContext());
+				// bug 387161: hack around that createGui(e, parent, context)
+				// does not reparent the element widget to the
+				// limbo shell wheb visible=false
+				if (!trimBar.isVisible()) {
+					trimBar.setVisible(true);
+					trimBar.setVisible(false);
+				}
+			}
+		}
+	}
+
+	@Override
+	public Object getUIContainer(MUIElement element) {
+		MUIElement parent = element.getParent();
+		if (parent == null) {
+			// might be a detached window
+			parent = (MUIElement) ((EObject) element).eContainer();
+			return parent == null ? null : parent.getWidget();
+		}
+
+		Composite shellComp = (Composite) element.getParent().getWidget();
+		TrimmedPartLayout tpl = (TrimmedPartLayout) shellComp.getLayout();
+		return tpl.clientArea;
+	}
+
+	@Override
+	public void postProcess(MUIElement shellME) {
+		super.postProcess(shellME);
+
+		Shell shell = (Shell) shellME.getWidget();
+
+		// Capture the max/min state
+		final MUIElement disposeME = shellME;
+		shell.addDisposeListener(new DisposeListener() {
+			/**
+			 *
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				Shell shell = (Shell) e.widget;
+				if (disposeME != null) {
+					disposeME.getTags().remove(ShellMinimizedTag);
+					disposeME.getTags().remove(ShellMaximizedTag);
+					if (shell.getMinimized())
+						disposeME.getTags().add(ShellMinimizedTag);
+					if (shell.getMaximized())
+						disposeME.getTags().add(ShellMaximizedTag);
+				}
+			}
+		});
+
+		// Apply the correct shell state
+		if (shellME.getTags().contains(ShellMaximizedTag))
+			shell.setMaximized(true);
+		else if (shellME.getTags().contains(ShellMinimizedTag))
+			shell.setMinimized(true);
+
+		shell.layout(true);
+		forceLayout(shell);
+		if (shellME.isVisible()) {
+			shell.open();
+		} else {
+			shell.setVisible(false);
+		}
+	}
+
+	private Object[] promptForSave(Shell parentShell,
+			Collection<MPart> saveableParts) {
+		SaveablePartPromptDialog dialog = new SaveablePartPromptDialog(
+				parentShell, saveableParts);
+		if (dialog.open() == Window.CANCEL) {
+			return null;
+		}
+
+		return dialog.getCheckedElements();
+	}
+
+	private void applyDialogStyles(Control control) {
+		IStylingEngine engine = (IStylingEngine) context
+				.get(IStylingEngine.SERVICE_NAME);
+		if (engine != null) {
+			Shell shell = control.getShell();
+			if (shell.getBackgroundMode() == SWT.INHERIT_NONE) {
+				shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
+			}
+
+			engine.style(shell);
+		}
+	}
+
+	class SaveablePartPromptDialog extends Dialog {
+
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = 1L;
+
+		private Collection<MPart> collection;
+
+		private CheckboxTableViewer tableViewer;
+
+		private Object[] checkedElements = new Object[0];
+
+		SaveablePartPromptDialog(Shell shell, Collection<MPart> collection) {
+			super(shell);
+			this.collection = collection;
+		}
+
+		@Override
+		protected void configureShell(Shell newShell) {
+			super.configureShell(newShell);
+			newShell.setText(SWTRenderersMessages.choosePartsToSaveTitle);
+		}
+
+
+		@Override
+		protected Control createDialogArea(Composite parent) {
+			parent = (Composite) super.createDialogArea(parent);
+
+			Label label = new Label(parent, SWT.LEAD);
+			label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+			label.setText(SWTRenderersMessages.choosePartsToSave);
+
+			tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.SINGLE
+					| SWT.BORDER);
+			GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+			data.heightHint = 250;
+			data.widthHint = 300;
+			tableViewer.getControl().setLayoutData(data);
+			tableViewer.setLabelProvider(new LabelProvider() {
+				/**
+				 *
+				 */
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public String getText(Object element) {
+					return ((MPart) element).getLocalizedLabel();
+				}
+			});
+			tableViewer.setContentProvider(ArrayContentProvider.getInstance());
+			tableViewer.setInput(collection);
+			tableViewer.setAllChecked(true);
+
+			return parent;
+		}
+
+		@Override
+		public void create() {
+			super.create();
+			applyDialogStyles(getShell());
+		}
+
+		@Override
+		protected void okPressed() {
+			checkedElements = tableViewer.getCheckedElements();
+			super.okPressed();
+		}
+
+		public Object[] getCheckedElements() {
+			return checkedElements;
+		}
+
+		@Override
+		protected boolean isResizable() {
+			return true;
+		}
+
+	}
+
+	// protected static class ThemeDefinitionChangedHandler {
+	// protected Set<Resource> unusedResources = new HashSet<Resource>();
+	//
+	// public void handleEvent(Event event) {
+	// Object element = event.getProperty(IEventBroker.DATA);
+	//
+	// if (!(element instanceof MApplication)) {
+	// return;
+	// }
+	//
+	// Set<CSSEngine> engines = new HashSet<CSSEngine>();
+	//
+	// // In theory we can have multiple engines since API allows it.
+	// // It doesn't hurt to be prepared for such case
+	// for (MWindow window : ((MApplication) element).getChildren()) {
+	// CSSEngine engine = getEngine(window);
+	// if (engine != null) {
+	// engines.add(engine);
+	// }
+	// }
+	//
+	// for (CSSEngine engine : engines) {
+	// for (Object resource : removeResources(engine.getResourcesRegistry())) {
+	// if (resource instanceof Resource && !((Resource) resource).isDisposed())
+	// {
+	// unusedResources.add((Resource) resource);
+	// }
+	// }
+	// engine.reapply();
+	// }
+	// }
+	//
+	// protected CSSEngine getEngine(MWindow window) {
+	// return WidgetElement.getEngine((Widget) window.getWidget());
+	// }
+	//
+	// protected List<Object> removeResources(IResourcesRegistry registry) {
+	// if (registry instanceof SWTResourcesRegistry) {
+	// return ((SWTResourcesRegistry)
+	// registry).removeResourcesByKeyTypeAndType(ResourceByDefinitionKey.class,
+	// Font.class, Color.class);
+	// }
+	// return Collections.emptyList();
+	// }
+	//
+	// public void dispose() {
+	// for (Resource resource : unusedResources) {
+	// if (!resource.isDisposed()) {
+	// resource.dispose();
+	// }
+	// }
+	// unusedResources.clear();
+	// }
+	// }
+
+	private void forceLayout(Shell shell) {
+		int i = 0;
+		while (shell.isLayoutDeferred()) {
+			shell.setLayoutDeferred(false);
+			i++;
+		}
+		while (i > 0) {
+			shell.setLayoutDeferred(true);
+			i--;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WorkbenchRendererFactory.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WorkbenchRendererFactory.java
new file mode 100644
index 0000000..777beee
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WorkbenchRendererFactory.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.renderers.swt;
+
+import java.util.HashMap;
+import java.util.Set;
+import javax.annotation.PostConstruct;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
+
+public class WorkbenchRendererFactory implements IRendererFactory {
+	public static final String SHARED_ELEMENTS_STORE = "org.eclipse.e4.ui.workbench.renderers.swt.SHARED_ELEMENTS_STORE"; //$NON-NLS-1$
+	private AreaRenderer areaRenderer;
+	private MenuManagerRenderer menuRenderer;
+	private ToolBarManagerRenderer toolbarRenderer;
+	// private ToolItemRenderer toolItemRenderer;
+	private SeparatorRenderer separatorRenderer;
+	private ContributedPartRenderer contributedPartRenderer;
+	private ElementReferenceRenderer elementRefRenderer;
+	private PerspectiveStackRenderer perspStackRenderer;
+	private PerspectiveRenderer perspRenderer;
+	private SashRenderer partSashRenderer;
+	private LazyStackRenderer stackRenderer;
+	private TrimBarRenderer trimBarRenderer;
+	private ToolControlRenderer toolControlRenderer;
+	private WBWRenderer wbwRenderer;
+
+	private IEclipseContext context;
+
+	// private RenderedToolBarRenderer renderedToolbarRenderer;
+
+	@Override
+	public AbstractPartRenderer getRenderer(MUIElement uiElement, Object parent) {
+		if (uiElement instanceof MArea) {
+			if (areaRenderer == null) {
+				areaRenderer = new AreaRenderer();
+				initRenderer(areaRenderer);
+			}
+			return areaRenderer;
+		} else if (uiElement instanceof MPart) {
+			if (contributedPartRenderer == null) {
+				contributedPartRenderer = new ContributedPartRenderer();
+				initRenderer(contributedPartRenderer);
+			}
+			return contributedPartRenderer;
+		} else if (uiElement instanceof MMenu) {
+			if (menuRenderer == null) {
+				menuRenderer = new MenuManagerRenderer();
+				initRenderer(menuRenderer);
+			}
+			return menuRenderer;
+		} else if (uiElement instanceof MToolBar) {
+			if (toolbarRenderer == null) {
+				toolbarRenderer = new ToolBarManagerRenderer();
+				initRenderer(toolbarRenderer);
+			}
+			return toolbarRenderer;
+		} else if (uiElement instanceof MMenuSeparator
+				|| uiElement instanceof MToolBarSeparator) {
+			if (separatorRenderer == null) {
+				separatorRenderer = new SeparatorRenderer();
+				initRenderer(separatorRenderer);
+			}
+			return separatorRenderer;
+		} else if (uiElement instanceof MPlaceholder) {
+			if (elementRefRenderer == null) {
+				elementRefRenderer = new ElementReferenceRenderer();
+				initRenderer(elementRefRenderer);
+			}
+			return elementRefRenderer;
+		} else if (uiElement instanceof MPerspective) {
+			if (perspRenderer == null) {
+				perspRenderer = new PerspectiveRenderer();
+				initRenderer(perspRenderer);
+			}
+			return perspRenderer;
+		} else if (uiElement instanceof MPerspectiveStack) {
+			if (perspStackRenderer == null) {
+				perspStackRenderer = new PerspectiveStackRenderer();
+				initRenderer(perspStackRenderer);
+			}
+			return perspStackRenderer;
+		} else if (uiElement instanceof MPartSashContainer) {
+			if (partSashRenderer == null) {
+				partSashRenderer = new SashRenderer();
+				initRenderer(partSashRenderer);
+			}
+			return partSashRenderer;
+		} else if (uiElement instanceof MPartStack) {
+			if (stackRenderer == null) {
+				stackRenderer = new StackRenderer();
+				initRenderer(stackRenderer);
+			}
+			return stackRenderer;
+		} else if (uiElement instanceof MTrimBar) {
+			if (trimBarRenderer == null) {
+				trimBarRenderer = new TrimBarRenderer();
+				initRenderer(trimBarRenderer);
+			}
+			return trimBarRenderer;
+		} else if (uiElement instanceof MToolControl) {
+			if (toolControlRenderer == null) {
+				toolControlRenderer = new ToolControlRenderer();
+				initRenderer(toolControlRenderer);
+			}
+			return toolControlRenderer;
+		} else if (uiElement instanceof MWindow) {
+			if (wbwRenderer == null) {
+				wbwRenderer = new WBWRenderer();
+				initRenderer(wbwRenderer);
+			}
+			return wbwRenderer;
+		}
+
+		// We could return an 'no renderer' renderer here ??
+		return null;
+	}
+
+	protected void initRenderer(AbstractPartRenderer renderer) {
+		renderer.init(context);
+		ContextInjectionFactory.inject(renderer, context);
+	}
+
+	@PostConstruct
+	public void init(IEclipseContext context) {
+		this.context = context;
+		this.context.set(SHARED_ELEMENTS_STORE,
+				new HashMap<MUIElement, Set<MPlaceholder>>());
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/messages.properties b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/messages.properties
new file mode 100644
index 0000000..f76335b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/messages.properties
@@ -0,0 +1,13 @@
+################################################################################
+# Copyright (c) 2014 vogella GmbH  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:
+#     Lars Vogel <Lars.Vogel@gmail.com> - initial API and implementation
+################################################################################
+
+ToolBarManagerRenderer_MenuCloseText = &Hide
+ToolBarManagerRenderer_MenuRestoreText = &Restore Hidden Toolbar Entries
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.classpath b/bundles/org.eclipse.e4.ui.workbench.swt/.classpath
new file mode 100644
index 0000000..e8ea977
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.options b/bundles/org.eclipse.e4.ui.workbench.swt/.options
new file mode 100644
index 0000000..5f29e99
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.options
@@ -0,0 +1,7 @@
+org.eclipse.e4.ui.workbench.swt/debug = false
+org.eclipse.e4.ui.workbench.swt/trace/commands = false
+org.eclipse.e4.ui.workbench.swt/trace/menus = false
+org.eclipse.e4.ui.workbench.swt/trace/eclipse.context = false
+org.eclipse.e4.ui.workbench.swt/trace/eclipse.context.verbose = false
+org.eclipse.e4.ui.workbench.swt/trace/workbench = false
+org.eclipse.e4.ui.workbench.swt/trace/renderer = false
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.project b/bundles/org.eclipse.e4.ui.workbench.swt/.project
new file mode 100644
index 0000000..0b690ac
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.workbench.swt</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>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/.api_filters b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/.api_filters
new file mode 100644
index 0000000..614fa35
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/.api_filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.e4.ui.workbench.swt" version="2">
+    <resource path="src/org/eclipse/e4/ui/workbench/swt/internal/copy/FilteredTree.java" type="org.eclipse.e4.ui.workbench.swt.internal.copy.FilteredTree$NotifyingTreeViewer">
+        <filter comment="Known extension" id="571473929">
+            <message_arguments>
+                <message_argument value="TreeViewer"/>
+                <message_argument value="NotifyingTreeViewer"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..cb3755e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,386 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..2bb4b14
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,66 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+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=false
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=false
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..db9c90e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/MANIFEST.MF
@@ -0,0 +1,51 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.ui.workbench.swt;singleton:=true
+Bundle-Version: 0.13.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-Activator: org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator
+Require-Bundle: org.eclipse.equinox.registry;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.equinox.app;bundle-version="[1.3.0,2.0.0)",
+ org.eclipse.e4.ui.workbench;bundle-version="0.10.0",
+ org.eclipse.e4.core.services;bundle-version="1.0.0",
+ org.eclipse.e4.ui.services;bundle-version="0.1.0",
+ org.eclipse.core.databinding;bundle-version="[1.2.0,2.0.0)",
+ org.eclipse.osgi.services;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.e4.ui.bindings;bundle-version="0.9.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.0.0",
+ org.eclipse.core.jobs;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.e4.core.di;bundle-version="1.1.0",
+ org.eclipse.core.expressions;bundle-version="[3.4.200,4.0.0)",
+ org.eclipse.osgi;bundle-version="[3.6.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.11.0,4.0.0)",
+ org.eclipse.e4.core.commands;bundle-version="0.9.0",
+ org.eclipse.e4.ui.di;bundle-version="0.9.0",
+ org.eclipse.equinox.ds,
+ org.eclipse.equinox.event;resolution:=optional,
+ org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",
+ org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
+ org.eclipse.core.commands,
+ org.eclipse.rap.jface,
+ org.eclipse.rap.jface.databinding,
+ org.eclipse.e4.core.di.extensions
+Require-Capability: org.eclipse.rap
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Export-Package: org.eclipse.e4.ui.internal.workbench.swt;x-friends:="org.eclipse.e4.ui.workbench.addons.swt,org.eclipse.e4.ui.workbench.renderers.swt,org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.internal.workbench.swt.handlers;x-internal:=true,
+ org.eclipse.e4.ui.workbench.swt.factories;x-friends:="org.eclipse.e4.ui.workbench.renderers.swt,org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.workbench.swt.internal.copy;x-friends:="org.eclipse.e4.ui.workbench.renderers.swt",
+ org.eclipse.e4.ui.workbench.swt.util;x-friends:="org.eclipse.e4.ui.workbench.renderers.swt,org.eclipse.ui.workbench"
+Import-Package: com.ibm.icu.text;version="4.2.1",
+ javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.osgi.service.datalocation;version="1.2.0",
+ org.eclipse.osgi.service.debug;version="1.1.0",
+ org.osgi.framework;version="1.5.0",
+ org.osgi.service.packageadmin;version="1.2.0",
+ org.osgi.util.tracker;version="1.4.0",
+ org.w3c.dom.css;version="2.0.0"
+Service-Component: OSGI-INF/testableobject.xml, OSGI-INF/statusreporter.xml,
+ OSGI-INF/menuservice.xml
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/p2.inf b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/menuservice.xml b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/menuservice.xml
new file mode 100644
index 0000000..7bfcfb2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/menuservice.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.workbench.swt.menuService">
+   <implementation class="org.eclipse.e4.ui.internal.workbench.swt.MenuServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.ui.services.EMenuService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/statusreporter.xml b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/statusreporter.xml
new file mode 100644
index 0000000..360e6a1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/statusreporter.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.workbench.swt.statusReporter">
+   <implementation class="org.eclipse.e4.ui.internal.workbench.swt.StatusReporterCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.services.statusreporter.StatusReporter"/>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/testableobject.xml b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/testableobject.xml
new file mode 100644
index 0000000..39bb707
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/OSGI-INF/testableobject.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.ui.testing.TestableObject">
+   <implementation class="org.eclipse.e4.ui.internal.workbench.swt.E4Testable"/>
+   <service>
+      <provide interface="org.eclipse.ui.testing.TestableObject"/>
+   </service>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/about.html b/bundles/org.eclipse.e4.ui.workbench.swt/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/build.properties b/bundles/org.eclipse.e4.ui.workbench.swt/build.properties
new file mode 100644
index 0000000..aa6bb3f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/build.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2010, 2015 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
+###############################################################################
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               .options,\
+               OSGI-INF/,\
+               icons/,\
+               about.html,\
+               plugin.properties
+source.. = src/
+src.includes = icons/,\
+               about.html
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.ui.workbench.swt/forceQualifierUpdate.txt
new file mode 100644
index 0000000..c5d88d1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/forceQualifierUpdate.txt
@@ -0,0 +1,6 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
+Bug 407961 - Comparator log shows special problem that will require "touches"
+Bug 416898 - Some Platform UI bundles need to be touched to get API descriptions back
+Bug 429184 - [Metadata] comparator errors in most recent I-builds
+
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/dtool16/clear_co.gif b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/dtool16/clear_co.gif
new file mode 100644
index 0000000..7f32480
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/dtool16/clear_co.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/etool16/clear_co.gif b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/etool16/clear_co.gif
new file mode 100644
index 0000000..2d3935a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/etool16/clear_co.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/obj16/fldr_obj.gif b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/obj16/fldr_obj.gif
new file mode 100644
index 0000000..51e703b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/icons/full/obj16/fldr_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/plugin.properties b/bundles/org.eclipse.e4.ui.workbench.swt/plugin.properties
new file mode 100644
index 0000000..b4a7ba8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2010, 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
+###############################################################################
+pluginName = Eclipse e4 Workbench SWT
+providerName = Eclipse.org
+
+extension.e4application.name = E4 Application
+extension.generatetopic.name = Internal Model Topic Generator
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/plugin.xml b/bundles/org.eclipse.e4.ui.workbench.swt/plugin.xml
new file mode 100644
index 0000000..a179e5c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/plugin.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+     Copyright (c) 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
+ -->
+<plugin>
+   <extension
+         id="E4Application"
+         name="%extension.e4application.name"
+         point="org.eclipse.core.runtime.applications">
+      <application
+            cardinality="singleton-global"
+            thread="main"
+            visible="true">
+         <run
+               class="org.eclipse.e4.ui.internal.workbench.swt.E4Application">
+         </run>
+      </application>
+   </extension>
+   <extension
+         id="GenTopic"
+         name="%extension.generatetopic.name"
+         point="org.eclipse.core.runtime.applications">
+      <application
+            cardinality="singleton-global"
+            thread="main"
+            visible="true">
+         <run
+               class="org.eclipse.e4.ui.internal.workbench.swt.GenTopic">
+         </run>
+      </application>
+   </extension>
+
+   <extension
+         point="org.eclipse.core.runtime.adapters">
+      <factory
+            adaptableType="org.eclipse.jface.viewers.ISelection"
+            class="org.eclipse.e4.ui.internal.workbench.swt.SelectionAdapterFactory">
+         <adapter
+               type="org.eclipse.core.expressions.IIterable">
+         </adapter>
+         <adapter
+               type="org.eclipse.core.expressions.ICountable">
+         </adapter>
+      </factory>
+   </extension>
+</plugin>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/pom.xml b/bundles/org.eclipse.e4.ui.workbench.swt/pom.xml
new file mode 100644
index 0000000..1c1afd6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.workbench.swt</artifactId>
+  <version>0.13.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AbstractPartRenderer.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AbstractPartRenderer.java
new file mode 100644
index 0000000..025a261
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AbstractPartRenderer.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 429728
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.MUILabel;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+
+public abstract class AbstractPartRenderer {
+	public static final String OWNING_ME = "modelElement"; //$NON-NLS-1$
+
+	protected IEclipseContext context;
+	protected EModelService modelService;
+
+	public void init(IEclipseContext context) {
+		this.context = context;
+		modelService = context.get(EModelService.class);
+	}
+
+	public abstract Object createWidget(MUIElement element, Object parent);
+
+	public abstract void processContents(MElementContainer<MUIElement> container);
+
+	public void postProcess(MUIElement childElement) {
+	}
+
+	public abstract void bindWidget(MUIElement me, Object widget);
+
+	protected abstract Object getParentWidget(MUIElement element);
+
+	public abstract void disposeWidget(MUIElement part);
+
+	public abstract void hookControllerLogic(final MUIElement me);
+
+	public abstract void childRendered(
+			MElementContainer<MUIElement> parentElement, MUIElement element);
+
+	public void hideChild(MElementContainer<MUIElement> parentElement,
+			MUIElement child) {
+	}
+
+	protected abstract Object getImage(MUILabel element);
+
+	//
+	// public Object createMenu(Object widgetObject, MMenu menu) {
+	// return null;
+	// }
+	//
+	// public Object createToolBar(Object widgetObject, MToolBar toolBar) {
+	// return null;
+	// }
+
+	/**
+	 * Return a parent context for this part.
+	 *
+	 * @param element
+	 *            the part to start searching from
+	 * @return the parent's closest context, or global context if none in the
+	 *         hierarchy
+	 */
+	protected IEclipseContext getContextForParent(MUIElement element) {
+		return modelService.getContainingContext(element);
+	}
+
+	/**
+	 * Return a context for this part.
+	 *
+	 * @param part
+	 *            the part to start searching from
+	 * @return the closest context, or global context if none in the hierarchy
+	 */
+	protected IEclipseContext getContext(MUIElement part) {
+		if (part instanceof MContext) {
+			return ((MContext) part).getContext();
+		}
+		return getContextForParent(part);
+	}
+
+	/**
+	 * Activate the part in the hierarchy. This should either still be internal
+	 * or be a public method somewhere else.
+	 *
+	 * @param element
+	 */
+	public void activate(MPart element) {
+		IEclipseContext curContext = getContext(element);
+		if (curContext != null) {
+			EPartService ps = (EPartService) curContext.get(EPartService.class
+					.getName());
+			if (ps != null)
+				ps.activate(element, requiresFocus(element));
+		}
+	}
+
+	/**
+	 * Check if activating {@code element} requires that the part set the focus.
+	 *
+	 * @param element
+	 * @return true if the part requires focus
+	 */
+	protected abstract boolean requiresFocus(MPart element);
+
+	public void removeGui(MUIElement element, Object widget) {
+	}
+
+	public Object getUIContainer(MUIElement element) {
+		if (element.getParent() != null)
+			return element.getParent().getWidget();
+
+		return null;
+	}
+
+	/**
+	 * Force the UI focus into the element if possible. This method should not
+	 * be called directly, it will be called by the IPresentationEngine#focusGui
+	 * method if the normal process used to set the focus cannot be performed.
+	 *
+	 * @param element
+	 */
+	public void forceFocus(MUIElement element) {
+		// Do nothing by default
+	}
+
+	/**
+	 * @param mElement
+	 * @return Returns the style override bits or -1 if there is no override
+	 */
+	public int getStyleOverride(MUIElement mElement) {
+		String overrideStr = mElement.getPersistedState().get(
+				IPresentationEngine.STYLE_OVERRIDE_KEY);
+		if (overrideStr == null || overrideStr.length() == 0)
+			return -1;
+
+		int val = -1;
+		val = Integer.parseInt(overrideStr);
+		return val;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationEngine.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationEngine.java
new file mode 100644
index 0000000..28dce5a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationEngine.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+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.contexts.IEclipseContext;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * This job creates an Animation Engine that uses an Animation Feedback to
+ * render the animation. To begin the animation, instantiate this object then
+ * call schedule().
+ *
+ * @since 3.3
+ *
+ */
+public class AnimationEngine extends Job {
+	public static final int TICK_TIMER = 1;
+	public static final int FRAME_COUNT = 2;
+	public static final int unlimitedDuration = -1;
+
+	private boolean enableAnimations;
+	private long startTime;
+	private long curTime;
+	private long prevTime;
+	private int timingStyle = TICK_TIMER;
+	private long frameCount;
+	private boolean animationCanceled = false;
+	private long sleepAmount;
+
+	private Display display;
+	private AnimationFeedbackBase feedbackRenderer;
+	private int duration;
+
+	public AnimationEngine(IEclipseContext context,
+			AnimationFeedbackBase animationFeedback, int durationIn) {
+		this(context, animationFeedback, durationIn, 0);
+	}
+
+	/**
+	 * Creates an Animation that will run for the given number of milliseconds.
+	 *
+	 * @param animationFeedback
+	 *            provides renderStep(), initialize() and jobInit() methods
+	 * @param durationIn
+	 *            number of milliseconds over which the animation will run
+	 * @param sleepAmountIn
+	 *            number of milliseconds to slow/delay the animation
+	 */
+	public AnimationEngine(IEclipseContext context,
+			AnimationFeedbackBase animationFeedback, int durationIn,
+			long sleepAmountIn) {
+		super("E4 Animation");
+		sleepAmount = sleepAmountIn;
+		feedbackRenderer = animationFeedback;
+		duration = durationIn;
+
+		// if animations aren't on this is a NO-OP
+		enableAnimations = false;
+		if (context.get(IPresentationEngine.ANIMATIONS_ENABLED) != null)
+			enableAnimations = (Boolean) context
+					.get(IPresentationEngine.ANIMATIONS_ENABLED);
+		if (!enableAnimations) {
+			return;
+		}
+
+		animationCanceled = false;
+
+		// Capture parameters
+		display = feedbackRenderer.getAnimationShell().getDisplay();
+
+		animationFeedback.getAnimationShell().addDisposeListener(
+				new DisposeListener() {
+					@Override
+					public void widgetDisposed(DisposeEvent e) {
+						cancelAnimation();
+					}
+				});
+
+		// Don't show the job in monitors
+		setSystem(true);
+
+		// Set it up
+		feedbackRenderer.initialize(this);
+
+		// Set the animation's initial state
+		curTime = startTime = System.currentTimeMillis();
+
+	}
+
+	/**
+	 * @return The current renderer
+	 */
+	public AnimationFeedbackBase getFeedback() {
+		return feedbackRenderer;
+	}
+
+	private Runnable animationStep = new Runnable() {
+
+		@Override
+		public void run() {
+			if (animationCanceled)
+				return;
+
+			// Capture time
+			prevTime = curTime;
+			curTime = System.currentTimeMillis();
+
+			if (isUpdateStep()) {
+				updateDisplay();
+				frameCount++;
+			}
+		}
+
+	};
+
+	protected void updateDisplay() {
+		if (animationCanceled)
+			return;
+
+		feedbackRenderer.renderStep(this);
+	}
+
+	protected boolean isUpdateStep() {
+		if (duration == unlimitedDuration || timingStyle == FRAME_COUNT) {
+			return true;
+		}
+
+		// Default to 'TICK_TIMER', update when the system timer changes
+		return prevTime != curTime;
+	}
+
+	private boolean done() {
+		return animationCanceled || amount() >= 1.0;
+	}
+
+	public double amount() {
+		if (duration == unlimitedDuration) {
+			return 0;
+		}
+		double amount = 0.0;
+		switch (timingStyle) {
+		case TICK_TIMER:
+			amount = (double) (curTime - startTime) / (double) duration;
+			break;
+
+		// For testing purposes
+		case FRAME_COUNT:
+			amount = (double) frameCount / (double) duration;
+		}
+
+		if (amount > 1.0)
+			amount = 1.0;
+
+		return amount;
+	}
+
+	@Override
+	protected IStatus run(IProgressMonitor monitor) {
+		// We use preference value to indicate that the animation should be
+		// skipped on this platform.
+		if (!enableAnimations) {
+			return Status.OK_STATUS;
+		}
+
+		// We're starting, initialize
+		display.syncExec(new Runnable() {
+			@Override
+			public void run() {
+				// 'jobInit' returns 'false' if it doesn't want to run...
+				if (!animationCanceled)
+					animationCanceled = !feedbackRenderer
+							.jobInit(AnimationEngine.this);
+			}
+		});
+
+		if (animationCanceled)
+			return Status.CANCEL_STATUS;
+
+		// Only start the animation timer -after- we've initialized
+		curTime = startTime = System.currentTimeMillis();
+
+		while (!done() && !animationCanceled) {
+			display.syncExec(animationStep);
+
+			// Don't pin the CPU
+			try {
+				Thread.sleep(sleepAmount);
+			} catch (InterruptedException e) {
+			}
+		}
+
+		if (animationCanceled)
+			return Status.CANCEL_STATUS;
+
+		// We're done, clean up
+		display.syncExec(new Runnable() {
+			@Override
+			public void run() {
+				feedbackRenderer.dispose();
+			}
+		});
+
+		return Status.OK_STATUS;
+	}
+
+	public void cancelAnimation() {
+		animationCanceled = true;
+		feedbackRenderer.dispose();
+		cancel();
+	}
+
+	public long getFrameCount() {
+		return frameCount;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationFeedbackBase.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationFeedbackBase.java
new file mode 100644
index 0000000..3dba62b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/AnimationFeedbackBase.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * AnimationFeedBackBase is an abstract class which provides renderStep(),
+ * jobInit() and initialize() methods for AnimationEngine. Its the base class
+ * for all the animationFeedbacks
+ *
+ * @since 3.3
+ *
+ */
+public abstract class AnimationFeedbackBase {
+	private AnimationEngine engine;
+	private Shell baseShell;
+	private Shell animationShell = null;
+
+	/**
+	 * Creates an AnimationFeedback
+	 *
+	 * @param parentShell
+	 *            specifies the composite where the animation will be drawn
+	 */
+	public AnimationFeedbackBase(Shell parentShell) {
+		baseShell = parentShell;
+
+		baseShell.addDisposeListener(new DisposeListener() {
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				if (engine != null)
+					engine.cancelAnimation();
+			}
+		});
+	}
+
+	/**
+	 * Perform any initialization you want to do -prior- to the Job actually
+	 * gets scheduled.
+	 *
+	 * @param animationEngine
+	 *            The engine we're hosted in.
+	 */
+	public abstract void initialize(AnimationEngine animationEngine);
+
+	/**
+	 * Its a draw method. All the code to render an animation goes in this
+	 * method.
+	 *
+	 * @param engine
+	 */
+	public abstract void renderStep(AnimationEngine engine);
+
+	/**
+	 * Perform any initialization you want to have happen -before- the animation
+	 * starts. Subclasses may subclass but not override (i.e. you have to call
+	 * super).
+	 *
+	 * @param engine
+	 *            The AnimationEngine hosting the feedback
+	 * @return 'true' iff the animation is capable of running
+	 */
+	public boolean jobInit(AnimationEngine engine) {
+		this.engine = engine;
+		return engine != null;
+	}
+
+	/**
+	 * Dispose any locally created resources
+	 */
+	public void dispose() {
+		if (animationShell != null && !animationShell.isDisposed())
+			animationShell.dispose();
+	}
+
+	/**
+	 * @return The shell this animation is being rendered 'on'
+	 */
+	public Shell getBaseShell() {
+		return baseShell;
+	}
+
+	/**
+	 * @return A shell that can be used to render the animation on
+	 */
+	public Shell getAnimationShell() {
+		if (animationShell == null) {
+			animationShell = new Shell(getBaseShell(), SWT.NO_TRIM | SWT.ON_TOP);
+
+			animationShell.addDisposeListener(new DisposeListener() {
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					if (engine != null)
+						engine.cancelAnimation();
+				}
+			});
+		}
+
+		return animationShell;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSConstants.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSConstants.java
new file mode 100644
index 0000000..6eec483
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSConstants.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 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.internal.workbench.swt;
+
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+
+public class CSSConstants {
+	public static final String CSS_BUSY_CLASS = "busy";
+
+	public static final String CSS_ACTIVE_CLASS = IPresentationEngine.ACTIVE;
+
+	public static final String CSS_NO_FOCUS_CLASS = "noFocus";
+
+	public static final String CSS_HIGHLIGHTED_CLASS = "highlighted";
+
+	public static final String CSS_CONTENT_CHANGE_CLASS = "contentChange";
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSRenderingUtils.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSRenderingUtils.java
new file mode 100644
index 0000000..b387b1a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/CSSRenderingUtils.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 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.internal.workbench.swt;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.w3c.dom.css.CSSValue;
+
+public class CSSRenderingUtils {
+	private final static String FRAME_IMAGE_PROP = "frame-image";
+
+	private final static String HANDLE_IMAGE_PROP = "handle-image";
+
+	// NOTE: The CSS engine 'owns' the image it returns (it caches it)
+	// so we have to cache any rotated versions to match
+	private Map<Image, Image> rotatedImageMap = new HashMap<Image, Image>();
+
+	public Control frameMeIfPossible(Control toFrame, String classId,
+			boolean vertical, boolean draggable) {
+		Integer[] frameInts = new Integer[4];
+		// FIXME RAP unsupported
+		// Image frameImage = createImage(toFrame, classId, FRAME_IMAGE_PROP,
+		// frameInts);
+		// if (vertical && frameImage != null)
+		// frameImage = rotateImage(toFrame.getDisplay(), frameImage,
+		// frameInts);
+		//
+		// Image handleImage = createImage(toFrame, classId, HANDLE_IMAGE_PROP,
+		// null);
+		// if (vertical && handleImage != null)
+		// handleImage = rotateImage(toFrame.getDisplay(), handleImage, null);
+		//
+		// if (frameImage != null) {
+		// ImageBasedFrame frame = new ImageBasedFrame(toFrame.getParent(),
+		// toFrame, vertical, draggable);
+		// frame.setImages(frameImage, frameInts, handleImage);
+		// addFrameImageDisposedListener(frame, toFrame, classId, vertical);
+		// return frame;
+		// } else if (handleImage != null) {
+		// ImageBasedFrame frame = new ImageBasedFrame(toFrame.getParent(),
+		// toFrame, vertical, draggable);
+		// frame.setImages(null, null, handleImage);
+		// addHandleImageDisposedListener(frame, toFrame, classId, vertical);
+		// return frame;
+		// }
+
+		return toFrame;
+	}
+
+	private Image rotateImage(Display display, Image image, Integer[] frameInts) {
+		// FIXME RAP unsupported
+		// // Swap the widths / heights of the 'cuts'
+		// if (frameInts != null) {
+		// int tmp;
+		// tmp = frameInts[0];
+		// frameInts[0] = frameInts[2];
+		// frameInts[2] = tmp;
+		// tmp = frameInts[1];
+		// frameInts[1] = frameInts[3];
+		// frameInts[3] = tmp;
+		// }
+		//
+		// if (rotatedImageMap.get(image) != null)
+		// return rotatedImageMap.get(image);
+		//
+		// // rotate 90 degrees,,,
+		// Rectangle bounds = image.getBounds();
+		// ImageData imageData = new ImageData(bounds.height, bounds.width, 32,
+		// new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
+		// Image rotatedImage = new Image(display, imageData);
+		// GC gc = new GC(rotatedImage);
+		// RGB rgb = new RGB(0x7d, 0, 0);
+		// Color offRed = new Color(display, rgb);
+		// gc.setBackground(offRed);
+		// gc.fillRectangle(0, 0, bounds.height, bounds.width);
+		// Transform t = new Transform(display);
+		// int w = image.getBounds().height;
+		// int offset = 0; // (w+1) % 2;
+		// t.translate(w - offset, 0);
+		// t.rotate(90);
+		// gc.setTransform(t);
+		// gc.drawImage(image, 0, 0);
+		// gc.dispose();
+		// t.dispose();
+		// offRed.dispose();
+		// ImageData alphaData = rotatedImage.getImageData();
+		// rotatedImage.dispose();
+		// int transparentPix = alphaData.palette.getPixel(rgb);
+		// for (int i = 0; i < alphaData.width; i++) {
+		// for (int j = 0; j < alphaData.height; j++) {
+		// if (alphaData.getPixel(i, j) != transparentPix) {
+		// alphaData.setAlpha(i, j, 255);
+		// }
+		// }
+		// }
+		// rotatedImage = new Image(display, alphaData);
+		// // ...and cache it
+		// rotatedImageMap.put(image, rotatedImage);
+		//
+		// // Return the new one
+		// return rotatedImage;
+		return null;
+	}
+
+	public CSSValue getCSSValue(Control styleControl, String className,
+			String attributeName) {
+		// FIXME RAP unsupported
+		// CSSEngine csseng = WidgetElement.getEngine(styleControl);
+		// if (csseng == null) {
+		// return null;
+		// }
+		// ControlElement tempEment = (ControlElement) csseng
+		// .getElement(styleControl);
+		// if (tempEment == null) {
+		// return null;
+		// }
+		//
+		// // super hack
+		// if (className != null)
+		// WidgetElement.setCSSClass(styleControl, className);
+		//
+		// CSSStyleDeclaration styleDeclarations = csseng.getViewCSS()
+		//				.getComputedStyle(tempEment, ""); //$NON-NLS-1$
+		//
+		// if (styleDeclarations == null)
+		// return null;
+		//
+		// return styleDeclarations.getPropertyCSSValue(attributeName);
+		return null;
+	}
+
+	/**
+	 * @param string
+	 * @param string2
+	 * @return
+	 */
+	public Image createImage(Control styleControl, String classId,
+			String attName, Integer[] frameInts) {
+		Image image = null;
+		// FIXME RAP unsupported
+		// CSSEngine csseng = WidgetElement.getEngine(styleControl);
+		// if (csseng == null) {
+		// return null;
+		// }
+		// ControlElement tempEment = (ControlElement) csseng
+		// .getElement(styleControl);
+		// if (tempEment == null) {
+		// return null;
+		// }
+		// if (classId != null)
+		//			ControlElement.setCSSClass(styleControl, classId); //$NON-NLS-1$
+		//
+		// CSSStyleDeclaration styleDeclarations = csseng.getViewCSS()
+		// .getComputedStyle(tempEment, "");
+		// if (styleDeclarations == null)
+		// return null;
+		//
+		//		CSSValue imagePath = styleDeclarations.getPropertyCSSValue(attName); //$NON-NLS-1$
+		// if (imagePath == null)
+		// return null;
+		//
+		// if (imagePath != null
+		// && imagePath.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+		// // String imageString = ((CSSPrimitiveValue) imagePath)
+		// // .getStringValue();
+		// // System.out.println("here" + imageString);
+		// try {
+		// image = (Image) csseng.convert(imagePath, Image.class,
+		// styleControl.getDisplay());
+		// if (image != null && frameInts != null) {
+		// CSSValue value = styleDeclarations
+		//							.getPropertyCSSValue("frame-cuts"); //$NON-NLS-1$
+		// if (value.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
+		// CSSValueList valueList = (CSSValueList) value;
+		// if (valueList.getLength() != 4)
+		// return null;
+		//
+		// for (int i = 0; i < valueList.getLength(); i++) {
+		// CSSValue val = valueList.item(i);
+		// if ((val.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE)
+		// && ((CSSPrimitiveValue) val)
+		// .getPrimitiveType() == CSSPrimitiveValue.CSS_PX) {
+		// frameInts[i] = (int) ((CSSPrimitiveValue) val)
+		// .getFloatValue(CSSPrimitiveValue.CSS_PX);
+		// } else {
+		// return null;
+		// }
+		// }
+		//
+		// // System.out.println("Results " + frameInts);
+		// }
+		// }
+		// } catch (Exception e1) {
+		// }
+		// }
+		return image;
+	}
+	// FIXME RAP unsupported
+	// private void addHandleImageDisposedListener(
+	// ImageBasedFrame imageBasedFrame, final Control toFrame,
+	// final String classId, final boolean vertical) {
+	// final Listener listener = new Listener() {
+	// @Override
+	// public void handleEvent(Event event) {
+	// if (!(event.widget instanceof ImageBasedFrame)) {
+	// return;
+	// }
+	//
+	// ImageBasedFrame frame = (ImageBasedFrame) event.widget;
+	// if (!isImagesRefreshRequired(frame)) {
+	// return;
+	// }
+	//
+	// Image handleImage = createImage(toFrame, classId,
+	// HANDLE_IMAGE_PROP, null);
+	// if (vertical && handleImage != null) {
+	// handleImage = rotateImage(toFrame.getDisplay(),
+	// handleImage, null);
+	// }
+	// if (handleImage != null) {
+	// frame.setImages(null, null, handleImage);
+	// }
+	// }
+	// };
+	//
+	// toFrame.getDisplay().addListener(SWT.Skin, listener);
+	//
+	// imageBasedFrame.addDisposeListener(new DisposeListener() {
+	// @Override
+	// public void widgetDisposed(DisposeEvent e) {
+	// e.widget.getDisplay().removeListener(SWT.Skin, listener);
+	// }
+	// });
+	// }
+	//
+	// private void addFrameImageDisposedListener(ImageBasedFrame
+	// imageBasedFrame,
+	// final Control toFrame, final String classId, final boolean vertical) {
+	// final Listener listener = new Listener() {
+	// @Override
+	// public void handleEvent(Event event) {
+	// if (!(event.widget instanceof ImageBasedFrame)) {
+	// return;
+	// }
+	//
+	// ImageBasedFrame frame = (ImageBasedFrame) event.widget;
+	// if (!isImagesRefreshRequired(frame)) {
+	// return;
+	// }
+	//
+	// Integer[] frameInts = new Integer[4];
+	// Image frameImage = createImage(toFrame, classId,
+	// FRAME_IMAGE_PROP, frameInts);
+	// if (vertical && frameImage != null) {
+	// frameImage = rotateImage(toFrame.getDisplay(), frameImage,
+	// frameInts);
+	// }
+	//
+	// Image handleImage = createImage(toFrame, classId,
+	// HANDLE_IMAGE_PROP, null);
+	// if (vertical && handleImage != null) {
+	// handleImage = rotateImage(toFrame.getDisplay(),
+	// handleImage, null);
+	// }
+	// if (frameImage != null) {
+	// frame.setImages(frameImage, frameInts, handleImage);
+	// }
+	// }
+	// };
+	//
+	// toFrame.getDisplay().addListener(SWT.Skin, listener);
+	//
+	// imageBasedFrame.addDisposeListener(new DisposeListener() {
+	// @Override
+	// public void widgetDisposed(DisposeEvent e) {
+	// e.widget.getDisplay().removeListener(SWT.Skin, listener);
+	// }
+	// });
+	// }
+	//
+	// private boolean isImagesRefreshRequired(ImageBasedFrame frame) {
+	// Object handleImage = frame.getData("handleImage");
+	// if (handleImage instanceof Image && ((Image) handleImage).isDisposed()) {
+	// return true;
+	// }
+	//
+	// Object frameImage = frame.getData("frameImage");
+	// if (frameImage instanceof Image && ((Image) frameImage).isDisposed()) {
+	// return true;
+	// }
+	//
+	// return false;
+	// }
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java
new file mode 100644
index 0000000..a0ac06a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java
@@ -0,0 +1,947 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Tristan Hume - <trishume@gmail.com> -
+ *     		Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting
+ *     		Implemented workbench auto-save to correctly restore state in case of crash.
+ *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 366364, 445724, 446088
+ *     Terry Parker <tparker@google.com> - Bug 416673
+ *     Christian Georgi (SAP)            - Bug 432480
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.UUID;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.core.internal.services.EclipseAdapter;
+import org.eclipse.e4.core.services.adapter.Adapter;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.ILoggerProvider;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.core.services.translation.TranslationProviderFactory;
+import org.eclipse.e4.core.services.translation.TranslationService;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.e4.ui.internal.workbench.ActiveChildLookupFunction;
+import org.eclipse.e4.ui.internal.workbench.ActivePartLookupFunction;
+import org.eclipse.e4.ui.internal.workbench.DefaultLoggerProvider;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.e4.ui.internal.workbench.ExceptionHandler;
+import org.eclipse.e4.ui.internal.workbench.ModelServiceImpl;
+import org.eclipse.e4.ui.internal.workbench.PlaceholderResolver;
+import org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory;
+import org.eclipse.e4.ui.internal.workbench.ResourceHandler;
+import org.eclipse.e4.ui.internal.workbench.SelectionAggregator;
+import org.eclipse.e4.ui.internal.workbench.SelectionServiceImpl;
+import org.eclipse.e4.ui.internal.workbench.URIHelper;
+import org.eclipse.e4.ui.internal.workbench.WorkbenchLogger;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.e4.ui.workbench.IExceptionHandler;
+import org.eclipse.e4.ui.workbench.IModelResourceHandler;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
+import org.eclipse.e4.ui.workbench.lifecycle.PreSave;
+import org.eclipse.e4.ui.workbench.lifecycle.ProcessAdditions;
+import org.eclipse.e4.ui.workbench.lifecycle.ProcessRemovals;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.swt.internal.copy.WorkbenchSWTMessages;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.jface.databinding.swt.SWTObservables;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.service.SettingStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.framework.Bundle;
+import org.w3c.dom.css.CSSStyleDeclaration;
+
+/**
+ *
+ */
+public class E4Application implements IApplication {
+
+	private static final String PLUGIN_ID = "org.eclipse.e4.ui.workbench.swt"; //$NON-NLS-1$
+
+	// Copied from IDEApplication
+	public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
+	private static final String VERSION_FILENAME = "version.ini"; //$NON-NLS-1$
+	private static final String WORKSPACE_VERSION_KEY = "org.eclipse.core.runtime"; //$NON-NLS-1$
+	private static final String WORKSPACE_VERSION_VALUE = "2"; //$NON-NLS-1$
+	private static final String APPLICATION_MODEL_PATH_DEFAULT = "Application.e4xmi";
+	private static final String PERSPECTIVE_ARG_NAME = "perspective";
+	private static final String SHOWLOCATION_ARG_NAME = "showLocation";
+	private static final String DEFAULT_THEME_ID = "org.eclipse.e4.ui.css.theme.e4_default";
+	public static final String HIGH_CONTRAST_THEME_ID = "org.eclipse.e4.ui.css.theme.high-contrast";
+
+	public static final String INSTANCEID = "E4Application.instanceId";
+
+	private String[] args;
+
+	private IModelResourceHandler handler;
+	private Display display = null;
+	private E4Workbench workbench = null;
+
+	public static final String THEME_ID = "cssTheme";
+
+	// TODO RAP modified
+	public Object lcManager;
+
+	public Display getApplicationDisplay() {
+		if (display == null) {
+			display = Display.getDefault();
+		}
+		return display;
+	}
+
+	@Override
+	public Object start(IApplicationContext applicationContext) throws Exception {
+		// set the display name before the Display is
+		// created to ensure the app name is used in any
+		// platform menus, etc. See
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329456#c14
+		IProduct product = Platform.getProduct();
+		if (product != null && product.getName() != null) {
+			Display.setAppName(product.getName());
+		}
+		Display display = getApplicationDisplay();
+		Location instanceLocation = null;
+		try {
+			E4Workbench workbench = createE4Workbench(applicationContext, display);
+			if (workbench == null) {
+				display.dispose();
+				return EXIT_OK;
+			}
+
+			instanceLocation = (Location) workbench.getContext().get(E4Workbench.INSTANCE_LOCATION);
+			Shell shell = display.getActiveShell();
+			if (shell == null) {
+				shell = new Shell();
+				// place it off so it's not visible
+				shell.setLocation(0, 10000);
+			}
+			if (!checkInstanceLocation(instanceLocation, shell,
+					workbench.getContext()))
+				return EXIT_OK;
+
+			// Create and run the UI (if any)
+			workbench.createAndRunUI(workbench.getApplication());
+
+			saveModel();
+			workbench.close();
+
+			if (workbench.isRestart()) {
+				return EXIT_RESTART;
+			}
+
+			return EXIT_OK;
+		} finally {
+			if (display != null)
+				display.dispose();
+			if (instanceLocation != null)
+				instanceLocation.release();
+		}
+	}
+
+	public void saveModel() {
+		// Save the model into the targetURI
+		if (lcManager != null && workbench != null) {
+			ContextInjectionFactory.invoke(lcManager, PreSave.class, workbench.getContext(), null);
+		}
+
+		try {
+			if (!(handler instanceof ResourceHandler) || ((ResourceHandler) handler).hasTopLevelWindows()) {
+				handler.save();
+			} else {
+				Logger logger = new WorkbenchLogger(PLUGIN_ID);
+				logger.error(new Exception(), // log a stack trace for debugging
+						"Attempted to save a workbench model that had no top-level windows! " //$NON-NLS-1$
+								+ "Skipped saving the model to avoid corruption."); //$NON-NLS-1$
+			}
+
+		} catch (IOException e) {
+			Logger logger = new WorkbenchLogger(PLUGIN_ID);
+			logger.error(e, "Error saving the workbench model"); //$NON-NLS-1$
+		}
+	}
+
+	public E4Workbench createE4Workbench(
+			IApplicationContext applicationContext, final Display display) {
+		args = (String[]) applicationContext.getArguments().get(IApplicationContext.APPLICATION_ARGS);
+
+		final IEclipseContext appContext = createDefaultContext();
+		appContext.set(Display.class, display);
+		// FIXME RAP DisplayRealm not public!!!
+		appContext.set(Realm.class, SWTObservables.getRealm(display));
+		appContext.set(UISynchronize.class, new UISynchronize() {
+
+			@Override
+			public void syncExec(Runnable runnable) {
+				if (display != null && !display.isDisposed()) {
+					display.syncExec(runnable);
+				}
+			}
+
+			@Override
+			public void asyncExec(Runnable runnable) {
+				if (display != null && !display.isDisposed()) {
+					display.asyncExec(runnable);
+				}
+			}
+		});
+		appContext.set(IApplicationContext.class, applicationContext);
+
+		// This context will be used by the injector for its
+		// extended data suppliers
+		ContextInjectionFactory.setDefault(appContext);
+
+		// Get the factory to create DI instances with
+		IContributionFactory factory = appContext.get(IContributionFactory.class);
+
+		// Install the life-cycle manager for this session if there's one
+		// defined
+		String lifeCycleURI = getArgValue(IWorkbench.LIFE_CYCLE_URI_ARG, applicationContext, false);
+		if (lifeCycleURI != null) {
+			lcManager = factory.create(lifeCycleURI, appContext);
+			if (lcManager != null) {
+				// Let the manager manipulate the appContext if desired
+				Object state = ContextInjectionFactory.invoke(lcManager,
+						PostContextCreate.class, appContext, Boolean.TRUE);
+				if (state != null && state instanceof Boolean) {
+					if (!((Boolean) state).booleanValue()) {
+						return null;
+					}
+				}
+			}
+		}
+
+		String forcedPerspectiveId = getArgValue(PERSPECTIVE_ARG_NAME, applicationContext, false);
+		if (forcedPerspectiveId != null) {
+			appContext.set(E4Workbench.FORCED_PERSPECTIVE_ID, forcedPerspectiveId);
+		}
+
+		String showLocation = getLocationFromCommandLine();
+		if (showLocation != null) {
+			appContext.set(E4Workbench.FORCED_SHOW_LOCATION, showLocation);
+		}
+
+		// Create the app model and its context
+		MApplication appModel = loadApplicationModel(applicationContext, appContext);
+		appModel.setContext(appContext);
+
+		// TODO RAP Unsupported
+		// boolean isRtl = ((Window.getDefaultOrientation() & SWT.RIGHT_TO_LEFT)
+		// != 0);
+		boolean isRtl = false;
+		appModel.getTransientData().put(E4Workbench.RTL_MODE, isRtl);
+
+		// for compatibility layer: set the application in the OSGi service
+		// context (see Workbench#getInstance())
+		// TODO: Remove in RAP we have no compat layer
+		// if (!E4Workbench.getServiceContext().containsKey(MApplication.class))
+		// {
+		// // first one wins.
+		// E4Workbench.getServiceContext().set(MApplication.class, appModel);
+		// }
+
+		// Set the app's context after adding itself
+		appContext.set(MApplication.class, appModel);
+
+		// adds basic services to the contexts
+		initializeServices(appModel);
+
+		// let the life cycle manager add to the model
+		if (lcManager != null) {
+			ContextInjectionFactory.invoke(lcManager, ProcessAdditions.class, appContext, null);
+			ContextInjectionFactory.invoke(lcManager, ProcessRemovals.class, appContext, null);
+		}
+
+		// Create the addons
+		IEclipseContext addonStaticContext = EclipseContextFactory.create();
+		for (MAddon addon : appModel.getAddons()) {
+			addonStaticContext.set(MAddon.class, addon);
+			Object obj = factory.create(addon.getContributionURI(), appContext,
+					addonStaticContext);
+			addon.setObject(obj);
+		}
+
+		// Parse out parameters from both the command line and/or the product
+		// definition (if any) and put them in the context
+		String xmiURI = getArgValue(IWorkbench.XMI_URI_ARG, applicationContext, false);
+		appContext.set(IWorkbench.XMI_URI_ARG, xmiURI);
+
+		String cssURI = getArgValue(IWorkbench.CSS_URI_ARG, applicationContext,
+				false);
+		if (cssURI != null) {
+			appContext.set(IWorkbench.CSS_URI_ARG, cssURI);
+		}
+		setCSSContextVariables(applicationContext, appContext);
+
+		String rendererFactoryURI = getArgValue(E4Workbench.RENDERER_FACTORY_URI, applicationContext, false);
+		appContext.set(E4Workbench.RENDERER_FACTORY_URI, rendererFactoryURI);
+
+		// This is a default arg, if missing we use the default rendering engine
+		String presentationURI = getArgValue(IWorkbench.PRESENTATION_URI_ARG, applicationContext, false);
+		if (presentationURI == null) {
+			presentationURI = PartRenderingEngine.engineURI;
+		}
+		appContext.set(IWorkbench.PRESENTATION_URI_ARG, presentationURI);
+
+		// Instantiate the Workbench (which is responsible for
+		// 'running' the UI (if any)...
+		return workbench = new E4Workbench(appModel, appContext) {
+			@Override
+			protected String createId() {
+				return (String) appContext.get(INSTANCEID);
+			}
+		};
+	}
+
+	private void setCSSContextVariables(IApplicationContext applicationContext,
+			IEclipseContext context) {
+		boolean highContrastMode = getApplicationDisplay().getHighContrast();
+
+		String cssURI = highContrastMode ? null : getArgValue(
+				IWorkbench.CSS_URI_ARG, applicationContext, false);
+
+		if (cssURI != null) {
+			context.set(IWorkbench.CSS_URI_ARG, cssURI);
+		}
+
+		String themeId = highContrastMode ? HIGH_CONTRAST_THEME_ID
+				: getArgValue(E4Application.THEME_ID, applicationContext, false);
+
+		if (themeId == null && cssURI == null) {
+			themeId = DEFAULT_THEME_ID;
+		}
+
+		context.set(E4Application.THEME_ID, themeId);
+
+		// validate static CSS URI
+		if (cssURI != null && !cssURI.startsWith("platform:/plugin/")) {
+			System.err
+					.println("Warning. Use the \"platform:/plugin/Bundle-SymbolicName/path/filename.extension\" URI for the  parameter:   "
+							+ IWorkbench.CSS_URI_ARG); //$NON-NLS-1$
+			context.set(E4Application.THEME_ID, cssURI);
+		}
+
+		String cssResourcesURI = getArgValue(IWorkbench.CSS_RESOURCE_URI_ARG, applicationContext, false);
+		context.set(IWorkbench.CSS_RESOURCE_URI_ARG, cssResourcesURI);
+	}
+
+	private MApplication loadApplicationModel(IApplicationContext appContext,
+			IEclipseContext eclipseContext) {
+		MApplication theApp = null;
+
+		Location instanceLocation = WorkbenchSWTActivator.getDefault()
+				.getInstanceLocation();
+
+		URI applicationModelURI = determineApplicationModelURI(appContext);
+		eclipseContext.set(E4Workbench.INITIAL_WORKBENCH_MODEL_URI, applicationModelURI);
+
+		// Save and restore
+		boolean saveAndRestore;
+		String value = getArgValue(IWorkbench.PERSIST_STATE, appContext, false);
+
+		saveAndRestore = value == null || Boolean.parseBoolean(value);
+
+		eclipseContext.set(IWorkbench.PERSIST_STATE,
+				Boolean.valueOf(saveAndRestore));
+
+		// when -data @none or -data @noDefault options
+		if (instanceLocation != null && instanceLocation.getURL() != null) {
+			eclipseContext.set(E4Workbench.INSTANCE_LOCATION, instanceLocation);
+		} else {
+			eclipseContext.set(IWorkbench.PERSIST_STATE, false);
+		}
+
+		// Persisted state
+		boolean clearPersistedState;
+		value = getArgValue(IWorkbench.CLEAR_PERSISTED_STATE, appContext, true);
+		clearPersistedState = value != null && Boolean.parseBoolean(value);
+		eclipseContext.set(IWorkbench.CLEAR_PERSISTED_STATE,
+				Boolean.valueOf(clearPersistedState));
+
+		// Delta save and restore
+		boolean deltaRestore;
+		value = getArgValue(E4Workbench.DELTA_RESTORE, appContext, false);
+		deltaRestore = value == null || Boolean.parseBoolean(value);
+		eclipseContext.set(E4Workbench.DELTA_RESTORE,
+				Boolean.valueOf(deltaRestore));
+
+		String resourceHandler = getArgValue(IWorkbench.MODEL_RESOURCE_HANDLER, appContext, false);
+
+		if (resourceHandler == null) {
+			resourceHandler = "bundleclass://org.eclipse.e4.ui.workbench/"
+					+ ResourceHandler.class.getName();
+		}
+
+		IContributionFactory factory = eclipseContext
+				.get(IContributionFactory.class);
+
+		handler = (IModelResourceHandler) factory.create(resourceHandler,
+				eclipseContext);
+		eclipseContext.set(IModelResourceHandler.class, handler);
+
+		Resource resource = handler.loadMostRecentModel();
+		theApp = (MApplication) resource.getContents().get(0);
+
+		return theApp;
+	}
+
+	/**
+	 * @param appContext
+	 * @return
+	 */
+	private URI determineApplicationModelURI(IApplicationContext appContext) {
+		String appModelPath = getArgValue(IWorkbench.XMI_URI_ARG, appContext, false);
+		if (appModelPath == null || appModelPath.length() == 0) {
+			Bundle brandingBundle = appContext.getBrandingBundle();
+			if (brandingBundle != null)
+				appModelPath = brandingBundle.getSymbolicName() + "/" + E4Application.APPLICATION_MODEL_PATH_DEFAULT;
+			else {
+				Logger logger = new WorkbenchLogger(PLUGIN_ID);
+				logger.error(new Exception(), // log a stack trace for debugging
+						"applicationXMI parameter not set and no branding plugin defined. "); //$NON-NLS-1$
+			}
+		}
+
+		URI applicationModelURI = null;
+
+		// check if the appModelPath is already a platform-URI and if so use it
+		if (URIHelper.isPlatformURI(appModelPath)) {
+			applicationModelURI = URI.createURI(appModelPath, true);
+		} else {
+			applicationModelURI = URI.createPlatformPluginURI(appModelPath, true);
+		}
+		return applicationModelURI;
+
+	}
+
+	/**
+	 * Finds an argument's value in the app's command line arguments, branding,
+	 * and system properties
+	 *
+	 * @param argName
+	 *            the argument name
+	 * @param appContext
+	 *            the application context
+	 * @param singledCmdArgValue
+	 *            whether it's a single-valued argument
+	 * @return the value, or <code>null</code>
+	 */
+	private String getArgValue(String argName, IApplicationContext appContext, boolean singledCmdArgValue) {
+		// Is it in the arg list ?
+		if (argName == null || argName.length() == 0)
+			return null;
+
+		if (singledCmdArgValue) {
+			for (int i = 0; i < args.length; i++) {
+				if (("-" + argName).equals(args[i]))
+					return "true";
+			}
+		} else {
+			for (int i = 0; i < args.length; i++) {
+				if (("-" + argName).equals(args[i]) && i + 1 < args.length)
+					return args[i + 1];
+			}
+		}
+
+		final String brandingProperty = appContext.getBrandingProperty(argName);
+		return brandingProperty == null ? System.getProperty(argName)
+				: brandingProperty;
+	}
+
+	/**
+	 * @return the value of the {@link E4Application#SHOWLOCATION_ARG_NAME
+	 *         showlocation} command line argument, or <code>null</code> if it
+	 *         is not set
+	 */
+	private String getLocationFromCommandLine() {
+		final String fullArgName = "-" + SHOWLOCATION_ARG_NAME;
+		for (int i = 0; i < args.length; i++) {
+			// ignore case for compatibility reasons
+			if (fullArgName.equalsIgnoreCase(args[i])) { // $NON-NLS-1$
+				String name = null;
+				if (args.length > i + 1) {
+					name = args[i + 1];
+				}
+				if (name != null && name.indexOf("-") == -1) { //$NON-NLS-1$
+					return name;
+				}
+				return Platform.getLocation().toOSString();
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void stop() {
+		if (workbench != null) {
+			workbench.close();
+		}
+	}
+
+	// TODO This should go into a different bundle
+	public static IEclipseContext createDefaultHeadlessContext() {
+		IEclipseContext serviceContext = EclipseContextFactory
+				.createServiceContext(WorkbenchSWTActivator.getDefault().getContext());
+
+		IExtensionRegistry registry = RegistryFactory.getRegistry();
+		ExceptionHandler exceptionHandler = new ExceptionHandler();
+		ReflectionContributionFactory contributionFactory = new ReflectionContributionFactory(
+				registry);
+		serviceContext.set(IContributionFactory.class, contributionFactory);
+		serviceContext.set(IExceptionHandler.class, exceptionHandler);
+		serviceContext.set(IExtensionRegistry.class, registry);
+
+		serviceContext.set(Adapter.class, ContextInjectionFactory.make(
+				EclipseAdapter.class, serviceContext));
+
+		// No default log provider available
+		if (serviceContext.get(ILoggerProvider.class) == null) {
+			serviceContext.set(ILoggerProvider.class, ContextInjectionFactory
+					.make(DefaultLoggerProvider.class, serviceContext));
+		}
+
+		return serviceContext;
+	}
+
+	// TODO This should go into a different bundle
+	public static IEclipseContext createDefaultContext() {
+		IEclipseContext serviceContext = createDefaultHeadlessContext();
+		final IEclipseContext appContext = serviceContext
+				.createChild("WorkbenchContext"); //$NON-NLS-1$
+		appContext.set(INSTANCEID, UUID.randomUUID().toString());
+		appContext
+				.set(Logger.class, ContextInjectionFactory.make(
+						WorkbenchLogger.class, appContext));
+
+		appContext.set(EModelService.class, new ModelServiceImpl(appContext));
+
+		appContext.set(EPlaceholderResolver.class, new PlaceholderResolver());
+
+		// setup for commands and handlers
+		appContext.set(IServiceConstants.ACTIVE_PART,
+				new ActivePartLookupFunction());
+
+		appContext.set(IServiceConstants.ACTIVE_SHELL,
+				new ActiveChildLookupFunction(IServiceConstants.ACTIVE_SHELL,
+						E4Workbench.LOCAL_ACTIVE_SHELL));
+
+		appContext.set(IStylingEngine.class, new IStylingEngine() {
+			@Override
+			public void setClassname(Object widget, String classname) {
+			}
+
+			@Override
+			public void setId(Object widget, String id) {
+			}
+
+			@Override
+			public void style(Object widget) {
+			}
+
+			@Override
+			public CSSStyleDeclaration getStyle(Object widget) {
+				return null;
+			}
+
+			@Override
+			public void setClassnameAndId(Object widget, String classname,
+					String id) {
+			}
+		});
+
+		// translation
+		initializeLocalization(appContext);
+
+		// TODO RAP specific stuff
+		appContext.set(SettingStore.class, RWT.getSettingStore());
+
+		return appContext;
+	}
+
+	/**
+	 * Initializes the given context with the locale and the TranslationService
+	 * to use.
+	 *
+	 * @param appContext
+	 *            The application context to which the locale and the
+	 *            TranslationService should be set.
+	 */
+	private static void initializeLocalization(IEclipseContext appContext) {
+		String locale = RWT.getLocale().toString();
+		appContext.set(TranslationService.LOCALE, new Locale(locale));
+		appContext.set(TranslationService.class, TranslationProviderFactory.bundleTranslationService(appContext));
+	}
+
+	/**
+	 * Simplified copy of IDEAplication processing that does not offer to choose
+	 * a workspace location.
+	 */
+	private boolean checkInstanceLocation(Location instanceLocation,
+			Shell shell, IEclipseContext context) {
+
+		// Eclipse has been run with -data @none or -data @noDefault options so
+		// we don't need to validate the location
+		if (instanceLocation == null
+				&& Boolean.FALSE.equals(context.get(IWorkbench.PERSIST_STATE))) {
+			return true;
+		}
+
+		if (instanceLocation == null) {
+			MessageDialog
+					.openError(
+							shell,
+							WorkbenchSWTMessages.IDEApplication_workspaceMandatoryTitle,
+							WorkbenchSWTMessages.IDEApplication_workspaceMandatoryMessage);
+			return false;
+		}
+
+		// -data "/valid/path", workspace already set
+		if (instanceLocation.isSet()) {
+			// make sure the meta data version is compatible (or the user
+			// has
+			// chosen to overwrite it).
+			if (!checkValidWorkspace(shell, instanceLocation.getURL())) {
+				return false;
+			}
+
+			// at this point its valid, so try to lock it and update the
+			// metadata version information if successful
+			try {
+				if (instanceLocation.lock()) {
+					writeWorkspaceVersion();
+					return true;
+				}
+
+				// we failed to create the directory.
+				// Two possibilities:
+				// 1. directory is already in use
+				// 2. directory could not be created
+				File workspaceDirectory = new File(instanceLocation.getURL()
+						.getFile());
+				if (workspaceDirectory.exists()) {
+					MessageDialog
+							.openError(
+									shell,
+									WorkbenchSWTMessages.IDEApplication_workspaceCannotLockTitle,
+									WorkbenchSWTMessages.IDEApplication_workspaceCannotLockMessage);
+				} else {
+					MessageDialog
+							.openError(
+									shell,
+									WorkbenchSWTMessages.IDEApplication_workspaceCannotBeSetTitle,
+									WorkbenchSWTMessages.IDEApplication_workspaceCannotBeSetMessage);
+				}
+			} catch (IOException e) {
+				Logger logger = new WorkbenchLogger(PLUGIN_ID);
+				logger.error(e);
+				MessageDialog.openError(shell,
+						WorkbenchSWTMessages.InternalError, e.getMessage());
+			}
+			return false;
+		}
+		/*
+		 * // -data @noDefault or -data not specified, prompt and set
+		 * ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLoc
+		 * .getDefault());
+		 *
+		 * boolean force = false; while (true) { URL workspaceUrl =
+		 * promptForWorkspace(shell, launchData, force); if (workspaceUrl ==
+		 * null) { return false; }
+		 *
+		 * // if there is an error with the first selection, then force the //
+		 * dialog to open to give the user a chance to correct force = true;
+		 *
+		 * try { // the operation will fail if the url is not a valid //
+		 * instance data area, so other checking is unneeded if
+		 * (instanceLocation.setURL(workspaceUrl, true)) {
+		 * launchData.writePersistedData(); writeWorkspaceVersion(); return
+		 * true; } } catch (IllegalStateException e) { MessageDialog .openError(
+		 * shell, IDEWorkbenchMessages.IDEApplication_workspaceCannotBeSetTitle,
+		 * IDEWorkbenchMessages.IDEApplication_workspaceCannotBeSetMessage);
+		 * return false; }
+		 *
+		 * // by this point it has been determined that the workspace is //
+		 * already in use -- force the user to choose again
+		 * MessageDialog.openError(shell,
+		 * IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
+		 * IDEWorkbenchMessages.IDEApplication_workspaceInUseMessage); }
+		 */
+		return false;
+	}
+
+	/**
+	 * Return true if the argument directory is ok to use as a workspace and
+	 * false otherwise. A version check will be performed, and a confirmation
+	 * box may be displayed on the argument shell if an older version is
+	 * detected.
+	 *
+	 * @return true if the argument URL is ok to use as a workspace and false
+	 *         otherwise.
+	 */
+	private boolean checkValidWorkspace(Shell shell, URL url) {
+		// a null url is not a valid workspace
+		if (url == null) {
+			return false;
+		}
+
+		String version = readWorkspaceVersion(url);
+
+		// if the version could not be read, then there is not any existing
+		// workspace data to trample, e.g., perhaps its a new directory that
+		// is just starting to be used as a workspace
+		if (version == null) {
+			return true;
+		}
+
+		final int ide_version = Integer.parseInt(WORKSPACE_VERSION_VALUE);
+		int workspace_version = Integer.parseInt(version);
+
+		// equality test is required since any version difference (newer
+		// or older) may result in data being trampled
+		if (workspace_version == ide_version) {
+			return true;
+		}
+
+		// At this point workspace has been detected to be from a version
+		// other than the current ide version -- find out if the user wants
+		// to use it anyhow.
+		String title = WorkbenchSWTMessages.IDEApplication_versionTitle;
+		String message = NLS.bind(
+				WorkbenchSWTMessages.IDEApplication_versionMessage,
+				url.getFile());
+
+		MessageBox mbox = new MessageBox(shell, SWT.OK | SWT.CANCEL
+				| SWT.ICON_WARNING | SWT.APPLICATION_MODAL);
+		mbox.setText(title);
+		mbox.setMessage(message);
+		return mbox.open() == SWT.OK;
+	}
+
+	/**
+	 * Look at the argument URL for the workspace's version information. Return
+	 * that version if found and null otherwise.
+	 */
+	private static String readWorkspaceVersion(URL workspace) {
+		File versionFile = getVersionFile(workspace, false);
+		if (versionFile == null || !versionFile.exists()) {
+			return null;
+		}
+
+		try {
+			// Although the version file is not spec'ed to be a Java properties
+			// file, it happens to follow the same format currently, so using
+			// Properties to read it is convenient.
+			Properties props = new Properties();
+			FileInputStream is = new FileInputStream(versionFile);
+			try {
+				props.load(is);
+			} finally {
+				is.close();
+			}
+
+			return props.getProperty(WORKSPACE_VERSION_KEY);
+		} catch (IOException e) {
+			Logger logger = new WorkbenchLogger(PLUGIN_ID);
+			logger.error(e);
+			return null;
+		}
+	}
+
+	/**
+	 * Write the version of the metadata into a known file overwriting any
+	 * existing file contents. Writing the version file isn't really crucial, so
+	 * the function is silent about failure
+	 */
+	private static void writeWorkspaceVersion() {
+		Location instanceLoc = Platform.getInstanceLocation();
+		if (instanceLoc == null || instanceLoc.isReadOnly()) {
+			return;
+		}
+
+		File versionFile = getVersionFile(instanceLoc.getURL(), true);
+		if (versionFile == null) {
+			return;
+		}
+
+		OutputStream output = null;
+		try {
+			String versionLine = WORKSPACE_VERSION_KEY + '='
+					+ WORKSPACE_VERSION_VALUE;
+
+			output = new FileOutputStream(versionFile);
+			output.write(versionLine.getBytes("UTF-8")); //$NON-NLS-1$
+		} catch (IOException e) {
+			Logger logger = new WorkbenchLogger(PLUGIN_ID);
+			logger.error(e);
+		} finally {
+			try {
+				if (output != null) {
+					output.close();
+				}
+			} catch (IOException e) {
+				// do nothing
+			}
+		}
+	}
+
+	/**
+	 * The version file is stored in the metadata area of the workspace. This
+	 * method returns an URL to the file or null if the directory or file does
+	 * not exist (and the create parameter is false).
+	 *
+	 * @param create
+	 *            If the directory and file does not exist this parameter
+	 *            controls whether it will be created.
+	 * @return An url to the file or null if the version file does not exist or
+	 *         could not be created.
+	 */
+	private static File getVersionFile(URL workspaceUrl, boolean create) {
+		if (workspaceUrl == null) {
+			return null;
+		}
+
+		try {
+			// make sure the directory exists
+			File metaDir = new File(workspaceUrl.getPath(), METADATA_FOLDER);
+			if (!metaDir.exists() && (!create || !metaDir.mkdir())) {
+				return null;
+			}
+
+			// make sure the file exists
+			File versionFile = new File(metaDir, VERSION_FILENAME);
+			if (!versionFile.exists()
+					&& (!create || !versionFile.createNewFile())) {
+				return null;
+			}
+
+			return versionFile;
+		} catch (IOException e) {
+			// cannot log because instance area has not been set
+			return null;
+		}
+	}
+
+	static final private String CONTEXT_INITIALIZED = "org.eclipse.ui.contextInitialized";
+
+	static public void initializeServices(MApplication appModel) {
+		IEclipseContext appContext = appModel.getContext();
+		// make sure we only add trackers once
+		if (appContext.containsKey(CONTEXT_INITIALIZED))
+			return;
+		appContext.set(CONTEXT_INITIALIZED, "true");
+		initializeApplicationServices(appContext);
+		List<MWindow> windows = appModel.getChildren();
+		for (MWindow childWindow : windows) {
+			initializeWindowServices(childWindow);
+		}
+		((EObject) appModel).eAdapters().add(new AdapterImpl() {
+			@Override
+			public void notifyChanged(Notification notification) {
+				if (notification.getFeatureID(MApplication.class) != UiPackageImpl.ELEMENT_CONTAINER__CHILDREN)
+					return;
+				if (notification.getEventType() != Notification.ADD)
+					return;
+				MWindow childWindow = (MWindow) notification.getNewValue();
+				initializeWindowServices(childWindow);
+			}
+		});
+	}
+
+	static public void initializeApplicationServices(IEclipseContext appContext) {
+		final IEclipseContext theContext = appContext;
+		// we add a special tracker to bring up current selection from
+		// the active window to the application level
+		appContext.runAndTrack(new RunAndTrack() {
+			public boolean changed(IEclipseContext context) {
+				IEclipseContext activeChildContext = context.getActiveChild();
+				if (activeChildContext != null) {
+					Object selection = activeChildContext
+							.get(IServiceConstants.ACTIVE_SELECTION);
+					theContext.set(IServiceConstants.ACTIVE_SELECTION,
+							selection);
+				}
+				return true;
+			}
+		});
+
+		// we create a selection service handle on every node that we are asked
+		// about as handle needs to know its context
+		appContext.set(ESelectionService.class.getName(),
+				new ContextFunction() {
+					@Override
+					public Object compute(IEclipseContext context,
+							String contextKey) {
+						return ContextInjectionFactory.make(
+								SelectionServiceImpl.class, context);
+					}
+				});
+	}
+
+	static public void initializeWindowServices(MWindow childWindow) {
+		IEclipseContext windowContext = childWindow.getContext();
+		initWindowContext(windowContext);
+		// Mostly MWindow contexts are lazily created by renderers and is not
+		// set at this point.
+		((EObject) childWindow).eAdapters().add(new AdapterImpl() {
+			@Override
+			public void notifyChanged(Notification notification) {
+				if (notification.getFeatureID(MWindow.class) != BasicPackageImpl.WINDOW__CONTEXT)
+					return;
+				IEclipseContext windowContext = (IEclipseContext) notification
+						.getNewValue();
+				initWindowContext(windowContext);
+			}
+		});
+	}
+
+	static private void initWindowContext(IEclipseContext windowContext) {
+		if (windowContext == null)
+			return;
+		SelectionAggregator selectionAggregator = ContextInjectionFactory.make(
+				SelectionAggregator.class, windowContext);
+		windowContext.set(SelectionAggregator.class, selectionAggregator);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Testable.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Testable.java
new file mode 100644
index 0000000..73f059e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Testable.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench.swt;
+
+
+/**
+ * The Workbench's testable object facade to a test harness.
+ * 
+ * @since 3.0
+ */
+public class E4Testable {
+}
+// extends TestableObject {
+//
+// private Display display;
+//
+// private IWorkbench workbench;
+//
+// private boolean oldAutomatedMode;
+//
+// private boolean oldIgnoreErrors;
+//
+// /**
+// * Constructs a new workbench testable object.
+// */
+// public E4Testable() {
+// // do nothing
+// }
+//
+// /**
+// * Initializes the workbench testable with the display and workbench, and
+// * notifies all listeners that the tests can be run.
+// *
+// * @param display
+// * the display
+// * @param workbench
+// * the workbench
+// */
+// public void init(Display display, IWorkbench workbench) {
+// Assert.isNotNull(display);
+// Assert.isNotNull(workbench);
+// this.display = display;
+// this.workbench = workbench;
+// if (getTestHarness() != null) {
+// // don't use a job, since tests often wait for all jobs to complete
+// // before proceeding
+// Runnable runnable = new Runnable() {
+// @Override
+// public void run() {
+// // Some tests (notably the startup performance tests) do not
+// // want to wait for early startup.
+// // Allow this to be disabled by specifying the system
+// // property: org.eclipse.ui.testsWaitForEarlyStartup=false
+// // For details, see bug 94129 [Workbench] Performance test
+// // regression caused by workbench harness change
+//					if (!"false".equalsIgnoreCase(System.getProperty("org.eclipse.ui.testsWaitForEarlyStartup"))) { //$NON-NLS-1$ //$NON-NLS-2$
+// waitForEarlyStartup();
+// }
+// getTestHarness().runTests();
+// }
+// };
+//			new Thread(runnable, "WorkbenchTestable").start(); //$NON-NLS-1$
+// }
+// }
+//
+// /**
+// * Waits for the early startup job to complete.
+// */
+// private void waitForEarlyStartup() {
+// try {
+// Job.getJobManager().join("earlyStartup", null);
+// } catch (OperationCanceledException e) {
+// // ignore
+// } catch (InterruptedException e) {
+// // ignore
+// }
+// }
+//
+// /**
+// * The <code>WorkbenchTestable</code> implementation of this
+// * <code>TestableObject</code> method ensures that the workbench has been
+// * set.
+// */
+// @Override
+// public void testingStarting() {
+// Assert.isNotNull(workbench);
+// oldAutomatedMode = ErrorDialog.AUTOMATED_MODE;
+// ErrorDialog.AUTOMATED_MODE = true;
+// oldIgnoreErrors = SafeRunnable.getIgnoreErrors();
+// SafeRunnable.setIgnoreErrors(true);
+// }
+//
+// /**
+// * The <code>WorkbenchTestable</code> implementation of this
+// * <code>TestableObject</code> method flushes the event queue, runs the test
+// * in a <code>syncExec</code>, then flushes the event queue again.
+// */
+// @Override
+// public void runTest(Runnable testRunnable) {
+// Assert.isNotNull(workbench);
+// display.syncExec(testRunnable);
+// }
+//
+// /**
+// * The <code>WorkbenchTestable</code> implementation of this
+// * <code>TestableObject</code> method flushes the event queue, then closes
+// * the workbench.
+// */
+// @Override
+// public void testingFinished() {
+// // force events to be processed, and ensure the close is done in the UI
+// // thread
+// display.syncExec(new Runnable() {
+// @Override
+// public void run() {
+// Assert.isTrue(workbench.close());
+// }
+// });
+// ErrorDialog.AUTOMATED_MODE = oldAutomatedMode;
+// SafeRunnable.setIgnoreErrors(oldIgnoreErrors);
+// }
+// }
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/FaderAnimationFeedback.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/FaderAnimationFeedback.java
new file mode 100644
index 0000000..dde2ff0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/FaderAnimationFeedback.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Creates an animation effect where the Shell's image is captured and
+ * over-lain (in its own shell) on top of the real one. This image
+ * masks the changes to the 'real' shell and then the covering image
+ * fades to transparent, revealing the new state.
+ * 
+ * This provides a nice cross-fade effect for operations like a
+ * perspective change (where the overall effect on the shell is large.
+ * 
+ * @since 3.3
+ *
+ */
+public class FaderAnimationFeedback extends	AnimationFeedbackBase {
+	private Image backingStore;
+
+	public FaderAnimationFeedback(Shell parentShell) {
+		super(parentShell);
+	}
+
+	@Override
+	public void dispose() {
+		super.dispose();
+
+		if (!backingStore.isDisposed())
+			backingStore.dispose();
+	}
+
+	@Override
+	public void initialize(AnimationEngine engine) {
+		// Rectangle psRect = getBaseShell().getBounds();
+		// getAnimationShell().setBounds(psRect);
+		//
+		// // Capture the background image
+		// Display display = getBaseShell().getDisplay();
+		// backingStore = new Image(display, psRect);
+		// GC gc = new GC(display);
+		// // gc.copyArea(backingStore, psRect.x, psRect.y);
+		// gc.copyArea(backingStore, psRect.x, psRect.y);
+		// gc.dispose();
+		//
+		// getAnimationShell().setAlpha(254);
+		// getAnimationShell().setBackgroundImage(backingStore);
+		// getAnimationShell().setVisible(true);
+	}
+
+	@Override
+	public void renderStep(AnimationEngine engine) {
+		getAnimationShell().setAlpha((int) (255 - (engine.amount()*255)));
+	}
+	
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/GenTopic.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/GenTopic.java
new file mode 100644
index 0000000..b56e550
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/GenTopic.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.internal.workbench.swt;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import org.eclipse.e4.ui.model.application.commands.impl.CommandsPackageImpl;
+import org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+
+public class GenTopic implements IApplication {
+
+	@Override
+	public Object start(IApplicationContext context) throws Exception {
+		try {
+			processLiterals(CommandsPackageImpl.Literals.class);
+			processLiterals(BasicPackageImpl.Literals.class);
+			processLiterals(ApplicationPackageImpl.Literals.class);
+			processLiterals(AdvancedPackageImpl.Literals.class);
+			processLiterals(org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl.Literals.class);
+			processLiterals(UiPackageImpl.Literals.class);
+			processLiterals(MenuPackageImpl.Literals.class);
+
+			// Add a newline to the last generated line
+			System.out.println();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return IApplication.EXIT_OK;
+	}
+
+	private void processLiterals(Class<?> literals)
+			throws IllegalArgumentException, IllegalAccessException {
+		Field[] fields = literals.getFields();
+		Map<String, EClass> classes = new TreeMap<String, EClass>();
+		for (int i = 0; i < fields.length; i++) {
+			Object value = fields[i].get(null);
+			if (value instanceof EClass) {
+				classes.put(((EClass) value).getName(), (EClass) value);
+			}
+		}
+		for (EClass ec : classes.values()) {
+			processEClass(ec);
+		}
+	}
+
+	private static final String interfaceDeclaration = "\n\tpublic static interface %s {";
+	private static final String deprecatedTopicDeclaration = "\n\n\t@Deprecated\n\tpublic static final String TOPIC = \"org/eclipse/e4/ui/model/%s/%s\"; //$NON-NLS-1$\n";
+	private static final String topicAllDeclaration = "\n\tpublic static final String TOPIC_ALL = \"org/eclipse/e4/ui/model/%s/%s/*\"; //$NON-NLS-1$";
+	private static final String topicAttributeDeclaration = "\n\tpublic static final String TOPIC_%S = \"org/eclipse/e4/ui/model/%s/%s/%s/*\"; //$NON-NLS-1$";
+	private static final String attributeDeclaration = "\n\tpublic static final String %S = \"%s\"; //$NON-NLS-1$";
+
+	private void processEClass(EClass eClass) {
+		EList<EStructuralFeature> features = eClass.getEStructuralFeatures();
+		if (features.isEmpty()) {
+			return;
+		}
+		String pkgName = eClass.getEPackage().getName();
+		String className = eClass.getName();
+		System.out.print("\r\r\t@SuppressWarnings(\"javadoc\")");
+		System.out.print(String.format(interfaceDeclaration, className));
+		System.out.print("\n\n\t//Topics that can be subscribed to");
+		System.out.print(String.format(deprecatedTopicDeclaration, pkgName,
+				className));
+		System.out
+				.print(String.format(topicAllDeclaration, pkgName, className));
+
+		Set<String> names = new TreeSet<String>();
+		for (EStructuralFeature feature : features) {
+			names.add(feature.getName());
+		}
+
+		for (String name : names) {
+			System.out.print(String.format(topicAttributeDeclaration, name,
+					pkgName, className, name));
+		}
+
+		System.out.print("\n"); //$NON-NLS-1$
+		System.out
+				.print("\n\t//Attributes that can be tested in event handlers");
+		for (String name : names) {
+			System.out.print(String.format(attributeDeclaration, name, name));
+		}
+
+		System.out.print("\n\t}"); //$NON-NLS-1$
+	}
+
+	@Override
+	public void stop() {
+		// nothing to do
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java
new file mode 100644
index 0000000..0182309
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/IEventLoopAdvisor.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.internal.workbench.swt;
+
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Allow client applications to interact with the event loop.
+ */
+public interface IEventLoopAdvisor {
+	/**
+	 * Performs arbitrary work or yields when there are no events to be
+	 * processed.
+	 * <p>
+	 * This method is called when there are currently no more events on the
+	 * queue to be processed at the moment.
+	 * </p>
+	 * <p>
+	 * Clients must not call this method directly (although super calls are
+	 * okay). The default implementation yields until new events enter the
+	 * queue. Subclasses may override or extend this method. It is generally a
+	 * bad idea to override with an empty method.
+	 * </p>
+	 *
+	 * @param display
+	 *            the main display of the rendering UI
+	 */
+	public void eventLoopIdle(Display display);
+
+	/**
+	 * Performs arbitrary actions when the event loop crashes (the code that
+	 * handles a UI event throws an exception that is not caught).
+	 * <p>
+	 * This method is called when the code handling a UI event throws an
+	 * exception. In a perfectly functioning application, this method would
+	 * never be called. In practice, it comes into play when there are bugs in
+	 * the code that trigger unchecked runtime exceptions. It is also activated
+	 * when the system runs short of memory, etc. Fatal errors (ThreadDeath) are
+	 * not passed on to this method, as there is nothing that could be done.
+	 * </p>
+	 * <p>
+	 * Clients must not call this method directly (although super calls are
+	 * okay). The default implementation logs the problem so that it does not go
+	 * unnoticed. Subclasses may override or extend this method. It is generally
+	 * a bad idea to override with an empty method, and you should be especially
+	 * careful when handling Errors.
+	 * </p>
+	 *
+	 * @param exception
+	 *            the uncaught exception that was thrown inside the UI event
+	 *            loop
+	 */
+	public void eventLoopException(Throwable exception);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuService.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuService.java
new file mode 100644
index 0000000..b01b571
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuService.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench.swt;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.services.EMenuService;
+import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+
+public class MenuService implements EMenuService {
+	@Inject
+	private MPart myPart;
+
+	@Override
+	public boolean registerContextMenu(Object parent, String menuId) {
+		if (!(parent instanceof Control)) {
+			return false;
+		}
+		Control parentControl = (Control) parent;
+		for (MMenu mmenu : myPart.getMenus()) {
+			if (menuId.equals(mmenu.getElementId())
+					&& mmenu instanceof MPopupMenu) {
+				Menu menu = registerMenu(parentControl, (MPopupMenu) mmenu,
+						myPart.getContext());
+				if (menu != null) {
+					parentControl.setMenu(menu);
+					return true;
+				}
+				return false;
+			}
+		}
+		return false;
+	}
+
+	public static Menu registerMenu(final Control parentControl, final MPopupMenu mmenu, IEclipseContext context) {
+		if (mmenu.getWidget() != null) {
+			return (Menu) mmenu.getWidget();
+		}
+		// we need to delegate to the renderer so that it "processes" the
+		// MenuManager correctly
+		IRendererFactory rendererFactory = context.get(IRendererFactory.class);
+		AbstractPartRenderer renderer = rendererFactory.getRenderer(mmenu, parentControl);
+
+		IEclipseContext popupContext = context.createChild("popup:" + mmenu.getElementId());
+		mmenu.setContext(popupContext);
+		Object widget = renderer.createWidget(mmenu, parentControl);
+		if (!(widget instanceof Menu)) {
+			return null;
+		}
+		renderer.bindWidget(mmenu, widget);
+		renderer.hookControllerLogic(mmenu);
+
+		// Process its internal structure through the renderer that created
+		// it
+		Object castObject = mmenu;
+		@SuppressWarnings("unchecked")
+		MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) castObject;
+		renderer.processContents(container);
+
+		// Allow a final chance to set up
+		renderer.postProcess(mmenu);
+
+		// Now that we have a widget let the parent (if any) know
+		MElementContainer<MUIElement> parentElement = mmenu.getParent();
+		if (parentElement != null) {
+			AbstractPartRenderer parentRenderer = rendererFactory.getRenderer(parentElement, null);
+			if (parentRenderer != null) {
+				parentRenderer.childRendered(parentElement, mmenu);
+			}
+		}
+
+		return (Menu) widget;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuServiceCreationFunction.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuServiceCreationFunction.java
new file mode 100644
index 0000000..f0178e1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/MenuServiceCreationFunction.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.internal.workbench.swt;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.InjectionException;
+
+public class MenuServiceCreationFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		try {
+			return ContextInjectionFactory.make(MenuService.class, context);
+		} catch (InjectionException ie) {
+			// we won't report this at the moment.
+			System.err.println("MenuService: " + context + ": " + ie);
+		}
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
new file mode 100644
index 0000000..0230e5c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/PartRenderingEngine.java
@@ -0,0 +1,1496 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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.internal.workbench.swt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.InjectionException;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.extensions.EventTopic;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.core.services.statusreporter.StatusReporter;
+import org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher;
+//import org.eclipse.e4.ui.css.core.util.impl.resources.OSGiResourceLocator;
+//import org.eclipse.e4.ui.css.swt.dom.WidgetElement;
+//import org.eclipse.e4.ui.css.swt.engine.CSSSWTEngineImpl;
+// import org.eclipse.e4.ui.css.swt.helpers.EclipsePreferencesHelper;
+//import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
+//import org.eclipse.e4.ui.css.swt.theme.IThemeManager;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.di.PersistState;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.MContribution;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MGenericStack;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+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.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.jface.bindings.keys.SWTKeySupport;
+import org.eclipse.jface.bindings.keys.formatting.KeyFormatterFactory;
+import org.eclipse.jface.databinding.swt.SWTObservables;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+//import org.eclipse.ui.testing.TestableObject;
+import org.osgi.service.event.Event;
+
+public class PartRenderingEngine implements IPresentationEngine {
+	public static final String EARLY_STARTUP_HOOK = "runEarlyStartup";
+
+	public static final String engineURI = "bundleclass://org.eclipse.e4.ui.workbench.swt/"
+			+ "org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine";
+
+	private static final String defaultFactoryUrl = "bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/"
+			+ "org.eclipse.e4.ui.workbench.renderers.swt.WorkbenchRendererFactory";
+	private String factoryUrl;
+
+	IRendererFactory curFactory = null;
+
+	private Map<String, AbstractPartRenderer> customRendererMap = new HashMap<String, AbstractPartRenderer>();
+
+	org.eclipse.swt.widgets.Listener keyListener;
+
+	@Inject
+	@Optional
+	private void subscribeTopicToBeRendered(@EventTopic(UIEvents.UIElement.TOPIC_TOBERENDERED) Event event) {
+
+		MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		MElementContainer<?> parent = changedElement.getParent();
+
+		// Handle Detached Windows
+		if (parent == null) {
+			parent = (MElementContainer<?>) ((EObject) changedElement).eContainer();
+		}
+
+		// menus are not handled here... ??
+		if (parent instanceof MMenu) {
+			return;
+		}
+
+		// If the parent isn't visible we don't care (The application is
+		// never rendered)
+		boolean okToRender = parent instanceof MApplication || parent.getWidget() != null;
+
+		if (changedElement.isToBeRendered() && okToRender) {
+			Activator.trace(Policy.DEBUG_RENDERER, "visible -> true", null); //$NON-NLS-1$
+
+			// Note that the 'createGui' protocol calls 'childAdded'
+			Object w = createGui(changedElement);
+			if (w instanceof Control && !(w instanceof Shell)) {
+				fixZOrder(changedElement);
+			}
+		} else {
+			Activator.trace(Policy.DEBUG_RENDERER, "visible -> false", null); //$NON-NLS-1$
+
+			// Ensure that the element about to be removed is not the
+			// selected element
+			if (parent.getSelectedElement() == changedElement)
+				parent.setSelectedElement(null);
+
+			if (okToRender) {
+				// Un-maximize the element before tearing it down
+				if (changedElement.getTags().contains(MAXIMIZED)) {
+					changedElement.getTags().remove(MAXIMIZED);
+				}
+
+				// Note that the 'removeGui' protocol calls 'childRemoved'
+				removeGui(changedElement);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeVisibilityHandler(@EventTopic(UIEvents.UIElement.TOPIC_VISIBLE) Event event) {
+
+		MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
+		MUIElement parent = changedElement.getParent();
+		if (parent == null) {
+			parent = (MUIElement) ((EObject) changedElement).eContainer();
+			if (parent == null) {
+				return;
+			}
+		}
+
+		AbstractPartRenderer renderer = (AbstractPartRenderer) parent.getRenderer();
+		if (renderer == null || parent instanceof MToolBar) {
+			return;
+		}
+
+		// Re-parent the control based on the visible state
+		if (changedElement.isVisible()) {
+			if (changedElement.isToBeRendered()) {
+				if (changedElement.getWidget() instanceof Control) {
+					// Ensure that the control is under its 'real' parent if
+					// it's visible
+					Composite realComp = (Composite) renderer.getUIContainer(changedElement);
+					Control ctrl = (Control) changedElement.getWidget();
+					ctrl.setParent(realComp);
+					fixZOrder(changedElement);
+				}
+
+				if (parent instanceof MElementContainer<?>) {
+					@SuppressWarnings("unchecked")
+					MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) parent;
+					renderer.childRendered(container, changedElement);
+				}
+			}
+		} else {
+			// Put the control under the 'limbo' shell
+			if (changedElement.getWidget() instanceof Control) {
+				Control ctrl = (Control) changedElement.getWidget();
+
+				if (!(ctrl instanceof Shell)) {
+					ctrl.getShell().layout(new Control[] { ctrl }, SWT.DEFER);
+				}
+
+				ctrl.setParent(getLimboShell());
+			}
+
+			if (parent instanceof MElementContainer<?>) {
+				@SuppressWarnings("unchecked")
+				MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) parent;
+				renderer.hideChild(container, changedElement);
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeTrimHandler(@EventTopic(UIEvents.TrimmedWindow.TOPIC_TRIMBARS) Event event) {
+
+		Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(changedObj instanceof MTrimmedWindow)) {
+			return;
+		}
+
+		MTrimmedWindow window = (MTrimmedWindow) changedObj;
+		if (window.getWidget() == null) {
+			return;
+		}
+
+		if (UIEvents.isADD(event)) {
+			for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
+				MUIElement added = (MUIElement) o;
+				if (added.isToBeRendered()) {
+					createGui(added, window.getWidget(), window.getContext());
+				}
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
+				MUIElement removed = (MUIElement) o;
+				if (removed.getRenderer() != null) {
+					removeGui(removed);
+				}
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeChildrenHandler(@EventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
+
+		Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+		if (!(changedObj instanceof MElementContainer<?>)) {
+			return;
+		}
+
+		@SuppressWarnings("unchecked")
+		MElementContainer<MUIElement> changedElement = (MElementContainer<MUIElement>) changedObj;
+		boolean isApplication = changedObj instanceof MApplication;
+
+		boolean menuChild = changedObj instanceof MMenu;
+		// If the parent isn't in the UI then who cares?
+		AbstractPartRenderer renderer = getRendererFor(changedElement);
+		if ((!isApplication && renderer == null) || menuChild) {
+			return;
+		}
+
+		if (UIEvents.isADD(event)) {
+			Activator.trace(Policy.DEBUG_RENDERER, "Child Added", null); //$NON-NLS-1$
+			for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
+				MUIElement added = (MUIElement) o;
+
+				// OK, we have a new -visible- part we either have to create
+				// it or host it under the correct parent. Note that we
+				// explicitly do *not* render non-selected elements in
+				// stacks (to support lazy loading).
+				boolean isStack = changedObj instanceof MGenericStack<?>;
+				boolean hasWidget = added.getWidget() != null;
+				boolean isSelected = added == changedElement.getSelectedElement();
+				boolean renderIt = !isStack || hasWidget || isSelected;
+				if (renderIt) {
+					// NOTE: createGui will call 'childAdded' if successful
+					Object w = createGui(added);
+					if (w instanceof Control && !(w instanceof Shell)) {
+						final Control ctrl = (Control) w;
+						fixZOrder(added);
+						if (!ctrl.isDisposed()) {
+							ctrl.getShell().layout(new Control[] { ctrl }, SWT.DEFER);
+						}
+					}
+				} else {
+					if (renderer != null && added.isToBeRendered()) {
+						renderer.childRendered(changedElement, added);
+					}
+				}
+
+				// If the element being added is a placeholder, check to see
+				// if
+				// it's 'globally visible' and, if so, remove all other
+				// 'local' placeholders referencing the same element.
+				int newLocation = modelService.getElementLocation(added);
+				if (newLocation == EModelService.IN_SHARED_AREA || newLocation == EModelService.OUTSIDE_PERSPECTIVE) {
+					MWindow topWin = modelService.getTopLevelWindowFor(added);
+					modelService.hideLocalPlaceholders(topWin, null);
+				}
+			}
+		} else if (UIEvents.isREMOVE(event)) {
+			Activator.trace(Policy.DEBUG_RENDERER, "Child Removed", null); //$NON-NLS-1$
+			for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.OLD_VALUE)) {
+				MUIElement removed = (MUIElement) o;
+				// Removing invisible elements is a NO-OP as far as the
+				// renderer is concerned
+				if (!removed.isToBeRendered()) {
+					continue;
+				}
+
+				if (removed.getWidget() instanceof Control) {
+					Control ctrl = (Control) removed.getWidget();
+					ctrl.setLayoutData(null);
+					ctrl.getParent().layout(new Control[] { ctrl }, SWT.CHANGED | SWT.DEFER);
+				}
+
+				// Ensure that the element about to be removed is not the
+				// selected element
+				if (changedElement.getSelectedElement() == removed) {
+					changedElement.setSelectedElement(null);
+				}
+
+				if (renderer != null) {
+					renderer.hideChild(changedElement, removed);
+				}
+			}
+		}
+	}
+
+	@Inject
+	@Optional
+	private void subscribeWindowsHandler(@EventTopic(UIEvents.Window.TOPIC_WINDOWS) Event event) {
+
+		subscribeChildrenHandler(event);
+	}
+
+	@Inject
+	@Optional
+	private void subscribePerspectiveWindowsHandler(@EventTopic(UIEvents.Perspective.TOPIC_WINDOWS) Event event) {
+		subscribeChildrenHandler(event);
+	}
+
+	// FIXME RAP unsupported
+	// @Inject
+	// @Optional
+	// private void
+	// subscribeCssThemeChanged(@EventTopic(IThemeEngine.Events.THEME_CHANGED)
+	// Event event) {
+	// cssThemeChangedHandler.handleEvent(event);
+	// }
+
+	// private StylingPreferencesHandler cssThemeChangedHandler;
+
+	private IEclipseContext appContext;
+
+	protected Shell testShell;
+
+	protected MApplication theApp;
+
+	@Inject
+	@Optional
+	protected IEventBroker eventBroker;
+
+	@Inject
+	EModelService modelService;
+
+	@Inject
+	protected Logger logger;
+
+	private Shell limbo;
+
+	private MUIElement removeRoot = null;
+
+	@Inject
+	public PartRenderingEngine(
+			@Named(E4Workbench.RENDERER_FACTORY_URI) @Optional String factoryUrl) {
+		if (factoryUrl == null) {
+			factoryUrl = defaultFactoryUrl;
+		}
+		this.factoryUrl = factoryUrl;
+	}
+
+	protected void fixZOrder(MUIElement element) {
+		MElementContainer<MUIElement> parent = element.getParent();
+		if (parent == null) {
+			Object econtainer = ((EObject) element).eContainer();
+			if (econtainer instanceof MElementContainer<?>) {
+				@SuppressWarnings("unchecked")
+				MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) econtainer;
+				parent = container;
+			}
+		}
+		if (parent == null || !(element.getWidget() instanceof Control)) {
+			return;
+		}
+
+		Control elementCtrl = (Control) element.getWidget();
+		Control prevCtrl = null;
+		for (MUIElement kid : parent.getChildren()) {
+			if (kid == element) {
+				if (prevCtrl != null) {
+					elementCtrl.moveBelow(prevCtrl);
+				} else {
+					elementCtrl.moveAbove(null);
+				}
+				break;
+			} else if (kid.getWidget() instanceof Control && kid.isVisible()) {
+				prevCtrl = (Control) kid.getWidget();
+			}
+		}
+
+		Object widget = parent.getWidget();
+		if (widget instanceof Composite) {
+			Composite composite = (Composite) widget;
+			if (composite.getShell() == elementCtrl.getShell()) {
+				Composite temp = elementCtrl.getParent();
+				while (temp != composite) {
+					if (temp == null) {
+						return;
+					}
+					temp = temp.getParent();
+				}
+
+				composite.layout(true, true);
+			}
+		}
+	}
+
+	/**
+	 * Initialize a part renderer from the extension point.
+	 *
+	 * @param context
+	 *            the context for the part factories
+	 */
+	@PostConstruct
+	void initialize(IEclipseContext context) {
+		this.appContext = context;
+
+		// initialize the correct key-binding display formatter
+		KeyFormatterFactory.setDefault(SWTKeySupport
+				.getKeyFormatterForPlatform());
+
+		// Add the renderer to the context
+		context.set(IPresentationEngine.class.getName(), this);
+
+		IRendererFactory factory = null;
+		IContributionFactory contribFactory = context
+				.get(IContributionFactory.class);
+		try {
+			factory = (IRendererFactory) contribFactory.create(factoryUrl,
+					context);
+		} catch (Exception e) {
+			logger.warn(e, "Could not create rendering factory");
+		}
+
+		// Try to load the default one
+		if (factory == null) {
+			try {
+				factory = (IRendererFactory) contribFactory.create(
+						defaultFactoryUrl, context);
+			} catch (Exception e) {
+				logger.error(e, "Could not create default rendering factory");
+			}
+		}
+
+		if (factory == null) {
+			throw new IllegalStateException(
+					"Could not create any rendering factory. Aborting ...");
+		}
+
+		curFactory = factory;
+		context.set(IRendererFactory.class, curFactory);
+
+		// cssThemeChangedHandler = new
+		// StylingPreferencesHandler(context.get(Display.class));
+	}
+
+	private static void populateModelInterfaces(MContext contextModel,
+			IEclipseContext context, Class<?>[] interfaces) {
+		for (Class<?> intf : interfaces) {
+			Activator.trace(Policy.DEBUG_CONTEXTS,
+					"Adding " + intf.getName() + " for " //$NON-NLS-1$ //$NON-NLS-2$
+							+ contextModel.getClass().getName(), null);
+			context.set(intf.getName(), contextModel);
+
+			populateModelInterfaces(contextModel, context, intf.getInterfaces());
+		}
+	}
+
+	private String getContextName(MUIElement element) {
+		StringBuilder builder = new StringBuilder(element.getClass()
+				.getSimpleName());
+		String elementId = element.getElementId();
+		if (elementId != null && elementId.length() != 0) {
+			builder.append(" (").append(elementId).append(") ");
+		}
+		builder.append("Context");
+		return builder.toString();
+	}
+
+	@Override
+	public Object createGui(final MUIElement element,
+			final Object parentWidget, final IEclipseContext parentContext) {
+		final Object[] gui = { null };
+		// wrap the handling in a SafeRunner so that exceptions do not prevent
+		// the renderer from processing other elements
+		SafeRunner.run(new ISafeRunnable() {
+			@Override
+			public void handleException(Throwable e) {
+				if (e instanceof Error) {
+					// errors are deadly, we shouldn't ignore these
+					throw (Error) e;
+				}
+
+				// log exceptions otherwise
+				if (logger != null) {
+					String message = "Exception occurred while rendering: {0}"; //$NON-NLS-1$
+					logger.error(e, NLS.bind(message, element));
+				}
+			}
+
+			public void run() throws Exception {
+				gui[0] = safeCreateGui(element, parentWidget, parentContext);
+			}
+		});
+		return gui[0];
+	}
+
+	public Object safeCreateGui(MUIElement element, Object parentWidget,
+			IEclipseContext parentContext) {
+		if (!element.isToBeRendered())
+			return null;
+
+		// no creates while processing a remove
+		if (removeRoot != null) {
+			return null;
+		}
+
+		Object currentWidget = element.getWidget();
+		if (currentWidget != null) {
+			if (currentWidget instanceof Control) {
+				Control control = (Control) currentWidget;
+				// make sure the control is visible
+				MUIElement elementParent = element.getParent();
+				if (!(element instanceof MPlaceholder)
+						|| !(elementParent instanceof MPartStack))
+					control.setVisible(true);
+
+				if (parentWidget instanceof Composite) {
+					Composite currentParent = control.getParent();
+					if (currentParent != parentWidget) {
+						// check if the original parent was a tab folder
+						if (currentParent instanceof CTabFolder) {
+							CTabFolder folder = (CTabFolder) currentParent;
+							// if we used to be the tab folder's top right
+							// control, unset it
+							if (folder.getTopRight() == control) {
+								folder.setTopRight(null);
+							}
+						}
+
+						// the parents are different so we should reparent it
+						control.setParent((Composite) parentWidget);
+					}
+				}
+			}
+
+			// Reparent the context (or the kid's context)
+			if (element instanceof MContext) {
+				IEclipseContext ctxt = ((MContext) element).getContext();
+				if (ctxt != null)
+					ctxt.setParent(parentContext);
+			} else {
+				List<MContext> childContexts = modelService.findElements(
+						element, null, MContext.class, null);
+				for (MContext c : childContexts) {
+					// Ensure that we only reset the context of our direct
+					// children
+					MUIElement kid = (MUIElement) c;
+					MUIElement parent = kid.getParent();
+					if (parent == null && kid.getCurSharedRef() != null)
+						parent = kid.getCurSharedRef().getParent();
+					if (!(element instanceof MPlaceholder) && parent != element)
+						continue;
+
+					if (c.getContext() != null
+							&& c.getContext().getParent() != parentContext) {
+						c.getContext().setParent(parentContext);
+					}
+				}
+			}
+
+			// Now that we have a widget let the parent (if any) know
+			if (element.getParent() instanceof MUIElement) {
+				MElementContainer<MUIElement> parentElement = element
+						.getParent();
+				AbstractPartRenderer parentRenderer = getRendererFor(parentElement);
+				if (parentRenderer != null)
+					parentRenderer.childRendered(parentElement, element);
+			}
+			return element.getWidget();
+		}
+
+		if (element instanceof MContext) {
+			MContext ctxt = (MContext) element;
+			// Assert.isTrue(ctxt.getContext() == null,
+			// "Before rendering Context should be null");
+			if (ctxt.getContext() == null) {
+				IEclipseContext lclContext = parentContext
+						.createChild(getContextName(element));
+				populateModelInterfaces(ctxt, lclContext, element.getClass()
+						.getInterfaces());
+				ctxt.setContext(lclContext);
+
+				// System.out.println("New Context: " + lclContext.toString()
+				// + " parent: " + parentContext.toString());
+
+				// make sure the context knows about these variables that have
+				// been defined in the model
+				for (String variable : ctxt.getVariables()) {
+					lclContext.declareModifiable(variable);
+				}
+
+				Map<String, String> props = ctxt.getProperties();
+				for (String key : props.keySet()) {
+					lclContext.set(key, props.get(key));
+				}
+			}
+		}
+
+		// We check the widget again since it could be created by some UI event.
+		// See Bug 417399
+		if (element.getWidget() != null) {
+			return safeCreateGui(element, parentWidget, parentContext);
+		}
+
+		// Create a control appropriate to the part
+		Object newWidget = createWidget(element, parentWidget);
+
+		// Remember that we've created the control
+		if (newWidget != null) {
+			AbstractPartRenderer renderer = getRendererFor(element);
+
+			// Have the renderer hook up any widget specific listeners
+			renderer.hookControllerLogic(element);
+
+			// Process its internal structure through the renderer that created
+			// it
+			if (element instanceof MElementContainer) {
+				renderer.processContents((MElementContainer<MUIElement>) element);
+			}
+
+			// Allow a final chance to set up
+			renderer.postProcess(element);
+
+			// Now that we have a widget let the parent (if any) know
+			if (element.getParent() instanceof MUIElement) {
+				MElementContainer<MUIElement> parentElement = element
+						.getParent();
+				AbstractPartRenderer parentRenderer = getRendererFor(parentElement);
+				if (parentRenderer != null)
+					parentRenderer.childRendered(parentElement, element);
+			}
+		} else {
+			// failed to create the widget, dispose its context if necessary
+			if (element instanceof MContext) {
+				MContext ctxt = (MContext) element;
+				IEclipseContext lclContext = ctxt.getContext();
+				if (lclContext != null) {
+					lclContext.dispose();
+					ctxt.setContext(null);
+				}
+			}
+		}
+
+		return newWidget;
+	}
+
+	private IEclipseContext getContext(MUIElement parent) {
+		if (parent instanceof MContext) {
+			return ((MContext) parent).getContext();
+		}
+		return modelService.getContainingContext(parent);
+	}
+
+	@Override
+	public Object createGui(final MUIElement element) {
+		final Object[] gui = { null };
+		// wrap the handling in a SafeRunner so that exceptions do not prevent
+		// the renderer from processing other elements
+		SafeRunner.run(new ISafeRunnable() {
+			public void handleException(Throwable e) {
+				if (e instanceof Error) {
+					// errors are deadly, we shouldn't ignore these
+					throw (Error) e;
+				}
+
+				// log exceptions otherwise
+				if (logger != null) {
+					String message = "Exception occurred while rendering: {0}"; //$NON-NLS-1$
+					logger.error(e, NLS.bind(message, element));
+				}
+			}
+
+			public void run() throws Exception {
+				gui[0] = safeCreateGui(element);
+			}
+		});
+		return gui[0];
+	}
+
+	private Object safeCreateGui(MUIElement element) {
+		// Obtain the necessary parent widget
+		Object parent = null;
+		MUIElement parentME = element.getParent();
+		if (parentME == null)
+			parentME = (MUIElement) ((EObject) element).eContainer();
+		if (parentME != null) {
+			AbstractPartRenderer renderer = getRendererFor(parentME);
+			if (renderer != null) {
+				if (!element.isVisible()) {
+					parent = getLimboShell();
+				} else {
+					parent = renderer.getUIContainer(element);
+				}
+			}
+		}
+
+		// Obtain the necessary parent context
+		IEclipseContext parentContext = null;
+		if (element.getCurSharedRef() != null) {
+			MPlaceholder ph = element.getCurSharedRef();
+			parentContext = getContext(ph.getParent());
+		} else if (parentContext == null && element.getParent() != null) {
+			parentContext = getContext(element.getParent());
+		} else if (parentContext == null && element.getParent() == null) {
+			parentContext = getContext((MUIElement) ((EObject) element)
+					.eContainer());
+		}
+
+		return safeCreateGui(element, parent, parentContext);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see
+	 * org.eclipse.e4.ui.workbench.IPresentationEngine#focusGui(org.eclipse.
+	 * e4.ui.model.application.ui.MUIElement)
+	 */
+	@Override
+	public void focusGui(MUIElement element) {
+		AbstractPartRenderer renderer = (AbstractPartRenderer) element
+				.getRenderer();
+		if (renderer == null || element.getWidget() == null)
+			return;
+
+		Object implementation = element instanceof MContribution ? ((MContribution) element)
+				.getObject() : null;
+
+		// If there is no class to call @Focus on then revert to the default
+		if (implementation == null) {
+			renderer.forceFocus(element);
+			return;
+		}
+
+		try {
+			IEclipseContext context = getContext(element);
+			Object defaultValue = new Object();
+			Object returnValue = ContextInjectionFactory.invoke(implementation,
+					Focus.class, context, defaultValue);
+			if (returnValue == defaultValue) {
+				// No @Focus method, force the focus
+				renderer.forceFocus(element);
+			}
+		} catch (InjectionException e) {
+			log("Failed to grant focus to element", "Failed to grant focus to element ({0})", //$NON-NLS-1$ //$NON-NLS-2$
+					element.getElementId(), e);
+		} catch (RuntimeException e) {
+			log("Failed to grant focus to element via DI", //$NON-NLS-1$
+					"Failed to grant focus via DI to element ({0})", element.getElementId(), e); //$NON-NLS-1$
+		}
+	}
+
+	private void log(String unidentifiedMessage, String identifiedMessage,
+			String id, Exception e) {
+		if (id == null || id.length() == 0) {
+			logger.error(e, unidentifiedMessage);
+		} else {
+			logger.error(e, NLS.bind(identifiedMessage, id));
+		}
+	}
+
+	private Shell getLimboShell() {
+		if (limbo == null) {
+			limbo = new Shell(Display.getCurrent(), SWT.NONE);
+			limbo.setText("PartRenderingEngine's limbo"); //$NON-NLS-1$ // just for debugging, not shown anywhere
+
+			// Place the limbo shell 'off screen'
+			limbo.setLocation(0, 10000);
+
+			limbo.setBackgroundMode(SWT.INHERIT_DEFAULT);
+			limbo.setData(ShellActivationListener.DIALOG_IGNORE_KEY,
+					Boolean.TRUE);
+		}
+		return limbo;
+	}
+
+	/**
+	 * @param element
+	 */
+	@Override
+	public void removeGui(final MUIElement element) {
+		// wrap the handling in a SafeRunner so that exceptions do not prevent
+		// the menu from being shown
+		SafeRunner.run(new ISafeRunnable() {
+			public void handleException(Throwable e) {
+				if (e instanceof Error) {
+					// errors are deadly, we shouldn't ignore these
+					throw (Error) e;
+				}
+
+				// log exceptions otherwise
+				if (logger != null) {
+					String message = "Exception occurred while unrendering: {0}"; //$NON-NLS-1$
+					logger.error(e, NLS.bind(message, element));
+				}
+			}
+
+			public void run() throws Exception {
+				safeRemoveGui(element);
+			}
+		});
+	}
+
+	private void safeRemoveGui(MUIElement element) {
+		if (removeRoot == null)
+			removeRoot = element;
+
+		// We call 'hideChild' *before* checking if the actual element
+		// has been rendered in order to pick up cases of 'lazy loading'
+		MUIElement parent = element.getParent();
+		AbstractPartRenderer parentRenderer = parent != null ? getRendererFor(parent)
+				: null;
+		if (parentRenderer != null) {
+			parentRenderer.hideChild(element.getParent(), element);
+		}
+
+		AbstractPartRenderer renderer = getRendererFor(element);
+
+		// If the element hasn't been rendered then this is a NO-OP
+		if (renderer != null) {
+
+			if (element instanceof MElementContainer<?>) {
+				MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
+				MUIElement selectedElement = container.getSelectedElement();
+				List<MUIElement> children = container.getChildren();
+				for (MUIElement child : children) {
+					// remove stuff in the "back" first
+					if (child != selectedElement) {
+						removeGui(child);
+					}
+				}
+
+				if (selectedElement != null
+						&& children.contains(selectedElement)) {
+					// now remove the selected element
+					removeGui(selectedElement);
+				}
+			}
+
+			if (element instanceof MPerspective) {
+				MPerspective perspective = (MPerspective) element;
+				for (MWindow subWindow : perspective.getWindows()) {
+					removeGui(subWindow);
+				}
+			} else if (element instanceof MWindow) {
+				MWindow window = (MWindow) element;
+				for (MWindow subWindow : window.getWindows()) {
+					removeGui(subWindow);
+				}
+
+				if (window instanceof MTrimmedWindow) {
+					MTrimmedWindow trimmedWindow = (MTrimmedWindow) window;
+					for (MUIElement trimBar : trimmedWindow.getTrimBars()) {
+						removeGui(trimBar);
+					}
+				}
+			}
+
+			if (element instanceof MContribution) {
+				MContribution contribution = (MContribution) element;
+				Object client = contribution.getObject();
+				IEclipseContext parentContext = renderer.getContext(element);
+				if (parentContext != null && client != null) {
+					try {
+						ContextInjectionFactory.invoke(client,
+								PersistState.class, parentContext, null);
+					} catch (Exception e) {
+						if (logger != null) {
+							logger.error(e);
+						}
+					}
+				}
+			}
+
+			renderer.disposeWidget(element);
+
+			// unset the client object
+			if (element instanceof MContribution) {
+				MContribution contribution = (MContribution) element;
+				Object client = contribution.getObject();
+				IEclipseContext parentContext = renderer.getContext(element);
+				if (parentContext != null && client != null) {
+					try {
+						ContextInjectionFactory.uninject(client, parentContext);
+					} catch (Exception e) {
+						if (logger != null) {
+							logger.error(e);
+						}
+					}
+				}
+				contribution.setObject(null);
+			}
+
+			// dispose the context
+			if (element instanceof MContext) {
+				clearContext((MContext) element);
+			}
+		}
+
+		if (removeRoot == element)
+			removeRoot = null;
+	}
+
+	private void clearContext(MContext contextME) {
+		MContext ctxt = (MContext) contextME;
+		IEclipseContext lclContext = ctxt.getContext();
+		if (lclContext != null) {
+			IEclipseContext parentContext = lclContext.getParent();
+			IEclipseContext child = parentContext != null ? parentContext
+					.getActiveChild() : null;
+			if (child == lclContext) {
+				child.deactivate();
+			}
+
+			ctxt.setContext(null);
+			lclContext.dispose();
+		}
+	}
+
+	protected Object createWidget(MUIElement element, Object parent) {
+		AbstractPartRenderer renderer = getRenderer(element, parent);
+		if (renderer != null) {
+			// Remember which renderer is responsible for this widget
+			element.setRenderer(renderer);
+			Object newWidget = renderer.createWidget(element, parent);
+			if (newWidget != null) {
+				renderer.bindWidget(element, newWidget);
+				return newWidget;
+			}
+		}
+
+		return null;
+	}
+
+	private AbstractPartRenderer getRenderer(MUIElement uiElement, Object parent) {
+		// Is there a custom renderer defined ?
+		String customURI = uiElement.getPersistedState().get(
+				IPresentationEngine.CUSTOM_RENDERER_KEY);
+		if (customURI != null) {
+			if (customRendererMap.get(customURI) instanceof AbstractPartRenderer)
+				return customRendererMap.get(customURI);
+
+			IEclipseContext owningContext = modelService
+					.getContainingContext(uiElement);
+			IContributionFactory contributionFactory = (IContributionFactory) owningContext
+					.get(IContributionFactory.class.getName());
+			Object customRenderer = contributionFactory.create(customURI,
+					owningContext);
+			if (customRenderer instanceof AbstractPartRenderer) {
+				customRendererMap.put(customURI,
+						(AbstractPartRenderer) customRenderer);
+				return (AbstractPartRenderer) customRenderer;
+			}
+		}
+
+		// If not then use the default renderer
+		return curFactory.getRenderer(uiElement, parent);
+	}
+
+	protected AbstractPartRenderer getRendererFor(MUIElement element) {
+		return (AbstractPartRenderer) element.getRenderer();
+	}
+
+	@Override
+	public Object run(final MApplicationElement uiRoot,
+			final IEclipseContext runContext) {
+		final Display display;
+		if (runContext.get(Display.class) != null) {
+			display = runContext.get(Display.class);
+		} else {
+			display = Display.getDefault();
+			runContext.set(Display.class, display);
+		}
+		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
+
+			@Override
+			public void run() {
+				initializeStyling(display, runContext);
+
+				// Register an SWT resource handler
+				runContext.set(IResourceUtilities.class.getName(),
+						new ResourceUtility());
+
+				// set up the keybinding manager
+				KeyBindingDispatcher dispatcher = (KeyBindingDispatcher) ContextInjectionFactory
+						.make(KeyBindingDispatcher.class, runContext);
+				runContext.set(KeyBindingDispatcher.class.getName(), dispatcher);
+				keyListener = dispatcher.getKeyDownFilter();
+				display.addFilter(SWT.KeyDown, keyListener);
+				display.addFilter(SWT.Traverse, keyListener);
+
+				// Show the initial UI
+
+				// Create a 'limbo' shell (used to host controls that shouldn't
+				// be in the current layout)
+				Shell limbo = getLimboShell();
+				runContext.set("limbo", limbo);
+
+				// HACK!! we should loop until the display gets disposed...
+				// ...then we listen for the last 'main' window to get disposed
+				// and dispose the Display
+				testShell = null;
+				theApp = null;
+				boolean spinOnce = true;
+				if (uiRoot instanceof MApplication) {
+					ShellActivationListener shellDialogListener = new ShellActivationListener(
+							(MApplication) uiRoot);
+					display.addFilter(SWT.Activate, shellDialogListener);
+					display.addFilter(SWT.Deactivate, shellDialogListener);
+					spinOnce = false; // loop until the app closes
+					theApp = (MApplication) uiRoot;
+					// long startTime = System.currentTimeMillis();
+					MWindow selected = theApp.getSelectedElement();
+					if (selected == null) {
+						for (MWindow window : theApp.getChildren()) {
+							createGui(window);
+						}
+					} else {
+						// render the selected one first
+						createGui(selected);
+						for (MWindow window : theApp.getChildren()) {
+							if (selected != window) {
+								createGui(window);
+							}
+						}
+					}
+					// long endTime = System.currentTimeMillis();
+					// System.out.println("Render: " + (endTime - startTime));
+					// tell the app context we are starting so the splash is
+					// torn down
+					IApplicationContext ac = appContext
+							.get(IApplicationContext.class);
+					if (ac != null) {
+						ac.applicationRunning();
+						if (eventBroker != null)
+							eventBroker.post(
+									UIEvents.UILifeCycle.APP_STARTUP_COMPLETE,
+									theApp);
+					}
+				} else if (uiRoot instanceof MUIElement) {
+					if (uiRoot instanceof MWindow) {
+						testShell = (Shell) createGui((MUIElement) uiRoot);
+					} else {
+						// Special handling for partial models (for testing...)
+						testShell = new Shell(display, SWT.SHELL_TRIM);
+						createGui((MUIElement) uiRoot, testShell, null);
+					}
+				}
+
+				// allow any early startup extensions to run
+				Runnable earlyStartup = (Runnable) runContext
+						.get(EARLY_STARTUP_HOOK);
+				if (earlyStartup != null) {
+					earlyStartup.run();
+				}
+				// TODO RAP unsupported
+				// TestableObject testableObject = (TestableObject) runContext
+				// .get(TestableObject.class.getName());
+				// if (testableObject instanceof E4Testable) {
+				// ((E4Testable) testableObject).init(display,
+				// (IWorkbench) runContext.get(IWorkbench.class
+				// .getName()));
+				// }
+
+				IEventLoopAdvisor advisor = runContext.getActiveLeaf().get(
+						IEventLoopAdvisor.class);
+				if (advisor == null) {
+					advisor = new IEventLoopAdvisor() {
+						@Override
+						public void eventLoopIdle(Display display) {
+							display.sleep();
+						}
+
+						@Override
+						public void eventLoopException(Throwable exception) {
+							StatusReporter statusReporter = (StatusReporter) appContext
+									.get(StatusReporter.class.getName());
+							if (statusReporter != null) {
+								statusReporter.show(StatusReporter.ERROR,
+										"Internal Error", exception);
+							} else {
+								if (logger != null) {
+									logger.error(exception);
+								}
+							}
+						}
+					};
+				}
+				// Spin the event loop until someone disposes the display
+				while (((testShell != null && !testShell.isDisposed()) || (theApp != null && someAreVisible(theApp
+						.getChildren()))) && !display.isDisposed()) {
+					try {
+						if (!display.readAndDispatch()) {
+							runContext.processWaiting();
+							if (spinOnce)
+								return;
+							advisor.eventLoopIdle(display);
+						}
+					} catch (ThreadDeath th) {
+						throw th;
+					} catch (Exception ex) {
+						handle(ex, advisor);
+					} catch (Error err) {
+						handle(err, advisor);
+					}
+				}
+				if (!spinOnce) {
+					cleanUp();
+				}
+			}
+
+			private void handle(Throwable ex, IEventLoopAdvisor advisor) {
+				try {
+					advisor.eventLoopException(ex);
+				} catch (Throwable t) {
+					if (t instanceof ThreadDeath) {
+						throw (ThreadDeath) t;
+					}
+
+					// couldn't handle the exception, print to console
+					t.printStackTrace();
+				}
+			}
+		});
+
+		return IApplication.EXIT_OK;
+	}
+
+	protected boolean someAreVisible(List<MWindow> windows) {
+		// This method is called from the event dispatch loop, so the
+		// following optimization is in order...
+
+		// Ideally, we'd just do:
+		// for (MWindow win : theApp.getChildren()) {
+		// But this creates an iterator (which must be GC'd)
+		// at every call. The code below creates no objects.
+		final int limit = windows.size();
+		for (int i = 0; i < limit; i++) {
+			final MWindow win = windows.get(i);
+			// Note: Removed isVisible test, as this should have
+			// no impact on the whether the event loop
+			// terminates - non-visible windows still exists
+			// and can receive events.
+			// Note: isToBeRendered() == true => win.getWidget() != null
+			// but I'm not sure whether there is latency between setting
+			// toBeRendered and the creation of the widget. So, keeping
+			// both tests seems prudent.
+			if (win.isToBeRendered() && win.getWidget() != null) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public void stop() {
+		// FIXME Without this call the test-suite fails
+		cleanUp();
+		if (theApp != null) {
+			for (MWindow window : theApp.getChildren()) {
+				if (window.getWidget() != null) {
+					removeGui(window);
+				}
+			}
+		} else if (testShell != null && !testShell.isDisposed()) {
+			Object model = testShell.getData(AbstractPartRenderer.OWNING_ME);
+			if (model instanceof MUIElement) {
+				removeGui((MUIElement) model);
+			} else {
+				testShell.close();
+			}
+		}
+	}
+
+	/*
+	 * There are situations where this is called more than once until we know
+	 * why this is needed we should make this safe for multiple calls
+	 */
+	private void cleanUp() {
+		if (keyListener != null) {
+			Display display = Display.getDefault();
+			if (!display.isDisposed()) {
+				display.removeFilter(SWT.KeyDown, keyListener);
+				display.removeFilter(SWT.Traverse, keyListener);
+				keyListener = null;
+			}
+		}
+	}
+
+	public static void initializeStyling(Display display,
+			IEclipseContext appContext) {
+		CSSRenderingUtils cssUtils = ContextInjectionFactory.make(
+				CSSRenderingUtils.class, appContext);
+		appContext.set(CSSRenderingUtils.class, cssUtils);
+	}
+
+	// FIXME RAP unsupported
+	// public static void initializeStyling(Display display,
+	// IEclipseContext appContext) {
+	// String cssTheme = (String) appContext.get(E4Application.THEME_ID);
+	// String cssURI = (String) appContext.get(IWorkbench.CSS_URI_ARG);
+	// if ("none".equals(cssTheme)) {
+	// appContext.set(IStylingEngine.SERVICE_NAME, new IStylingEngine() {
+	// @Override
+	// public void setClassname(Object widget, String classname) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// }
+	//
+	// @Override
+	// public void setId(Object widget, String id) {
+	// WidgetElement.setID((Widget) widget, id);
+	// }
+	//
+	// @Override
+	// public void style(Object widget) {
+	// }
+	//
+	// @Override
+	// public CSSStyleDeclaration getStyle(Object widget) {
+	// return null;
+	// }
+	//
+	// @Override
+	// public void setClassnameAndId(Object widget, String classname,
+	// String id) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// WidgetElement.setID((Widget) widget, id);
+	// }
+	// });
+	// } else if (cssTheme != null) {
+	// final IThemeEngine themeEngine = createThemeEngine(display,
+	// appContext);
+	// String cssResourcesURI = (String) appContext
+	// .get(IWorkbench.CSS_RESOURCE_URI_ARG);
+	//
+	// // Create the OSGi resource locator
+	// if (cssResourcesURI != null) {
+	// // TODO: Should this be set through an extension as well?
+	// themeEngine.registerResourceLocator(new OSGiResourceLocator(
+	// cssResourcesURI));
+	// }
+	//
+	// appContext.set(IStylingEngine.SERVICE_NAME, new IStylingEngine() {
+	// @Override
+	// public void setClassname(Object widget, String classname) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// themeEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public void setId(Object widget, String id) {
+	// WidgetElement.setID((Widget) widget, id);
+	// themeEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public void style(Object widget) {
+	// themeEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public CSSStyleDeclaration getStyle(Object widget) {
+	// return themeEngine.getStyle(widget);
+	// }
+	//
+	// @Override
+	// public void setClassnameAndId(Object widget, String classname,
+	// String id) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// WidgetElement.setID((Widget) widget, id);
+	// themeEngine.applyStyles(widget, true);
+	// }
+	// });
+	//
+	// setCSSTheme(display, themeEngine, cssTheme);
+	//
+	// } else if (cssURI != null) {
+	// String cssResourcesURI = (String) appContext
+	// .get(IWorkbench.CSS_RESOURCE_URI_ARG);
+	// final CSSSWTEngineImpl cssEngine = new CSSSWTEngineImpl(display,
+	// true);
+	// WidgetElement.setEngine(display, cssEngine);
+	// if (cssResourcesURI != null) {
+	// cssEngine.getResourcesLocatorManager().registerResourceLocator(
+	// new OSGiResourceLocator(cssResourcesURI.toString()));
+	// }
+	// // FIXME: is this needed?
+	//			display.setData("org.eclipse.e4.ui.css.context", appContext); //$NON-NLS-1$
+	// appContext.set(IStylingEngine.SERVICE_NAME, new IStylingEngine() {
+	// @Override
+	// public void setClassname(Object widget, String classname) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// cssEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public void setId(Object widget, String id) {
+	// WidgetElement.setID((Widget) widget, id);
+	// cssEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public void style(Object widget) {
+	// cssEngine.applyStyles(widget, true);
+	// }
+	//
+	// @Override
+	// public CSSStyleDeclaration getStyle(Object widget) {
+	// Element e = cssEngine.getCSSElementContext(widget)
+	// .getElement();
+	// if (e == null) {
+	// return null;
+	// }
+	// return cssEngine.getViewCSS().getComputedStyle(e, null);
+	// }
+	//
+	// @Override
+	// public void setClassnameAndId(Object widget, String classname,
+	// String id) {
+	// WidgetElement.setCSSClass((Widget) widget, classname);
+	// WidgetElement.setID((Widget) widget, id);
+	// cssEngine.applyStyles(widget, true);
+	// }
+	// });
+	//
+	// URL url;
+	// InputStream stream = null;
+	// try {
+	// url = FileLocator.resolve(new URL(cssURI));
+	// stream = url.openStream();
+	// cssEngine.parseStyleSheet(stream);
+	// } catch (MalformedURLException e) {
+	// // TODO Auto-generated catch block
+	// e.printStackTrace();
+	// } catch (IOException e) {
+	// // TODO Auto-generated catch block
+	// e.printStackTrace();
+	// } finally {
+	// if (stream != null) {
+	// try {
+	// stream.close();
+	// } catch (IOException e) {
+	// // TODO Auto-generated catch block
+	// e.printStackTrace();
+	// }
+	// }
+	// }
+	//
+	// Shell[] shells = display.getShells();
+	// for (Shell s : shells) {
+	// try {
+	// s.setRedraw(false);
+	// s.reskin(SWT.ALL);
+	// cssEngine.applyStyles(s, true);
+	// } catch (Exception e) {
+	// // TODO Auto-generated catch block
+	// e.printStackTrace();
+	// } finally {
+	// s.setRedraw(true);
+	// }
+	// }
+	// }
+	//
+	// CSSRenderingUtils cssUtils = ContextInjectionFactory.make(
+	// CSSRenderingUtils.class, appContext);
+	// appContext.set(CSSRenderingUtils.class, cssUtils);
+	// }
+	//
+	// private static IThemeEngine createThemeEngine(Display display,
+	// IEclipseContext appContext) {
+	// // Store the app context
+	// IContributionFactory contribution = (IContributionFactory) appContext
+	// .get(IContributionFactory.class.getName());
+	// IEclipseContext cssContext = EclipseContextFactory.create();
+	// cssContext.set(IContributionFactory.class.getName(), contribution);
+	//		display.setData("org.eclipse.e4.ui.css.context", cssContext); //$NON-NLS-1$
+	//
+	// IThemeManager mgr = appContext.get(IThemeManager.class);
+	// IThemeEngine themeEngine = mgr.getEngineForDisplay(display);
+	//
+	// appContext.set(IThemeEngine.class.getName(), themeEngine);
+	// return themeEngine;
+	// }
+	//
+	// private static void setCSSTheme(Display display, IThemeEngine
+	// themeEngine,
+	// String cssTheme) {
+	// if (display.getHighContrast()) {
+	// themeEngine.setTheme(cssTheme, false);
+	// } else {
+	// themeEngine.restore(cssTheme);
+	// }
+	// }
+	//
+	// public static class StylingPreferencesHandler implements EventHandler {
+	// private HashSet<IEclipsePreferences> prefs = null;
+	//
+	// public StylingPreferencesHandler(Display display) {
+	// if (display != null) {
+	// display.addListener(SWT.Dispose,
+	// createOnDisplayDisposedListener());
+	// }
+	// }
+	//
+	// protected Listener createOnDisplayDisposedListener() {
+	// return new Listener() {
+	// @Override
+	// public void handleEvent(org.eclipse.swt.widgets.Event event) {
+	// resetOverriddenPreferences();
+	// }
+	// };
+	// }
+	//
+	// @Override
+	// public void handleEvent(Event event) {
+	// resetOverriddenPreferences();
+	// overridePreferences(getThemeEngine(event));
+	// }
+	//
+	// protected void resetOverriddenPreferences() {
+	// for (IEclipsePreferences preferences : getPreferences()) {
+	// resetOverriddenPreferences(preferences);
+	// }
+	// }
+	//
+	// protected void resetOverriddenPreferences(
+	// IEclipsePreferences preferences) {
+	// for (String name : getOverriddenPropertyNames(preferences)) {
+	// preferences.remove(name);
+	// }
+	// removeOverriddenPropertyNames(preferences);
+	// }
+	//
+	// protected void removeOverriddenPropertyNames(
+	// IEclipsePreferences preferences) {
+	// EclipsePreferencesHelper.removeOverriddenPropertyNames(preferences);
+	// }
+	//
+	// protected List<String> getOverriddenPropertyNames(
+	// IEclipsePreferences preferences) {
+	// return EclipsePreferencesHelper
+	// .getOverriddenPropertyNames(preferences);
+	// }
+	//
+	// protected Set<IEclipsePreferences> getPreferences() {
+	// if (prefs == null) {
+	// prefs = new HashSet<IEclipsePreferences>();
+	// PlatformAdmin admin = WorkbenchSWTActivator.getDefault()
+	// .getPlatformAdmin();
+	//
+	// State state = admin.getState(false);
+	// BundleDescription[] bundles = state.getBundles();
+	//
+	// for (BundleDescription desc : bundles) {
+	// if (desc.getName() != null) {
+	// prefs.add(InstanceScope.INSTANCE.getNode(desc.getName()));
+	// }
+	// }
+	// }
+	// return prefs;
+	// }
+	//
+	// private void overridePreferences(IThemeEngine themeEngine) {
+	// if (themeEngine != null) {
+	// for (IEclipsePreferences preferences : getPreferences()) {
+	// themeEngine.applyStyles(preferences, false);
+	// }
+	// }
+	// }
+	//
+	// private IThemeEngine getThemeEngine(Event event) {
+	// return (IThemeEngine) event
+	// .getProperty(IThemeEngine.Events.THEME_ENGINE);
+	// }
+	// }
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/Policy.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/Policy.java
new file mode 100644
index 0000000..e77bf14
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/Policy.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench.swt;
+
+public class Policy {
+	public static final String DEBUG_RENDERER = "/trace/renderer"; //$NON-NLS-1$
+	public static final String MENUS = "/trace/menus"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ResourceUtility.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ResourceUtility.java
new file mode 100644
index 0000000..68e8e63
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ResourceUtility.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 BestSolution.at 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:
+ *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     Boris Bokowski, IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+public class ResourceUtility implements ISWTResourceUtilities {
+
+	public ResourceUtility() {
+		super();
+	}
+
+	@Override
+	public ImageDescriptor imageDescriptorFromURI(URI iconPath) {
+		try {
+			return ImageDescriptor.createFromURL(new URL(iconPath.toString()));
+		} catch (MalformedURLException e) {
+			System.err.println("iconURI \"" + iconPath.toString()
+					+ "\" is invalid, no image will be shown");
+			return null;
+		}
+	}
+
+	@Override
+	public Image adornImage(Image toAdorn, Image adornment) {
+		// if (toAdorn == null)
+		// return null;
+		// if (adornment == null)
+		// return toAdorn;
+		// Rectangle adornmentSize = adornment.getBounds();
+		//
+		// Image adornedImage = new Image(toAdorn.getDevice(), 16, 16);
+		// GC gc = new GC(adornedImage);
+		// gc.drawImage(toAdorn, 0, 0);
+		// // For now assume top-right
+		// gc.drawImage(adornment, 16 - adornmentSize.width, 0);
+		// gc.dispose();
+		//
+		// return adornedImage;
+		return toAdorn;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/SelectionAdapterFactory.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/SelectionAdapterFactory.java
new file mode 100644
index 0000000..3805f22
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/SelectionAdapterFactory.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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
+ *     Simon Scholz <simon.scholz@vogella.com> - Bug 460405
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.expressions.ICountable;
+import org.eclipse.core.expressions.IIterable;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * Adapts ISelection instances to either IIterable or ICountable. For use with
+ * core expressions.
+ *
+ * @since 3.3
+ */
+public class SelectionAdapterFactory implements IAdapterFactory {
+
+	private static final ICountable ICOUNT_0 = new ICountable() {
+		@Override
+		public int count() {
+			return 0;
+		}
+	};
+
+	private static final ICountable ICOUNT_1 = new ICountable() {
+		@Override
+		public int count() {
+			return 1;
+		}
+	};
+
+	private static final IIterable<?> ITERATE_EMPTY = new IIterable<Object>() {
+		@Override
+		public Iterator<Object> iterator() {
+			return Collections.emptyList().iterator();
+		}
+	};
+
+	/**
+	 * The classes we can adapt to.
+	 */
+	private static final Class<?>[] CLASSES = new Class[] { IIterable.class, ICountable.class };
+
+	@Override
+	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
+		if (adaptableObject instanceof ISelection) {
+			if (adapterType == IIterable.class) {
+				return adapterType.cast(iterable((ISelection) adaptableObject));
+			} else if (adapterType == ICountable.class) {
+				return adapterType.cast(countable((ISelection) adaptableObject));
+			}
+		}
+		return null;
+	}
+
+	private IIterable<?> iterable(final ISelection sel) {
+		if (sel.isEmpty()) {
+			return ITERATE_EMPTY;
+		}
+		if (sel instanceof IStructuredSelection) {
+			return new IIterable<Object>() {
+				@Override
+				public Iterator<Object> iterator() {
+					return ((IStructuredSelection) sel).iterator();
+				}
+			};
+		}
+		final List<Object> list = Arrays.asList(new Object[] { sel });
+		return new IIterable<Object>() {
+
+			@Override
+			public Iterator<Object> iterator() {
+				return list.iterator();
+			}
+		};
+	}
+
+	private ICountable countable(final ISelection sel) {
+		if (sel.isEmpty()) {
+			return ICOUNT_0;
+		}
+		if (sel instanceof IStructuredSelection) {
+			final IStructuredSelection ss = (IStructuredSelection) sel;
+			return new ICountable() {
+				@Override
+				public int count() {
+					return ss.size();
+				}
+			};
+		}
+		return ICOUNT_1;
+	}
+
+	@Override
+	public Class<?>[] getAdapterList() {
+		return CLASSES;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ShellActivationListener.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ShellActivationListener.java
new file mode 100644
index 0000000..16820cd
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/ShellActivationListener.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench.swt;
+
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.services.EContextService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * An SWT listener for listening for activation events of shells that aren't
+ * associated with an MWindow.
+ */
+public class ShellActivationListener implements Listener {
+
+	/**
+	 * A string key for use with a shell's keyed data to determine whether
+	 * activation events of that shell should be ignored by this listener. The
+	 * retrieved data of this string key must either be <code>null</code> or be
+	 * of type <code>Boolean</code>.
+	 */
+	public static final String DIALOG_IGNORE_KEY = "org.eclipse.e4.ui.ignoreDialog"; //$NON-NLS-1$
+
+	/**
+	 * A string key for use with a shell's keyed data to retrieve the top level
+	 * eclipse context that the shell is supposed to represent.
+	 */
+	private static final String ECLIPSE_CONTEXT_SHELL_CONTEXT = "org.eclipse.e4.ui.shellContext"; //$NON-NLS-1$
+
+	private MApplication application;
+
+	ShellActivationListener(MApplication application) {
+		this.application = application;
+	}
+
+	@Override
+	public void handleEvent(Event event) {
+		if (!(event.widget instanceof Shell)) {
+			return;
+		}
+
+		Shell shell = (Shell) event.widget;
+		Object obj = shell.getData(AbstractPartRenderer.OWNING_ME);
+		if (obj instanceof MWindow) {
+			processWindow(event, shell, (MWindow) obj);
+			return;
+		}
+
+		obj = shell.getData(DIALOG_IGNORE_KEY);
+		if (obj instanceof Boolean && ((Boolean) obj).booleanValue()) {
+			return;
+		}
+
+		switch (event.type) {
+		case SWT.Activate:
+			activate(shell);
+			break;
+		case SWT.Deactivate:
+			deactivate(shell);
+			break;
+		}
+	}
+
+	private void processWindow(Event event, Shell shell, MWindow window) {
+		switch (event.type) {
+		case SWT.Activate:
+			final IEclipseContext local = window.getContext();
+			WorkbenchSWTActivator.trace("/trace/workbench",
+					"setting mwindow context " + local, null);
+			// record this shell's context
+			shell.setData(ECLIPSE_CONTEXT_SHELL_CONTEXT, local);
+
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					// reconstruct the active chain for this mwindow
+					local.activateBranch();
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					WorkbenchSWTActivator.trace("/trace/workbench",
+							"failed correcting context chain", exception);
+				}
+			});
+			break;
+		case SWT.Deactivate:
+			Object context = window.getContext();
+			WorkbenchSWTActivator.trace("/trace/workbench",
+					"setting mwindow context " + context, null);
+			// record this shell's context
+			shell.setData(ECLIPSE_CONTEXT_SHELL_CONTEXT, context);
+			break;
+		}
+	}
+
+	private void activate(Shell shell) {
+		final IEclipseContext parentContext = application.getContext();
+		final IEclipseContext shellContext = getShellContext(shell,
+				parentContext);
+
+		SafeRunner.run(new ISafeRunnable() {
+			@Override
+			public void run() throws Exception {
+				// activate this shell
+				shellContext.activate();
+			}
+
+			@Override
+			public void handleException(Throwable exception) {
+				WorkbenchSWTActivator.trace("/trace/workbench",
+						"failed setting dialog child", exception);
+			}
+		});
+
+	}
+
+	private void deactivate(Shell shell) {
+		// bug 412001. Cannot assume anything about a non-modelled Shell's
+		// deactivation. It could be:
+		// * some other application got activated
+		// * some dialog we cannot see (IE's Find dialog in 412001) get's
+		// activated
+		// * another unmodelled shell is about to be activated
+		// * a modelled shell is about to be activated.
+		// No matter what, the time to do things is on activation
+
+	}
+
+	/**
+	 * Retrieves the eclipse context for the specified shell. If one cannot be
+	 * found, a child context will be created off of the provided parent
+	 * context.
+	 *
+	 * @param shell
+	 *            the shell of interest, must not be <code>null</code>
+	 * @param parentContext
+	 *            the parent context that the shell's context should be created
+	 *            off of if it doesn't have one, must not be <code>null</code>
+	 * @return the shell's eclipse context
+	 */
+	private IEclipseContext getShellContext(final Shell shell,
+			IEclipseContext parentContext) {
+		IEclipseContext shellContext = (IEclipseContext) shell
+				.getData(ECLIPSE_CONTEXT_SHELL_CONTEXT);
+		if (shellContext != null) {
+			return shellContext;
+		}
+		final IEclipseContext context = parentContext
+				.createChild(EBindingService.DIALOG_CONTEXT_ID);
+
+		context.set(E4Workbench.LOCAL_ACTIVE_SHELL, shell);
+
+		// set the context into the widget for future retrieval
+		shell.setData(ECLIPSE_CONTEXT_SHELL_CONTEXT, context);
+
+		EContextService contextService = context.get(EContextService.class);
+		contextService.activateContext(EBindingService.DIALOG_CONTEXT_ID);
+
+		shell.addDisposeListener(new DisposeListener() {
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				deactivate(shell);
+				context.dispose();
+			}
+		});
+
+		return context;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/StatusReporterCreationFunction.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/StatusReporterCreationFunction.java
new file mode 100644
index 0000000..2b6ba53
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/StatusReporterCreationFunction.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.internal.workbench.swt;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ *
+ */
+public class StatusReporterCreationFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		return ContextInjectionFactory.make(WorkbenchStatusReporter.class,
+				context);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java
new file mode 100644
index 0000000..6c99977
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchSWTActivator.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench.swt;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import org.eclipse.core.internal.runtime.InternalPlatform;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.service.debug.DebugOptions;
+import org.eclipse.osgi.service.debug.DebugTrace;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class WorkbenchSWTActivator implements BundleActivator { // extends
+																// Plugin {
+	public static final String PI_RENDERERS = "org.eclipse.e4.ui.workbench.swt"; //$NON-NLS-1$
+
+	private BundleContext context;
+	private ServiceTracker<?, PackageAdmin> pkgAdminTracker;
+	private ServiceTracker<?, Location> locationTracker;
+	private static WorkbenchSWTActivator activator;
+	private ServiceTracker<?, DebugOptions> debugTracker;
+	private DebugTrace trace;
+
+
+	/**
+	 * Get the default activator.
+	 *
+	 * @return a BundleActivator
+	 */
+	public static WorkbenchSWTActivator getDefault() {
+		return activator;
+	}
+
+	/**
+	 * @return this bundles context
+	 */
+	public BundleContext getContext() {
+		return context;
+	}
+
+	@Override
+	public void start(BundleContext context) throws Exception {
+		activator = this;
+		this.context = context;
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		saveDialogSettings();
+		if (pkgAdminTracker != null) {
+			pkgAdminTracker.close();
+			pkgAdminTracker = null;
+		}
+	}
+
+	public Bundle getBundle() {
+		if (context == null) {
+			return null;
+		}
+		return context.getBundle();
+	}
+
+	/**
+	 * @return the PackageAdmin service from this bundle
+	 */
+	public PackageAdmin getBundleAdmin() {
+		if (pkgAdminTracker == null) {
+			if (context == null) {
+				return null;
+			}
+			pkgAdminTracker = new ServiceTracker<>(context, PackageAdmin.class, null);
+			pkgAdminTracker.open();
+		}
+		return pkgAdminTracker.getService();
+	}
+
+	/**
+	 * @return the instance Location service
+	 */
+	public Location getInstanceLocation() {
+		if (locationTracker == null) {
+			Filter filter = null;
+			try {
+				filter = context.createFilter(Location.INSTANCE_FILTER);
+			} catch (InvalidSyntaxException e) {
+				// ignore this. It should never happen as we have tested the
+				// above format.
+			}
+			locationTracker = new ServiceTracker<>(context, filter, null);
+			locationTracker.open();
+		}
+		return locationTracker.getService();
+	}
+
+	/**
+	 * @param bundleName
+	 *            the bundle id
+	 * @return A bundle if found, or <code>null</code>
+	 */
+	public Bundle getBundleForName(String bundleName) {
+		Bundle[] bundles = getBundleAdmin().getBundles(bundleName, null);
+		if (bundles == null) {
+			return null;
+		}
+		// Return the first bundle that is not installed or uninstalled
+		for (int i = 0; i < bundles.length; i++) {
+			if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
+				return bundles[i];
+			}
+		}
+		return null;
+	}
+
+	public static void trace(String option, String msg, Throwable error) {
+		final DebugOptions debugOptions = activator.getDebugOptions();
+		if (debugOptions.isDebugEnabled()
+				&& debugOptions.getBooleanOption(PI_RENDERERS + option, false)) {
+			System.out.println(msg);
+			if (error != null) {
+				error.printStackTrace(System.out);
+			}
+		}
+		activator.getTrace().trace(option, msg, error);
+	}
+
+	public DebugOptions getDebugOptions() {
+		if (debugTracker == null) {
+			if (context == null) {
+				return null;
+			}
+			debugTracker = new ServiceTracker<>(context, DebugOptions.class, null);
+			debugTracker.open();
+		}
+		return debugTracker.getService();
+	}
+
+	public DebugTrace getTrace() {
+		if (trace == null) {
+			trace = getDebugOptions().newDebugTrace(PI_RENDERERS);
+		}
+		return trace;
+	}
+
+	// //////////////////////////////////////////////////////////////////////
+	// The following code was copied from AbstractUIPlugin class.
+
+	/**
+	 * The name of the dialog settings file (value
+	 * <code>"dialog_settings.xml"</code>).
+	 */
+	private static final String FN_DIALOG_SETTINGS = "dialog_settings.xml"; //$NON-NLS-1$
+	/**
+	 * Storage for dialog and wizard data; <code>null</code> if not yet
+	 * initialized.
+	 */
+	private IDialogSettings dialogSettings = null;
+
+	/**
+	 * Returns the dialog settings for this UI plug-in. The dialog settings is
+	 * used to hold persistent state data for the various wizards and dialogs of
+	 * this plug-in in the context of a workbench.
+	 * <p>
+	 * If an error occurs reading the dialog store, an empty one is quietly
+	 * created and returned.
+	 * </p>
+	 * <p>
+	 * Subclasses may override this method but are not expected to.
+	 * </p>
+	 *
+	 * @return the dialog settings
+	 */
+	public IDialogSettings getDialogSettings() {
+		if (dialogSettings == null) {
+			loadDialogSettings();
+		}
+		return dialogSettings;
+	}
+
+	/**
+	 * Loads the dialog settings for this plug-in. The default implementation
+	 * first looks for a standard named file in the plug-in's read/write state
+	 * area; if no such file exists, the plug-in's install directory is checked
+	 * to see if one was installed with some default settings; if no file is
+	 * found in either place, a new empty dialog settings is created. If a
+	 * problem occurs, an empty settings is silently used.
+	 * <p>
+	 * This framework method may be overridden, although this is typically
+	 * unnecessary.
+	 * </p>
+	 */
+	protected void loadDialogSettings() {
+		dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
+
+		// bug 69387: The instance area should not be created (in the call to
+		// #getStateLocation) if -data @none or -data @noDefault was used
+		IPath dataLocation = getStateLocationOrNull();
+		if (dataLocation != null) {
+			// try r/w state area in the local file system
+			String readWritePath = dataLocation.append(FN_DIALOG_SETTINGS).toOSString();
+			File settingsFile = new File(readWritePath);
+			if (settingsFile.exists()) {
+				try {
+					dialogSettings.load(readWritePath);
+				} catch (IOException e) {
+					// load failed so ensure we have an empty settings
+					dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
+				}
+
+				return;
+			}
+		}
+
+		// otherwise look for bundle specific dialog settings
+		Bundle bundle = context.getBundle();
+		URL dsURL = FileLocator.find(bundle, new Path(FN_DIALOG_SETTINGS), null);
+		if (dsURL == null) {
+			return;
+		}
+
+		InputStream is = null;
+		try {
+			is = dsURL.openStream();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8")); //$NON-NLS-1$
+			dialogSettings.load(reader);
+		} catch (IOException e) {
+			// load failed so ensure we have an empty settings
+			dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
+		} finally {
+			try {
+				if (is != null) {
+					is.close();
+				}
+			} catch (IOException e) {
+				// do nothing
+			}
+		}
+	}
+
+	/**
+	 * Saves this plug-in's dialog settings. Any problems which arise are
+	 * silently ignored.
+	 */
+	protected void saveDialogSettings() {
+		if (dialogSettings == null) {
+			return;
+		}
+
+		try {
+			IPath path = getStateLocationOrNull();
+			if (path == null) {
+				return;
+			}
+			String readWritePath = path.append(FN_DIALOG_SETTINGS).toOSString();
+			dialogSettings.save(readWritePath);
+		} catch (IOException e) {
+			// spec'ed to ignore problems
+		} catch (IllegalStateException e) {
+			// spec'ed to ignore problems
+		}
+	}
+
+	/**
+	 * FOR INTERNAL WORKBENCH USE ONLY.
+	 *
+	 * Returns the path to a location in the file system that can be used to
+	 * persist/restore state between workbench invocations. If the location did
+	 * not exist prior to this call it will be created. Returns
+	 * <code>null</code> if no such location is available.
+	 *
+	 * @return path to a location in the file system where this plug-in can
+	 *         persist data between sessions, or <code>null</code> if no such
+	 *         location is available.
+	 * @since 3.1
+	 */
+	private IPath getStateLocationOrNull() {
+		// TBD the state location is only accessible from Plugin class
+		// However, using it causes problems in the activation order
+		// So, for now, we get it directly.
+		try {
+			return InternalPlatform.getDefault().getStateLocation(context.getBundle(), true);
+		} catch (IllegalStateException e) {
+			// This occurs if -data=@none is explicitly specified, so ignore
+			// this silently.
+			// Is this OK? See bug 85071.
+			return null;
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchStatusReporter.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchStatusReporter.java
new file mode 100644
index 0000000..84add08
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/WorkbenchStatusReporter.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ *     Sopot Cela (sopotcela@gmail.com) Bug 386022 - Title of ErrorDialog in WorkbenchStatusReporter should be externalized
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.swt;
+
+import javax.inject.Inject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.core.services.statusreporter.StatusReporter;
+import org.eclipse.e4.ui.workbench.swt.internal.copy.WorkbenchSWTMessages;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
+import org.osgi.framework.BundleContext;
+
+/**
+ *
+ */
+public class WorkbenchStatusReporter extends StatusReporter {
+
+	@Inject
+	@Optional
+	IShellProvider shellProvider;
+	@Inject
+	Logger logger;
+	@Inject
+	@Optional
+	BundleContext bundleContext;
+	ErrorDialog dialog;
+
+	@Inject
+	private IEclipseContext context;
+
+	@Override
+	public void report(IStatus status, int style, Object... information) {
+		int action = style & (IGNORE | LOG | SHOW | BLOCK);
+		if (action == 0) {
+			if (status.matches(ERROR)) {
+				action = SHOW;
+			} else {
+				action = LOG;
+			}
+		}
+		if (style != IGNORE) {
+			// log even if showing a dialog
+			log(status);
+			if ((action & (SHOW | BLOCK)) != 0) {
+				boolean shouldBlock = (action & BLOCK) != 0;
+				openDialog(status, shouldBlock, information);
+			}
+		}
+	}
+
+	private void log(IStatus status) {
+		if (status.matches(ERROR)) {
+			logger.error(status.getException(), status.getMessage());
+		} else if (status.matches(WARNING)) {
+			logger.warn(status.getException(), status.getMessage());
+		} else if (status.matches(INFO)) {
+			logger.info(status.getException(), status.getMessage());
+		}
+	}
+
+	private void openDialog(final IStatus status, boolean shouldBlock,
+			Object... information) {
+		String[] informationStrings = new String[information.length];
+		if (dialog != null && dialog.getShell() != null
+				&& !dialog.getShell().isDisposed()) {
+			// another dialog is still open, ideally we'd add the current status
+			// to that dialog.
+			// for now, just log the new problem
+			log(status);
+			return;
+		}
+		final Status exceptionStatus = new Status(status.getSeverity(),
+				status.getPlugin(),
+				status.getException() == null ? status.getMessage() : status
+						.getException().toString(), status.getException());
+
+		// TBD this code should really be in IShellProvider which should be
+		// available at the application context level.
+		Shell myShell = null;
+		if (shellProvider != null)
+			myShell = shellProvider.getShell();
+		else {
+			IEclipseContext activeLeaf = context.getActiveLeaf();
+			if (activeLeaf != null) {
+				IShellProvider provider = activeLeaf.get(IShellProvider.class);
+				if (provider != null)
+					myShell = provider.getShell();
+			}
+		}
+		if (myShell == null) {
+			myShell = new Shell();
+		}
+
+		dialog = new ErrorDialog(myShell, WorkbenchSWTMessages.InternalError,
+				status.getMessage(),
+				status.getException() != null ? exceptionStatus : status, ERROR
+						| WARNING | INFO) {
+			@Override
+			protected void configureShell(Shell shell) {
+				super.configureShell(shell);
+				shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
+			}
+		};
+		for (int i = 0; i < information.length; i++) {
+			informationStrings[i] = information[i] == null ? "null" : information[i].toString(); //$NON-NLS-1$
+		}
+		dialog.setBlockOnOpen(shouldBlock);
+		dialog.open();
+	}
+
+	@Override
+	public IStatus newStatus(int severity, String message, Throwable exception) {
+		return new Status(severity, getPluginId(), message, exception);
+	}
+
+	protected String getPluginId() {
+		return bundleContext == null ? "unknown" : bundleContext.getBundle()
+				.getSymbolicName();
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ShowViewHandler.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ShowViewHandler.java
new file mode 100644
index 0000000..c8add47
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ShowViewHandler.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench.swt.handlers;
+
+import javax.inject.Named;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.swt.internal.copy.ShowViewDialog;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+
+public class ShowViewHandler {
+
+	public static final String VIEWS_SHOW_VIEW_PARM_ID = "org.eclipse.ui.views.showView.viewId"; //$NON-NLS-1$
+
+	@Execute
+	public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell,
+			MApplication application, EPartService partService,
+			IEclipseContext context,
+			@Optional @Named(VIEWS_SHOW_VIEW_PARM_ID) String viewId) {
+		if (viewId != null) {
+			partService.showPart(viewId, PartState.ACTIVATE);
+			return;
+		}
+
+		final ShowViewDialog dialog = new ShowViewDialog(shell, application,
+				context);
+		dialog.open();
+		if (dialog.getReturnCode() != Window.OK)
+			return;
+
+		for (MPartDescriptor descriptor : dialog.getSelection()) {
+			partService.showPart(descriptor.getElementId(), PartState.ACTIVATE);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ThemeUtil.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ThemeUtil.java
new file mode 100644
index 0000000..03949ca
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/handlers/ThemeUtil.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Siemens AG 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:
+ *     Kai Tödter - initial implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.swt.handlers;
+
+import org.eclipse.e4.ui.services.IStylingEngine;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+public class ThemeUtil {
+
+	public static void applyDialogStyles(IStylingEngine engine, Control control) {
+		if (engine != null) {
+			Shell shell = control.getShell();
+			if (shell.getBackgroundMode() == SWT.INHERIT_NONE) {
+				shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
+			}
+
+			engine.style(shell);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/factories/IRendererFactory.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/factories/IRendererFactory.java
new file mode 100644
index 0000000..a09b3aa
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/factories/IRendererFactory.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.swt.factories;
+
+import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+
+public interface IRendererFactory {
+	public AbstractPartRenderer getRenderer(MUIElement uiElement, Object parent);
+
+	// public void init(IEclipseContext context);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/BasicUIJob.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/BasicUIJob.java
new file mode 100644
index 0000000..44b266f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/BasicUIJob.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.swt.internal.copy;
+
+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.swt.widgets.Display;
+
+/**
+ * Merge of UIJob and WokbenchJob minus tracking whether the workbench is
+ * running - do not use for long running jobs!
+ */
+public abstract class BasicUIJob 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 BasicUIJob(String name, Display display) {
+		super(name);
+		this.cachedDisplay = display;
+	}
+
+	/**
+	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+	 *      Note: this message is marked final. Implementors should use
+	 *      runInUIThread() instead.
+	 */
+	@Override
+	public final IStatus run(final IProgressMonitor monitor) {
+		if (monitor.isCanceled()) {
+			return Status.CANCEL_STATUS;
+		}
+		Display asyncDisplay = (cachedDisplay == null) ? getDisplay()
+				: cachedDisplay;
+		if (asyncDisplay == null || asyncDisplay.isDisposed()) {
+			return Status.CANCEL_STATUS;
+		}
+		asyncDisplay.asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				IStatus result = 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 {
+						result = runInUIThread(monitor);
+					}
+				} finally {
+					done(result);
+				}
+			}
+		});
+		return Job.ASYNC_FINISH;
+	}
+
+	/**
+	 * Run the job in the UI Thread.
+	 *
+	 * @param monitor
+	 * @return IStatus
+	 */
+	public abstract IStatus runInUIThread(IProgressMonitor monitor);
+
+	/**
+	 * 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() {
+		return (cachedDisplay != null) ? cachedDisplay : Display.getCurrent();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/FilteredTree.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/FilteredTree.java
new file mode 100644
index 0000000..a9d98ad
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/FilteredTree.java
@@ -0,0 +1,1193 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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
+ *     Jacek Pospychala - bug 187762
+ *     Mohamed Tarief - tarief@eg.ibm.com - IBM - Bug 174481
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 440381
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.swt.internal.copy;
+
+import java.net.URL;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+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.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.osgi.framework.Bundle;
+
+/**
+ * Based on org.eclipse.ui.dialogs.FilteredTree.
+ */
+public class FilteredTree extends Composite {
+
+	/**
+	 * The filter text widget to be used by this tree. This value may be
+	 * <code>null</code> if there is no filter widget, or if the controls have
+	 * not yet been created.
+	 */
+	protected Text filterText;
+
+	/**
+	 * The control representing the clear button for the filter text entry. This
+	 * value may be <code>null</code> if no such button exists, or if the
+	 * controls have not yet been created.
+	 * <p>
+	 * <strong>Note:</strong> As of 3.5, this is not used if the new look is
+	 * chosen.
+	 * </p>
+	 */
+	protected ToolBarManager filterToolBar;
+
+	/**
+	 * The control representing the clear button for the filter text entry. This
+	 * value may be <code>null</code> if no such button exists, or if the
+	 * controls have not yet been created.
+	 * <p>
+	 * <strong>Note:</strong> This is only used if the new look is chosen.
+	 * </p>
+	 *
+	 * @since 3.5
+	 */
+	protected Control clearButtonControl;
+
+	/**
+	 * The viewer for the filtered tree. This value should never be
+	 * <code>null</code> after the widget creation methods are complete.
+	 */
+	protected TreeViewer treeViewer;
+
+	/**
+	 * The Composite on which the filter controls are created. This is used to
+	 * set the background color of the filter controls to match the surrounding
+	 * controls.
+	 */
+	protected Composite filterComposite;
+
+	/**
+	 * The pattern filter for the tree. This value must not be <code>null</code>
+	 * .
+	 */
+	private PatternFilter patternFilter;
+
+	/**
+	 * The text to initially show in the filter text control.
+	 */
+	protected String initialText = ""; //$NON-NLS-1$
+
+	/**
+	 * The job used to refresh the tree.
+	 */
+	private Job refreshJob;
+
+	/**
+	 * The parent composite of the filtered tree.
+	 *
+	 * @since 3.3
+	 */
+	protected Composite parent;
+
+	/**
+	 * Whether or not to show the filter controls (text and clear button). The
+	 * default is to show these controls. This can be overridden by providing a
+	 * setting in the product configuration file. The setting to add to not show
+	 * these controls is:
+	 *
+	 * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
+	 */
+	protected boolean showFilterControls;
+
+	/**
+	 * @since 3.3
+	 */
+	protected Composite treeComposite;
+
+	/**
+	 * Image descriptor for enabled clear button.
+	 */
+	private static final String CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
+
+	/**
+	 * Image descriptor for disabled clear button.
+	 */
+	private static final String DISABLED_CLEAR_ICON = "org.eclipse.ui.internal.dialogs.DCLEAR_ICON"; //$NON-NLS-1$
+
+	/**
+	 * Maximum time spent expanding the tree after the filter text has been
+	 * updated (this is only used if we were able to at least expand the visible
+	 * nodes)
+	 */
+	private static final long SOFT_MAX_EXPAND_TIME = 200;
+
+	/**
+	 * Get image descriptors for the clear button.
+	 */
+	static {
+		Bundle bundle = org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator
+				.getDefault().getBundle();
+		IPath enabledPath = new Path("$nl$/icons/full/etool16/clear_co.gif");
+		URL enabledURL = FileLocator.find(bundle, enabledPath, null);
+		ImageDescriptor enabledDesc = ImageDescriptor.createFromURL(enabledURL);
+		if (enabledDesc != null)
+			JFaceResources.getImageRegistry().put(CLEAR_ICON, enabledDesc);
+
+		IPath disabledPath = new Path("$nl$/icons/full/etool16/clear_co.gif");
+		URL disabledURL = FileLocator.find(bundle, disabledPath, null);
+		ImageDescriptor disabledDesc = ImageDescriptor
+				.createFromURL(disabledURL);
+		if (disabledDesc != null)
+			JFaceResources.getImageRegistry().put(DISABLED_CLEAR_ICON,
+					disabledDesc);
+	}
+
+	/**
+	 * Create a new instance of the receiver.
+	 *
+	 * @param parent
+	 *            the parent <code>Composite</code>
+	 * @param treeStyle
+	 *            the style bits for the <code>Tree</code>
+	 * @param filter
+	 *            the filter to be used
+	 * @since 3.5
+	 */
+	public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) {
+		super(parent, SWT.NONE);
+		this.parent = parent;
+		init(treeStyle, filter);
+	}
+
+	/**
+	 * Create a new instance of the receiver.
+	 *
+	 * @param parent
+	 *            the parent <code>Composite</code>
+	 * @param treeStyle
+	 *            the style bits for the <code>Tree</code>
+	 * @param filter
+	 *            the filter to be used
+	 * @param useNewLook
+	 *            ignored, look introduced in 3.5 is always used
+	 * @since 3.5
+	 *
+	 * @deprecated use FilteredTree(Composite parent, int treeStyle,
+	 *             PatternFilter filter)
+	 */
+	@Deprecated
+	public FilteredTree(Composite parent, int treeStyle, PatternFilter filter,
+			boolean useNewLook) {
+		this(parent, treeStyle, filter);
+	}
+
+	/**
+	 * Create a new instance of the receiver. Subclasses that wish to override
+	 * the default creation behavior may use this constructor, but must ensure
+	 * that the <code>init(composite, int, PatternFilter)</code> method is
+	 * called in the overriding constructor.
+	 *
+	 * @param parent
+	 *            the parent <code>Composite</code>
+	 * @see #init(int, PatternFilter)
+	 *
+	 * @since 3.5
+	 */
+	protected FilteredTree(Composite parent) {
+		super(parent, SWT.NONE);
+		this.parent = parent;
+	}
+
+	/**
+	 * Create a new instance of the receiver. Subclasses that wish to override
+	 * the default creation behavior may use this constructor, but must ensure
+	 * that the <code>init(composite, int, PatternFilter)</code> method is
+	 * called in the overriding constructor.
+	 *
+	 * @param parent
+	 *            the parent <code>Composite</code>
+	 * @param useNewLook
+	 *            ignored, look introduced in 3.5 is always used
+	 * @see #init(int, PatternFilter)
+	 *
+	 * @since 3.5
+	 *
+	 * @deprecated use FilteredTree(Composite parent) instead
+	 */
+	@Deprecated
+	protected FilteredTree(Composite parent, boolean useNewLook) {
+		this(parent);
+	}
+
+	/**
+	 * Create the filtered tree.
+	 *
+	 * @param treeStyle
+	 *            the style bits for the <code>Tree</code>
+	 * @param filter
+	 *            the filter to be used
+	 *
+	 * @since 3.3
+	 */
+	protected void init(int treeStyle, PatternFilter filter) {
+		patternFilter = filter;
+		showFilterControls = true; // PlatformUI.getPreferenceStore().getBoolean(
+		// IWorkbenchPreferenceConstants.SHOW_FILTERED_TEXTS);
+		createControl(parent, treeStyle);
+		createRefreshJob();
+		setInitialText(WorkbenchSWTMessages.FilteredTree_FilterMessage);
+		setFont(parent.getFont());
+	}
+
+	/**
+	 * Create the filtered tree's controls. Subclasses should override.
+	 *
+	 * @param parent
+	 * @param treeStyle
+	 */
+	protected void createControl(Composite parent, int treeStyle) {
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		setLayout(layout);
+		setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+		if (showFilterControls) {
+			if (useNativeSearchField(parent)) {
+				filterComposite = new Composite(this, SWT.NONE);
+			} else {
+				filterComposite = new Composite(this, SWT.BORDER);
+				filterComposite.setBackground(getDisplay().getSystemColor(
+						SWT.COLOR_LIST_BACKGROUND));
+			}
+			GridLayout filterLayout = new GridLayout(2, false);
+			filterLayout.marginHeight = 0;
+			filterLayout.marginWidth = 0;
+			filterComposite.setLayout(filterLayout);
+			filterComposite.setFont(parent.getFont());
+
+			createFilterControls(filterComposite);
+			filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING,
+					true, false));
+		}
+
+		treeComposite = new Composite(this, SWT.NONE);
+		GridLayout treeCompositeLayout = new GridLayout();
+		treeCompositeLayout.marginHeight = 0;
+		treeCompositeLayout.marginWidth = 0;
+		treeComposite.setLayout(treeCompositeLayout);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+		treeComposite.setLayoutData(data);
+		createTreeControl(treeComposite, treeStyle);
+	}
+
+	private static Boolean useNativeSearchField;
+
+	private static boolean useNativeSearchField(Composite composite) {
+		if (useNativeSearchField == null) {
+			useNativeSearchField = Boolean.FALSE;
+			Text testText = null;
+			try {
+				testText = new Text(composite, SWT.SEARCH | SWT.ICON_CANCEL);
+				useNativeSearchField = new Boolean(
+						(testText.getStyle() & SWT.ICON_CANCEL) != 0);
+			} finally {
+				if (testText != null) {
+					testText.dispose();
+				}
+			}
+
+		}
+		return useNativeSearchField.booleanValue();
+	}
+
+	/**
+	 * Create the filter controls. By default, a text and corresponding tool bar
+	 * button that clears the contents of the text is created. Subclasses may
+	 * override.
+	 *
+	 * @param parent
+	 *            parent <code>Composite</code> of the filter controls
+	 * @return the <code>Composite</code> that contains the filter controls
+	 */
+	protected Composite createFilterControls(Composite parent) {
+		createFilterText(parent);
+		createClearText(parent);
+		if (clearButtonControl != null) {
+			// initially there is no text to clear
+			clearButtonControl.setVisible(false);
+		}
+		if (filterToolBar != null) {
+			filterToolBar.update(false);
+			// initially there is no text to clear
+			filterToolBar.getControl().setVisible(false);
+		}
+		return parent;
+	}
+
+	/**
+	 * Creates and set up the tree and tree viewer. This method calls
+	 * {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
+	 * Subclasses should override {@link #doCreateTreeViewer(Composite, int)}
+	 * instead of overriding this method.
+	 *
+	 * @param parent
+	 *            parent <code>Composite</code>
+	 * @param style
+	 *            SWT style bits used to create the tree
+	 * @return the tree
+	 */
+	protected Control createTreeControl(Composite parent, int style) {
+		treeViewer = doCreateTreeViewer(parent, style);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+		treeViewer.getControl().setLayoutData(data);
+		treeViewer.getControl().addDisposeListener(new DisposeListener() {
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				refreshJob.cancel();
+			}
+		});
+		if (treeViewer instanceof NotifyingTreeViewer) {
+			patternFilter.setUseCache(true);
+		}
+		treeViewer.addFilter(patternFilter);
+		return treeViewer.getControl();
+	}
+
+	/**
+	 * Creates the tree viewer. Subclasses may override.
+	 *
+	 * @param parent
+	 *            the parent composite
+	 * @param style
+	 *            SWT style bits used to create the tree viewer
+	 * @return the tree viewer
+	 *
+	 * @since 3.3
+	 */
+	protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
+		return new NotifyingTreeViewer(parent, style);
+	}
+
+	/**
+	 * Return the first item in the tree that matches the filter pattern.
+	 *
+	 * @param items
+	 * @return the first matching TreeItem
+	 */
+	private TreeItem getFirstMatchingItem(TreeItem[] items) {
+		for (int i = 0; i < items.length; i++) {
+			if (patternFilter.isLeafMatch(treeViewer, items[i].getData())
+					&& patternFilter.isElementSelectable(items[i].getData())) {
+				return items[i];
+			}
+			TreeItem treeItem = getFirstMatchingItem(items[i].getItems());
+			if (treeItem != null) {
+				return treeItem;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Create the refresh job for the receiver.
+	 *
+	 */
+	private void createRefreshJob() {
+		refreshJob = doCreateRefreshJob();
+		refreshJob.setSystem(true);
+	}
+
+	/**
+	 * Creates a workbench job that will refresh the tree based on the current
+	 * filter text. Subclasses may override.
+	 *
+	 * @return a workbench job that can be scheduled to refresh the tree
+	 *
+	 * @since 3.4
+	 */
+	protected BasicUIJob doCreateRefreshJob() {
+		return new BasicUIJob("Refresh Filter", parent.getDisplay()) {//$NON-NLS-1$
+			@Override
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				if (treeViewer.getControl().isDisposed()) {
+					return Status.CANCEL_STATUS;
+				}
+
+				String text = getFilterString();
+				if (text == null) {
+					return Status.OK_STATUS;
+				}
+
+				boolean initial = initialText != null
+						&& initialText.equals(text);
+				if (initial) {
+					patternFilter.setPattern(null);
+				} else if (text != null) {
+					patternFilter.setPattern(text);
+				}
+
+				Control redrawFalseControl = treeComposite != null ? treeComposite
+						: treeViewer.getControl();
+				try {
+					// don't want the user to see updates that will be made to
+					// the tree
+					// we are setting redraw(false) on the composite to avoid
+					// dancing scrollbar
+					redrawFalseControl.setRedraw(false);
+					if (!narrowingDown) {
+						// collapse all
+						TreeItem[] is = treeViewer.getTree().getItems();
+						for (int i = 0; i < is.length; i++) {
+							TreeItem item = is[i];
+							if (item.getExpanded()) {
+								treeViewer.setExpandedState(item.getData(),
+										false);
+							}
+						}
+					}
+					treeViewer.refresh(true);
+
+					if (text.length() > 0 && !initial) {
+						/*
+						 * Expand elements one at a time. After each is
+						 * expanded, check to see if the filter text has been
+						 * modified. If it has, then cancel the refresh job so
+						 * the user doesn't have to endure expansion of all the
+						 * nodes.
+						 */
+						TreeItem[] items = getViewer().getTree().getItems();
+						int treeHeight = getViewer().getTree().getBounds().height;
+						int numVisibleItems = treeHeight
+								/ getViewer().getTree().getItemHeight();
+						long stopTime = SOFT_MAX_EXPAND_TIME
+								+ System.currentTimeMillis();
+						boolean cancel = false;
+						if (items.length > 0
+								&& recursiveExpand(items, monitor, stopTime,
+										new int[] { numVisibleItems })) {
+							cancel = true;
+						}
+
+						// enabled toolbar - there is text to clear
+						// and the list is currently being filtered
+						updateToolbar(true);
+
+						if (cancel) {
+							return Status.CANCEL_STATUS;
+						}
+					} else {
+						// disabled toolbar - there is no text to clear
+						// and the list is currently not filtered
+						updateToolbar(false);
+					}
+				} finally {
+					// done updating the tree - set redraw back to true
+					TreeItem[] items = getViewer().getTree().getItems();
+					if (items.length > 0
+							&& getViewer().getTree().getSelectionCount() == 0) {
+						treeViewer.getTree().setTopItem(items[0]);
+					}
+					redrawFalseControl.setRedraw(true);
+				}
+				return Status.OK_STATUS;
+			}
+
+			/**
+			 * Returns true if the job should be canceled (because of timeout or
+			 * actual cancellation).
+			 *
+			 * @param items
+			 * @param monitor
+			 * @param cancelTime
+			 * @param numItemsLeft
+			 * @return true if canceled
+			 */
+			private boolean recursiveExpand(TreeItem[] items,
+					IProgressMonitor monitor, long cancelTime,
+					int[] numItemsLeft) {
+				boolean canceled = false;
+				for (int i = 0; !canceled && i < items.length; i++) {
+					TreeItem item = items[i];
+					boolean visible = numItemsLeft[0]-- >= 0;
+					if (monitor.isCanceled()
+							|| (!visible && System.currentTimeMillis() > cancelTime)) {
+						canceled = true;
+					} else {
+						Object itemData = item.getData();
+						if (itemData != null) {
+							if (!item.getExpanded()) {
+								// do the expansion through the viewer so that
+								// it can refresh children appropriately.
+								treeViewer.setExpandedState(itemData, true);
+							}
+							TreeItem[] children = item.getItems();
+							if (items.length > 0) {
+								canceled = recursiveExpand(children, monitor,
+										cancelTime, numItemsLeft);
+							}
+						}
+					}
+				}
+				return canceled;
+			}
+
+		};
+	}
+
+	protected void updateToolbar(boolean visible) {
+		if (clearButtonControl != null) {
+			clearButtonControl.setVisible(visible);
+		}
+		if (filterToolBar != null) {
+			filterToolBar.getControl().setVisible(visible);
+		}
+	}
+
+	/**
+	 * Creates the filter text and adds listeners. This method calls
+	 * {@link #doCreateFilterText(Composite)} to create the text control.
+	 * Subclasses should override {@link #doCreateFilterText(Composite)} instead
+	 * of overriding this method.
+	 *
+	 * @param parent
+	 *            <code>Composite</code> of the filter text
+	 */
+	protected void createFilterText(Composite parent) {
+		filterText = doCreateFilterText(parent);
+		filterText.getAccessible().addAccessibleListener(
+				new AccessibleAdapter() {
+					@Override
+					public void getName(AccessibleEvent e) {
+						String filterTextString = filterText.getText();
+						if (filterTextString.length() == 0
+								|| filterTextString.equals(initialText)) {
+							e.result = initialText;
+						} else {
+							e.result = NLS
+									.bind(
+											WorkbenchSWTMessages.FilteredTree_AccessibleListenerFiltered,
+											new String[] {
+													filterTextString,
+													String.valueOf(getFilteredItemsCount()) });
+						}
+					}
+
+					/**
+			 * Return the number of filtered items
+			 *
+			 * @return int
+			 */
+					private int getFilteredItemsCount() {
+						int total = 0;
+						TreeItem[] items = getViewer().getTree().getItems();
+						for (int i = 0; i < items.length; i++) {
+							total += itemCount(items[i]);
+
+						}
+						return total;
+					}
+
+					/**
+			 * Return the count of treeItem and it's children to infinite depth.
+			 *
+			 * @param treeItem
+			 * @return int
+			 */
+					private int itemCount(TreeItem treeItem) {
+						int count = 1;
+						TreeItem[] children = treeItem.getItems();
+						for (int i = 0; i < children.length; i++) {
+							count += itemCount(children[i]);
+
+						}
+						return count;
+					}
+				});
+
+		filterText.addFocusListener(new FocusAdapter() {
+
+			@Override
+			public void focusLost(FocusEvent e) {
+				if (filterText.getText().equals(initialText)) {
+					setFilterText(""); //$NON-NLS-1$
+					textChanged();
+				}
+			}
+		});
+
+		filterText.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mouseDown(MouseEvent e) {
+				if (filterText.getText().equals(initialText)) {
+					// XXX: We cannot call clearText() due to
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=260664
+					setFilterText(""); //$NON-NLS-1$
+					textChanged();
+				}
+			}
+		});
+
+		filterText.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent e) {
+				// on a CR we want to transfer focus to the list
+				boolean hasItems = getViewer().getTree().getItemCount() > 0;
+				if (hasItems && e.keyCode == SWT.ARROW_DOWN) {
+					treeViewer.getTree().setFocus();
+					return;
+				}
+			}
+		});
+
+		// enter key set focus to tree
+		filterText.addTraverseListener(new TraverseListener() {
+			@Override
+			public void keyTraversed(TraverseEvent e) {
+				if (e.detail == SWT.TRAVERSE_RETURN) {
+					e.doit = false;
+					if (getViewer().getTree().getItemCount() == 0) {
+						Display.getCurrent().beep();
+					} else {
+						// if the initial filter text hasn't changed, do not try
+						// to match
+						boolean hasFocus = getViewer().getTree().setFocus();
+						boolean textChanged = !getInitialText().equals(
+								filterText.getText().trim());
+						if (hasFocus && textChanged
+								&& filterText.getText().trim().length() > 0) {
+							Tree tree = getViewer().getTree();
+							TreeItem item;
+							if (tree.getSelectionCount() > 0)
+								item = getFirstMatchingItem(tree.getSelection());
+							else
+								item = getFirstMatchingItem(tree.getItems());
+							if (item != null) {
+								tree.setSelection(new TreeItem[] { item });
+								ISelection sel = getViewer().getSelection();
+								getViewer().setSelection(sel, true);
+							}
+						}
+					}
+				}
+			}
+		});
+
+		filterText.addModifyListener(new ModifyListener() {
+			@Override
+			public void modifyText(ModifyEvent e) {
+				textChanged();
+			}
+		});
+
+		// if we're using a field with built in cancel we need to listen for
+		// default selection changes (which tell us the cancel button has been
+		// pressed)
+		if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0) {
+			filterText.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+					if (e.detail == SWT.ICON_CANCEL)
+						clearText();
+				}
+			});
+		}
+
+		GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
+		// if the text widget supported cancel then it will have it's own
+		// integrated button. We can take all of the space.
+		if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0)
+			gridData.horizontalSpan = 2;
+		filterText.setLayoutData(gridData);
+	}
+
+	/**
+	 * Creates the text control for entering the filter text. Subclasses may
+	 * override.
+	 *
+	 * @param parent
+	 *            the parent composite
+	 * @return the text widget
+	 *
+	 * @since 3.3
+	 */
+	protected Text doCreateFilterText(Composite parent) {
+		if (useNativeSearchField(parent)) {
+			return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH
+					| SWT.ICON_CANCEL);
+		}
+		return new Text(parent, SWT.SINGLE);
+	}
+
+	private String previousFilterText;
+
+	private boolean narrowingDown;
+
+	/**
+	 * Update the receiver after the text has changed.
+	 */
+	protected void textChanged() {
+		narrowingDown = previousFilterText == null
+				|| previousFilterText
+						.equals(WorkbenchSWTMessages.FilteredTree_FilterMessage)
+				|| getFilterString().startsWith(previousFilterText);
+		previousFilterText = getFilterString();
+		// cancel currently running job first, to prevent unnecessary redraw
+		refreshJob.cancel();
+		refreshJob.schedule(getRefreshJobDelay());
+	}
+
+	/**
+	 * Return the time delay that should be used when scheduling the filter
+	 * refresh job. Subclasses may override.
+	 *
+	 * @return a time delay in milliseconds before the job should run
+	 *
+	 * @since 3.5
+	 */
+	protected long getRefreshJobDelay() {
+		return 200;
+	}
+
+	/**
+	 * Set the background for the widgets that support the filter text area.
+	 *
+	 * @param background
+	 *            background <code>Color</code> to set
+	 */
+	@Override
+	public void setBackground(Color background) {
+		super.setBackground(background);
+		if (filterComposite != null && (useNativeSearchField(filterComposite))) {
+			filterComposite.setBackground(background);
+		}
+		if (filterToolBar != null && filterToolBar.getControl() != null) {
+			filterToolBar.getControl().setBackground(background);
+		}
+	}
+
+
+	/**
+	 * Create the button that clears the text.
+	 *
+	 * @param parent
+	 *            parent <code>Composite</code> of toolbar button
+	 */
+	private void createClearText(Composite parent) {
+		// only create the button if the text widget doesn't support one
+		// natively
+		if ((filterText.getStyle() & SWT.ICON_CANCEL) == 0) {
+			final Image inactiveImage = JFaceResources.getImageRegistry()
+					.getDescriptor(DISABLED_CLEAR_ICON).createImage();
+			final Image activeImage = JFaceResources.getImageRegistry()
+					.getDescriptor(CLEAR_ICON).createImage();
+			final Image pressedImage = new Image(getDisplay(), activeImage,
+ SWT.IMAGE_GRAY);
+
+			final Label clearButton = new Label(parent, SWT.NONE);
+			clearButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER,
+					false, false));
+			clearButton.setImage(inactiveImage);
+			clearButton.setBackground(parent.getDisplay().getSystemColor(
+					SWT.COLOR_LIST_BACKGROUND));
+			clearButton
+					.setToolTipText(WorkbenchSWTMessages.FilteredTree_ClearToolTip);
+			clearButton.addMouseListener(new MouseAdapter() {
+				private MouseMoveListener fMoveListener;
+
+				@Override
+				public void mouseDown(MouseEvent e) {
+					clearButton.setImage(pressedImage);
+					fMoveListener = new MouseMoveListener() {
+						private boolean fMouseInButton = true;
+
+						@Override
+						public void mouseMove(MouseEvent e) {
+							boolean mouseInButton = isMouseInButton(e);
+							if (mouseInButton != fMouseInButton) {
+								fMouseInButton = mouseInButton;
+								clearButton
+										.setImage(mouseInButton ? pressedImage
+												: inactiveImage);
+							}
+						}
+					};
+					// FIXME RAP
+					// clearButton.addMouseMoveListener(fMoveListener);
+				}
+
+				@Override
+				public void mouseUp(MouseEvent e) {
+					if (fMoveListener != null) {
+						// FIXME RAP
+						// clearButton.removeMouseMoveListener(fMoveListener);
+						fMoveListener = null;
+						boolean mouseInButton = isMouseInButton(e);
+						clearButton.setImage(mouseInButton ? activeImage
+								: inactiveImage);
+						if (mouseInButton) {
+							clearText();
+							filterText.setFocus();
+						}
+					}
+				}
+
+				private boolean isMouseInButton(MouseEvent e) {
+					Point buttonSize = clearButton.getSize();
+					return 0 <= e.x && e.x < buttonSize.x && 0 <= e.y
+							&& e.y < buttonSize.y;
+				}
+			});
+			// FIXME RAP
+			// clearButton.addMouseTrackListener(new MouseTrackListener() {
+			// @Override
+			// public void mouseEnter(MouseEvent e) {
+			// clearButton.setImage(activeImage);
+			// }
+			//
+			// @Override
+			// public void mouseExit(MouseEvent e) {
+			// clearButton.setImage(inactiveImage);
+			// }
+			//
+			// @Override
+			// public void mouseHover(MouseEvent e) {
+			// }
+			// });
+			clearButton.addDisposeListener(new DisposeListener() {
+				@Override
+				public void widgetDisposed(DisposeEvent e) {
+					inactiveImage.dispose();
+					activeImage.dispose();
+					pressedImage.dispose();
+				}
+			});
+			clearButton.getAccessible().addAccessibleListener(
+					new AccessibleAdapter() {
+						@Override
+						public void getName(AccessibleEvent e) {
+							e.result = WorkbenchSWTMessages.FilteredTree_AccessibleListenerClearButton;
+						}
+					});
+			clearButton.getAccessible().addAccessibleControlListener(
+					new AccessibleControlAdapter() {
+						@Override
+						public void getRole(AccessibleControlEvent e) {
+							e.detail = ACC.ROLE_PUSHBUTTON;
+						}
+					});
+			this.clearButtonControl = clearButton;
+		}
+	}
+
+	/**
+	 * Clears the text in the filter text widget.
+	 */
+	protected void clearText() {
+		setFilterText(""); //$NON-NLS-1$
+		textChanged();
+	}
+
+	/**
+	 * Set the text in the filter control.
+	 *
+	 * @param string
+	 */
+	protected void setFilterText(String string) {
+		if (filterText != null) {
+			filterText.setText(string);
+			selectAll();
+		}
+	}
+
+	/**
+	 * Returns the pattern filter used by this tree.
+	 *
+	 * @return The pattern filter; never <code>null</code>.
+	 */
+	public final PatternFilter getPatternFilter() {
+		return patternFilter;
+	}
+
+	/**
+	 * Get the tree viewer of the receiver.
+	 *
+	 * @return the tree viewer
+	 */
+	public TreeViewer getViewer() {
+		return treeViewer;
+	}
+
+	/**
+	 * Get the filter text for the receiver, if it was created. Otherwise return
+	 * <code>null</code>.
+	 *
+	 * @return the filter Text, or null if it was not created
+	 */
+	public Text getFilterControl() {
+		return filterText;
+	}
+
+	/**
+	 * Convenience method to return the text of the filter control. If the text
+	 * widget is not created, then null is returned.
+	 *
+	 * @return String in the text, or null if the text does not exist
+	 */
+	protected String getFilterString() {
+		return filterText != null ? filterText.getText() : null;
+	}
+
+	/**
+	 * Set the text that will be shown until the first focus. A default value is
+	 * provided, so this method only need be called if overriding the default
+	 * initial text is desired.
+	 *
+	 * @param text
+	 *            initial text to appear in text field
+	 */
+	public void setInitialText(String text) {
+		initialText = text;
+		if (filterText != null) {
+			filterText.setMessage(text);
+			if (filterText.isFocusControl()) {
+				setFilterText(initialText);
+				textChanged();
+			} else {
+				getDisplay().asyncExec(new Runnable() {
+					@Override
+					public void run() {
+						if (!filterText.isDisposed()
+								&& filterText.isFocusControl()) {
+							setFilterText(initialText);
+							textChanged();
+						}
+					}
+				});
+			}
+		} else {
+			setFilterText(initialText);
+			textChanged();
+		}
+	}
+
+	/**
+	 * Select all text in the filter text field.
+	 *
+	 */
+	protected void selectAll() {
+		if (filterText != null) {
+			filterText.selectAll();
+		}
+	}
+
+	/**
+	 * Get the initial text for the receiver.
+	 *
+	 * @return String
+	 */
+	protected String getInitialText() {
+		return initialText;
+	}
+
+	/**
+	 * Return a bold font if the given element matches the given pattern.
+	 * Clients can opt to call this method from a Viewer's label provider to get
+	 * a bold font for which to highlight the given element in the tree.
+	 *
+	 * @param element
+	 *            element for which a match should be determined
+	 * @param tree
+	 *            FilteredTree in which the element resides
+	 * @param filter
+	 *            PatternFilter which determines a match
+	 *
+	 * @return bold font
+	 */
+	public static Font getBoldFont(Object element, FilteredTree tree,
+			PatternFilter filter) {
+		String filterText = tree.getFilterString();
+
+		if (filterText == null) {
+			return null;
+		}
+
+		// Do nothing if it's empty string
+		String initialText = tree.getInitialText();
+		if (!filterText.equals("") && !filterText.equals(initialText)) {//$NON-NLS-1$
+			if (tree.getPatternFilter() != filter) {
+				boolean initial = initialText != null
+						&& initialText.equals(filterText);
+				if (initial) {
+					filter.setPattern(null);
+				} else if (filterText != null) {
+					filter.setPattern(filterText);
+				}
+			}
+			if (filter.isElementVisible(tree.getViewer(), element)
+					&& filter.isLeafMatch(tree.getViewer(), element)) {
+				return JFaceResources.getFontRegistry().getBold(
+						JFaceResources.DIALOG_FONT);
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Custom tree viewer subclass that clears the caches in patternFilter on
+	 * any change to the tree. See bug 187200.
+	 *
+	 * @since 3.3
+	 *
+	 */
+	class NotifyingTreeViewer extends TreeViewer {
+
+		/**
+		 * @param parent
+		 * @param style
+		 */
+		public NotifyingTreeViewer(Composite parent, int style) {
+			super(parent, style);
+		}
+
+		@Override
+		public void add(Object parentElementOrTreePath, Object childElement) {
+			getPatternFilter().clearCaches();
+			super.add(parentElementOrTreePath, childElement);
+		}
+
+		@Override
+		public void add(Object parentElementOrTreePath, Object[] childElements) {
+			getPatternFilter().clearCaches();
+			super.add(parentElementOrTreePath, childElements);
+		}
+
+		@Override
+		protected void inputChanged(Object input, Object oldInput) {
+			getPatternFilter().clearCaches();
+			super.inputChanged(input, oldInput);
+		}
+
+		@Override
+		public void insert(Object parentElementOrTreePath, Object element,
+				int position) {
+			getPatternFilter().clearCaches();
+			super.insert(parentElementOrTreePath, element, position);
+		}
+
+		@Override
+		public void refresh() {
+			getPatternFilter().clearCaches();
+			super.refresh();
+		}
+
+		@Override
+		public void refresh(boolean updateLabels) {
+			getPatternFilter().clearCaches();
+			super.refresh(updateLabels);
+		}
+
+		@Override
+		public void refresh(Object element) {
+			getPatternFilter().clearCaches();
+			super.refresh(element);
+		}
+
+		@Override
+		public void refresh(Object element, boolean updateLabels) {
+			getPatternFilter().clearCaches();
+			super.refresh(element, updateLabels);
+		}
+
+		@Override
+		public void remove(Object elementsOrTreePaths) {
+			getPatternFilter().clearCaches();
+			super.remove(elementsOrTreePaths);
+		}
+
+		@Override
+		public void remove(Object parent, Object[] elements) {
+			getPatternFilter().clearCaches();
+			super.remove(parent, elements);
+		}
+
+		@Override
+		public void remove(Object[] elementsOrTreePaths) {
+			getPatternFilter().clearCaches();
+			super.remove(elementsOrTreePaths);
+		}
+
+		@Override
+		public void replace(Object parentElementOrTreePath, int index,
+				Object element) {
+			getPatternFilter().clearCaches();
+			super.replace(parentElementOrTreePath, index, element);
+		}
+
+		@Override
+		public void setChildCount(Object elementOrTreePath, int count) {
+			getPatternFilter().clearCaches();
+			super.setChildCount(elementOrTreePath, count);
+		}
+
+		@Override
+		public void setContentProvider(IContentProvider provider) {
+			getPatternFilter().clearCaches();
+			super.setContentProvider(provider);
+		}
+
+		@Override
+		public void setHasChildren(Object elementOrTreePath, boolean hasChildren) {
+			getPatternFilter().clearCaches();
+			super.setHasChildren(elementOrTreePath, hasChildren);
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/PatternFilter.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/PatternFilter.java
new file mode 100644
index 0000000..a2ea942
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/PatternFilter.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2015 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.workbench.swt.internal.copy;
+
+import com.ibm.icu.text.BreakIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Based on org.eclipse.ui.dialogs.PatternFilter.
+ */
+public class PatternFilter extends ViewerFilter {
+	/*
+	 * Cache of filtered elements in the tree
+	 */
+	private Map<Object, Object[]> cache = new HashMap<>();
+
+	/*
+	 * Maps parent elements to TRUE or FALSE
+	 */
+	private Map<Object, Boolean> foundAnyCache = new HashMap<>();
+
+	private boolean useCache = false;
+
+	/**
+	 * Whether to include a leading wildcard for all provided patterns. A
+	 * trailing wildcard is always included.
+	 */
+	private boolean includeLeadingWildcard = false;
+
+	/**
+	 * The string pattern matcher used for this pattern filter.
+	 */
+	private StringMatcher matcher;
+
+	private boolean useEarlyReturnIfMatcherIsNull = true;
+
+	private static Object[] EMPTY = new Object[0];
+
+	@Override
+	public final Object[] filter(Viewer viewer, Object parent, Object[] elements) {
+		// we don't want to optimize if we've extended the filter ... this
+		// needs to be addressed in 3.4
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
+		if (matcher == null && useEarlyReturnIfMatcherIsNull) {
+			return elements;
+		}
+
+		if (!useCache) {
+			return super.filter(viewer, parent, elements);
+		}
+
+		Object[] filtered = cache.get(parent);
+		if (filtered == null) {
+			Boolean foundAny = foundAnyCache.get(parent);
+			if (foundAny != null && !foundAny.booleanValue()) {
+				filtered = EMPTY;
+			} else {
+				filtered = super.filter(viewer, parent, elements);
+			}
+			cache.put(parent, filtered);
+		}
+		return filtered;
+	}
+
+	/**
+	 * Returns true if any of the elements makes it through the filter. This
+	 * method uses caching if enabled; the computation is done in
+	 * computeAnyVisible.
+	 *
+	 * @param viewer
+	 * @param parent
+	 * @param elements
+	 *            the elements (must not be an empty array)
+	 * @return true if any of the elements makes it through the filter.
+	 */
+	private boolean isAnyVisible(Viewer viewer, Object parent, Object[] elements) {
+		if (matcher == null) {
+			return true;
+		}
+
+		if (!useCache) {
+			return computeAnyVisible(viewer, elements);
+		}
+
+		Object[] filtered = cache.get(parent);
+		if (filtered != null) {
+			return filtered.length > 0;
+		}
+		Boolean foundAny = foundAnyCache.get(parent);
+		if (foundAny == null) {
+			foundAny = computeAnyVisible(viewer, elements) ? Boolean.TRUE : Boolean.FALSE;
+			foundAnyCache.put(parent, foundAny);
+		}
+		return foundAny.booleanValue();
+	}
+
+	/**
+	 * Returns true if any of the elements makes it through the filter.
+	 *
+	 * @param viewer
+	 *            the viewer
+	 * @param elements
+	 *            the elements to test
+	 * @return <code>true</code> if any of the elements makes it through the
+	 *         filter
+	 */
+	private boolean computeAnyVisible(Viewer viewer, Object[] elements) {
+		boolean elementFound = false;
+		for (int i = 0; i < elements.length && !elementFound; i++) {
+			Object element = elements[i];
+			elementFound = isElementVisible(viewer, element);
+		}
+		return elementFound;
+	}
+
+	@Override
+	public final boolean select(Viewer viewer, Object parentElement, Object element) {
+		return isElementVisible(viewer, element);
+	}
+
+	/**
+	 * Sets whether a leading wildcard should be attached to each pattern
+	 * string.
+	 *
+	 * @param includeLeadingWildcard
+	 *            Whether a leading wildcard should be added.
+	 */
+	public final void setIncludeLeadingWildcard(final boolean includeLeadingWildcard) {
+		this.includeLeadingWildcard = includeLeadingWildcard;
+	}
+
+	/**
+	 * The pattern string for which this filter should select elements in the
+	 * viewer.
+	 *
+	 * @param patternString
+	 */
+	public void setPattern(String patternString) {
+		// these 2 strings allow the PatternFilter to be extended in
+		// 3.3 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
+		if ("org.eclipse.ui.keys.optimization.true".equals(patternString)) { //$NON-NLS-1$
+			useEarlyReturnIfMatcherIsNull = true;
+			return;
+		} else if ("org.eclipse.ui.keys.optimization.false".equals(patternString)) { //$NON-NLS-1$
+			useEarlyReturnIfMatcherIsNull = false;
+			return;
+		}
+		clearCaches();
+		if (patternString == null || patternString.equals("")) { //$NON-NLS-1$
+			matcher = null;
+		} else {
+			String pattern = patternString + "*"; //$NON-NLS-1$
+			if (includeLeadingWildcard) {
+				pattern = "*" + pattern; //$NON-NLS-1$
+			}
+			matcher = new StringMatcher(pattern, true, false);
+		}
+	}
+
+	/**
+	 * Clears the caches used for optimizing this filter. Needs to be called
+	 * whenever the tree content changes.
+	 */
+	/* package */void clearCaches() {
+		cache.clear();
+		foundAnyCache.clear();
+	}
+
+	/**
+	 * Answers whether the given String matches the pattern.
+	 *
+	 * @param string
+	 *            the String to test
+	 *
+	 * @return whether the string matches the pattern
+	 */
+	private boolean match(String string) {
+		if (matcher == null) {
+			return true;
+		}
+		return matcher.match(string);
+	}
+
+	/**
+	 * Answers whether the given element is a valid selection in the filtered
+	 * tree. For example, if a tree has items that are categorized, the category
+	 * itself may not be a valid selection since it is used merely to organize
+	 * the elements.
+	 *
+	 * @param element
+	 * @return true if this element is eligible for automatic selection
+	 */
+	public boolean isElementSelectable(Object element) {
+		return element != null;
+	}
+
+	/**
+	 * Answers whether the given element in the given viewer matches the filter
+	 * pattern. This is a default implementation that will show a leaf element
+	 * in the tree based on whether the provided filter text matches the text of
+	 * the given element's text, or that of it's children (if the element has
+	 * any).
+	 *
+	 * Subclasses may override this method.
+	 *
+	 * @param viewer
+	 *            the tree viewer in which the element resides
+	 * @param element
+	 *            the element in the tree to check for a match
+	 *
+	 * @return true if the element matches the filter pattern
+	 */
+	public boolean isElementVisible(Viewer viewer, Object element) {
+		return isParentMatch(viewer, element) || isLeafMatch(viewer, element);
+	}
+
+	/**
+	 * Check if the parent (category) is a match to the filter text. The default
+	 * behavior returns true if the element has at least one child element that
+	 * is a match with the filter text.
+	 *
+	 * Subclasses may override this method.
+	 *
+	 * @param viewer
+	 *            the viewer that contains the element
+	 * @param element
+	 *            the tree element to check
+	 * @return true if the given element has children that matches the filter
+	 *         text
+	 */
+	protected boolean isParentMatch(Viewer viewer, Object element) {
+		Object[] children = ((ITreeContentProvider) ((AbstractTreeViewer) viewer)
+				.getContentProvider()).getChildren(element);
+
+		if ((children != null) && (children.length > 0)) {
+			return isAnyVisible(viewer, element, children);
+		}
+		return false;
+	}
+
+	/**
+	 * Check if the current (leaf) element is a match with the filter text. The
+	 * default behavior checks that the label of the element is a match.
+	 *
+	 * Subclasses should override this method.
+	 *
+	 * @param viewer
+	 *            the viewer that contains the element
+	 * @param element
+	 *            the tree element to check
+	 * @return true if the given element's label matches the filter text
+	 */
+	protected boolean isLeafMatch(Viewer viewer, Object element) {
+		String labelText = ((ILabelProvider) ((StructuredViewer) viewer)
+				.getLabelProvider()).getText(element);
+
+		if (labelText == null) {
+			return false;
+		}
+		return wordMatches(labelText);
+	}
+
+	/**
+	 * Take the given filter text and break it down into words using a
+	 * BreakIterator.
+	 *
+	 * @param text
+	 * @return an array of words
+	 */
+	private String[] getWords(String text) {
+		List<String> words = new ArrayList<>();
+		// Break the text up into words, separating based on whitespace and
+		// common punctuation.
+		// Previously used String.split(..., "\\W"), where "\W" is a regular
+		// expression (see the Javadoc for class Pattern).
+		// Need to avoid both String.split and regular expressions, in order to
+		// compile against JCL Foundation (bug 80053).
+		// Also need to do this in an NL-sensitive way. The use of BreakIterator
+		// was suggested in bug 90579.
+		BreakIterator iter = BreakIterator.getWordInstance();
+		iter.setText(text);
+		int i = iter.first();
+		while (i != java.text.BreakIterator.DONE && i < text.length()) {
+			int j = iter.following(i);
+			if (j == java.text.BreakIterator.DONE) {
+				j = text.length();
+			}
+			// match the word
+			if (Character.isLetterOrDigit(text.charAt(i))) {
+				String word = text.substring(i, j);
+				words.add(word);
+			}
+			i = j;
+		}
+		return words.toArray(new String[words.size()]);
+	}
+
+	/**
+	 * Return whether or not if any of the words in text satisfy the match
+	 * critera.
+	 *
+	 * @param text
+	 *            the text to match
+	 * @return boolean <code>true</code> if one of the words in text satisifes
+	 *         the match criteria.
+	 */
+	protected boolean wordMatches(String text) {
+		if (text == null) {
+			return false;
+		}
+
+		// If the whole text matches we are all set
+		if (match(text)) {
+			return true;
+		}
+
+		// Otherwise check if any of the words of the text matches
+		String[] words = getWords(text);
+		for (int i = 0; i < words.length; i++) {
+			String word = words[i];
+			if (match(word)) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * Can be called by the filtered tree to turn on caching.
+	 *
+	 * @param useCache
+	 *            The useCache to set.
+	 */
+	void setUseCache(boolean useCache) {
+		this.useCache = useCache;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/SearchPattern.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/SearchPattern.java
new file mode 100644
index 0000000..9eb6429
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/SearchPattern.java
@@ -0,0 +1,679 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 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.workbench.swt.internal.copy;
+
+import org.eclipse.jface.util.Util;
+
+/**
+ * A copy of org.eclipse.ui.dialogs.SearchPattern
+ */
+public class SearchPattern {
+
+	// Rules for pattern matching: (exact, prefix, pattern) [ | case sensitive]
+	/**
+	 * Match rule: The search pattern matches exactly the search result, that
+	 * is, the source of the search result equals the search pattern. Search pattern
+	 * should start from lowerCase char.
+	 */
+	public static final int RULE_EXACT_MATCH = 0;
+
+	/**
+	 * Match rule: The search pattern is a prefix of the search result.
+	 */
+	public static final int RULE_PREFIX_MATCH = 0x0001;
+
+	/**
+	 * Match rule: The search pattern contains one or more wild cards ('*' or
+	 * '?'). A '*' wild-card can replace 0 or more characters in the search
+	 * result. A '?' wild-card replaces exactly 1 character in the search
+	 * result.
+	 */
+	public static final int RULE_PATTERN_MATCH = 0x0002;
+
+	/**
+	 * Match rule: The search pattern matches the search result only if cases
+	 * are the same. Can be combined to previous rules, e.g.
+	 * {@link #RULE_EXACT_MATCH} | {@link #RULE_CASE_SENSITIVE}
+	 */
+	public static final int RULE_CASE_SENSITIVE = 0x0008;
+
+	/**
+	 * Match rule: The search pattern is blank.
+	 */
+	public static final int RULE_BLANK_MATCH = 0x0020;
+
+	/**
+	 * Match rule: The search pattern contains a Camel Case expression. <br>
+	 * Examples:
+	 * <ul>
+	 * <li><code>NPE</code> type string pattern will match
+	 * <code>NullPointerException</code> and
+	 * <code>NpPermissionException</code> types,</li>
+	 * <li><code>NuPoEx</code> type string pattern will only match
+	 * <code>NullPointerException</code> type.</li>
+	 * </ul>
+	 *
+	 *
+	 * <br>
+	 * Can be combined to {@link #RULE_PREFIX_MATCH} match rule. For example,
+	 * when prefix match rule is combined with Camel Case match rule,
+	 * <code>"nPE"</code> pattern will match <code>nPException</code>. <br>
+	 * Match rule {@link #RULE_PATTERN_MATCH} may also be combined but both
+	 * rules will not be used simultaneously as they are mutually exclusive.
+	 * Used match rule depends on whether string pattern contains specific
+	 * pattern characters (e.g. '*' or '?') or not. If it does, then only
+	 * Pattern match rule will be used, otherwise only Camel Case match will be
+	 * used. For example, with <code>"NPE"</code> string pattern, search will
+	 * only use Camel Case match rule, but with <code>N*P*E*</code> string
+	 * pattern, it will use only Pattern match rule.
+	 *
+	 */
+	public static final int RULE_CAMELCASE_MATCH = 0x0080;
+
+	private int matchRule;
+
+	private String stringPattern;
+
+	private String initialPattern;
+
+	private StringMatcher stringMatcher;
+
+	private static final char END_SYMBOL = '<';
+
+	private static final char ANY_STRING = '*';
+
+	private static final char BLANK = ' ';
+
+	private int allowedRules;
+
+	/**
+	 * Creates new instance of SearchPattern Default allowedRules for it is
+	 * result of belong logic operation: ( RULE_EXACT_MATCH | RULE_PREFIX_MATCH |
+	 * RULE_PATTERN_MATCH | RULE_CAMELCASE_MATCH )
+	 *
+	 */
+	public SearchPattern() {
+		this(RULE_EXACT_MATCH | RULE_PREFIX_MATCH | RULE_PATTERN_MATCH
+				| RULE_CAMELCASE_MATCH | RULE_BLANK_MATCH);
+	}
+
+	/**
+	 * Creates a search pattern with the rule to apply for matching index keys.
+	 * It can be exact match, prefix match, pattern match or camelCase match.
+	 * Rule can also be combined with a case sensitivity flag.
+	 *
+	 * @param allowedRules
+	 *            one of {@link #RULE_EXACT_MATCH}, {@link #RULE_PREFIX_MATCH},
+	 *            {@link #RULE_PATTERN_MATCH}, {@link #RULE_CASE_SENSITIVE},
+	 *            {@link #RULE_CAMELCASE_MATCH} combined with one of following
+	 *            values: {@link #RULE_EXACT_MATCH}, {@link #RULE_PREFIX_MATCH},
+	 *            {@link #RULE_PATTERN_MATCH} or {@link #RULE_CAMELCASE_MATCH}.
+	 *            e.g. {@link #RULE_EXACT_MATCH} | {@link #RULE_CASE_SENSITIVE}
+	 *            if an exact and case sensitive match is requested,
+	 *            {@link #RULE_PREFIX_MATCH} if a prefix non case sensitive
+	 *            match is requested or {@link #RULE_EXACT_MATCH} if a non case
+	 *            sensitive and erasure match is requested.<br>
+	 *            Note also that default behavior for generic types/methods
+	 *            search is to find exact matches.
+	 */
+	public SearchPattern(int allowedRules) {
+		this.allowedRules = allowedRules;
+	}
+
+	/**
+	 * Gets string pattern used by matcher
+	 *
+	 * @return pattern
+	 */
+	public String getPattern() {
+		return this.stringPattern;
+	}
+
+	/**
+	 * @param stringPattern
+	 *            The stringPattern to set.
+	 */
+	public void setPattern(String stringPattern) {
+		this.initialPattern = stringPattern;
+		this.stringPattern = stringPattern;
+		initializePatternAndMatchRule(stringPattern);
+		matchRule = matchRule & this.allowedRules;
+		if (matchRule == RULE_PATTERN_MATCH) {
+			stringMatcher = new StringMatcher(this.stringPattern, true, false);
+		}
+	}
+
+	/**
+	 * Matches text with pattern. matching is determine by matchKind.
+	 *
+	 * @param text
+	 * @return true if search pattern was matched with text false in other way
+	 */
+	public boolean matches(String text) {
+		switch (matchRule) {
+		case RULE_BLANK_MATCH:
+			return true;
+		case RULE_PATTERN_MATCH:
+			return stringMatcher.match(text);
+		case RULE_EXACT_MATCH:
+			return stringPattern.equalsIgnoreCase(text);
+		case RULE_CAMELCASE_MATCH:
+			if (camelCaseMatch(stringPattern, text)) {
+				return true;
+			}
+			//$FALL-THROUGH$
+			default:
+			return startsWithIgnoreCase(text, stringPattern);
+		}
+	}
+
+	private void initializePatternAndMatchRule(String pattern) {
+		int length = pattern.length();
+		if (length == 0) {
+			matchRule = RULE_BLANK_MATCH;
+			stringPattern = pattern;
+			return;
+		}
+		char last = pattern.charAt(length - 1);
+
+		if (pattern.indexOf('*') != -1 || pattern.indexOf('?') != -1) {
+			matchRule = RULE_PATTERN_MATCH;
+			switch (last) {
+			case END_SYMBOL:
+			case BLANK:
+				stringPattern = pattern.substring(0, length - 1);
+				break;
+			case ANY_STRING:
+				stringPattern = pattern;
+				break;
+			default:
+				stringPattern = pattern + ANY_STRING;
+			}
+			return;
+		}
+
+		if (validateMatchRule(pattern, RULE_CAMELCASE_MATCH) == RULE_CAMELCASE_MATCH) {
+			matchRule = RULE_CAMELCASE_MATCH;
+			stringPattern = pattern;
+			return;
+		}
+
+		if (last == END_SYMBOL || last == BLANK) {
+			matchRule = RULE_EXACT_MATCH;
+			stringPattern = pattern.substring(0, length - 1);
+			return;
+		}
+
+		matchRule = RULE_PREFIX_MATCH;
+		stringPattern = pattern;
+
+	}
+
+	/**
+	 * @param text
+	 * @param prefix
+	 * @return true if text starts with given prefix, ignoring case false in
+	 *         other way
+	 */
+	private boolean startsWithIgnoreCase(String text, String prefix) {
+		int textLength = text.length();
+		int prefixLength = prefix.length();
+		if (textLength < prefixLength)
+			return false;
+		for (int i = prefixLength - 1; i >= 0; i--) {
+			if (Character.toLowerCase(prefix.charAt(i)) != Character
+					.toLowerCase(text.charAt(i)))
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Answers true if the pattern matches the given name using CamelCase rules,
+	 * or false otherwise. CamelCase matching does NOT accept explicit
+	 * wild-cards '*' and '?' and is inherently case sensitive. <br>
+	 * CamelCase denotes the convention of writing compound names without
+	 * spaces, and capitalizing every term. This function recognizes both upper
+	 * and lower CamelCase, depending whether the leading character is
+	 * capitalized or not. The leading part of an upper CamelCase pattern is
+	 * assumed to contain a sequence of capitals which are appearing in the
+	 * matching name; e.g. 'NPE' will match 'NullPointerException', but not
+	 * 'NewPerfData'. A lower CamelCase pattern uses a lowercase first
+	 * character. In Java, type names follow the upper CamelCase convention,
+	 * whereas method or field names follow the lower CamelCase convention. <br>
+	 * The pattern may contain lowercase characters, which will be match in a
+	 * case sensitive way. These characters must appear in sequence in the name.
+	 * For instance, 'NPExcep' will match 'NullPointerException', but not
+	 * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but
+	 * not 'NoPointerException'. <br>
+	 * <br>
+	 * Examples:
+	 * <ol>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NPE&quot;
+	 *                 name = NullPointerException / NoPermissionException
+	 *                 result =&gt; true
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NuPoEx&quot;
+	 *                 name = NullPointerException
+	 *                 result =&gt; true
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;npe&quot;
+	 *                 name = NullPointerException
+	 *                 result =&gt; false
+	 * </pre>
+	 *
+	 * </li>
+	 * </ol>
+	 *
+	 * @param pattern
+	 *            the given pattern
+	 * @param name
+	 *            the given name
+	 * @return true if the pattern matches the given name, false otherwise
+	 *
+	 */
+	private boolean camelCaseMatch(String pattern, String name) {
+		if (pattern == null)
+			return true; // null pattern is equivalent to '*'
+		if (name == null)
+			return false; // null name cannot match
+
+		return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name
+				.length());
+	}
+
+	/**
+	 * Answers true if a sub-pattern matches the subpart of the given name using
+	 * CamelCase rules, or false otherwise. CamelCase matching does NOT accept
+	 * explicit wild-cards '*' and '?' and is inherently case sensitive. Can
+	 * match only subset of name/pattern, considering end positions as
+	 * non-inclusive. The subpattern is defined by the patternStart and
+	 * patternEnd positions. <br>
+	 * CamelCase denotes the convention of writing compound names without
+	 * spaces, and capitalizing every term. This function recognizes both upper
+	 * and lower CamelCase, depending whether the leading character is
+	 * capitalized or not. The leading part of an upper CamelCase pattern is
+	 * assumed to contain a sequence of capitals which are appearing in the
+	 * matching name; e.g. 'NPE' will match 'NullPointerException', but not
+	 * 'NewPerfData'. A lower CamelCase pattern uses a lowercase first
+	 * character. In Java, type names follow the upper CamelCase convention,
+	 * whereas method or field names follow the lower CamelCase convention. <br>
+	 * The pattern may contain lowercase characters, which will be match in a
+	 * case sensitive way. These characters must appear in sequence in the name.
+	 * For instance, 'NPExcep' will match 'NullPointerException', but not
+	 * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but
+	 * not 'NoPointerException'. <br>
+	 * <br>
+	 * Examples:
+	 * <ol>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NPE&quot;
+	 *                 patternStart = 0
+	 *                 patternEnd = 3
+	 *                 name = NullPointerException
+	 *                 nameStart = 0
+	 *                 nameEnd = 20
+	 *                 result =&gt; true
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NPE&quot;
+	 *                 patternStart = 0
+	 *                 patternEnd = 3
+	 *                 name = NoPermissionException
+	 *                 nameStart = 0
+	 *                 nameEnd = 21
+	 *                 result =&gt; true
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NuPoEx&quot;
+	 *                 patternStart = 0
+	 *                 patternEnd = 6
+	 *                 name = NullPointerException
+	 *                 nameStart = 0
+	 *                 nameEnd = 20
+	 *                 result =&gt; true
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;NuPoEx&quot;
+	 *                 patternStart = 0
+	 *                 patternEnd = 6
+	 *                 name = NoPermissionException
+	 *                 nameStart = 0
+	 *                 nameEnd = 21
+	 *                 result =&gt; false
+	 * </pre>
+	 *
+	 * </li>
+	 * <li>
+	 *
+	 * <pre>
+	 *                 pattern = &quot;npe&quot;
+	 *                 patternStart = 0
+	 *                 patternEnd = 3
+	 *                 name = NullPointerException
+	 *                 nameStart = 0
+	 *                 nameEnd = 20
+	 *                 result =&gt; false
+	 * </pre>
+	 *
+	 * </li>
+	 * </ol>
+	 *
+	 * @param pattern
+	 *            the given pattern
+	 * @param patternStart
+	 *            the start index of the pattern, inclusive
+	 * @param patternEnd
+	 *            the end index of the pattern, exclusive
+	 * @param name
+	 *            the given name
+	 * @param nameStart
+	 *            the start index of the name, inclusive
+	 * @param nameEnd
+	 *            the end index of the name, exclusive
+	 * @return true if a sub-pattern matches the subpart of the given name,
+	 *         false otherwise
+	 */
+	private boolean camelCaseMatch(String pattern, int patternStart,
+			int patternEnd, String name, int nameStart, int nameEnd) {
+		if (name == null)
+			return false; // null name cannot match
+		if (pattern == null)
+			return true; // null pattern is equivalent to '*'
+		if (patternEnd < 0)
+			patternEnd = pattern.length();
+		if (nameEnd < 0)
+			nameEnd = name.length();
+
+		if (patternEnd <= patternStart)
+			return nameEnd <= nameStart;
+		if (nameEnd <= nameStart)
+			return false;
+		// check first pattern char
+		if (name.charAt(nameStart) != pattern.charAt(patternStart)) {
+			// first char must strictly match (upper/lower)
+			return false;
+		}
+
+		int patternLength = patternEnd;
+
+		if (pattern.charAt(patternEnd - 1) == END_SYMBOL || pattern.charAt(patternEnd - 1) == BLANK )
+			patternLength = patternEnd - 1;
+
+
+		char patternChar, nameChar;
+		int iPattern = patternStart;
+		int iName = nameStart;
+
+		// Main loop is on pattern characters
+		while (true) {
+
+			iPattern++;
+			iName++;
+
+				if (iPattern == patternEnd) {
+				// We have exhausted pattern, so it's a match
+				return true;
+			}
+
+			if (iName == nameEnd) {
+				if (iPattern == patternLength)
+					return true;
+				// We have exhausted name (and not pattern), so it's not a match
+				return false;
+			}
+
+			// For as long as we're exactly matching, bring it on (even if it's
+			// a lower case character)
+			if ((patternChar = pattern.charAt(iPattern)) == name.charAt(iName)) {
+				continue;
+			}
+
+			// If characters are not equals, then it's not a match if
+			// patternChar is lowercase
+			if (!isPatternCharAllowed(patternChar))
+				return false;
+
+			// patternChar is uppercase, so let's find the next uppercase in
+			// name
+			while (true) {
+				if (iName == nameEnd) {
+					if ((iPattern == patternLength) && (patternChar == END_SYMBOL || patternChar == BLANK))
+						return true;
+					return false;
+				}
+
+				nameChar = name.charAt(iName);
+
+				if ((iPattern == patternLength) && (patternChar == END_SYMBOL || patternChar == BLANK)) {
+					if (isNameCharAllowed(nameChar)) {
+						return false;
+					}
+					iName++;
+					continue;
+				}
+
+				if (Character.isDigit(nameChar)) {
+					// nameChar is digit => break if the digit is current pattern character otherwise consume it
+					if (patternChar == nameChar) break;
+					iName++;
+				} else if (!isNameCharAllowed(nameChar)) {
+					// nameChar is lowercase
+					iName++;
+				// nameChar is uppercase...
+				} else if (patternChar != nameChar) {
+					// .. and it does not match patternChar, so it's not a match
+					return false;
+				} else {
+					// .. and it matched patternChar. Back to the big loop
+					break;
+				}
+			}
+			// At this point, either name has been exhausted, or it is at an
+			// uppercase letter.
+			// Since pattern is also at an uppercase letter
+		}
+	}
+
+	/**
+	 * Checks pattern's character is allowed for specified set. It could be
+	 * override if you want change logic of camelCaseMatch methods.
+	 *
+	 * @param patternChar
+	 * @return true if patternChar is in set of allowed characters for pattern
+	 */
+	protected boolean isPatternCharAllowed(char patternChar) {
+		return patternChar == END_SYMBOL || patternChar == BLANK
+			|| Character.isUpperCase(patternChar) || Character.isDigit(patternChar);
+	}
+
+	/**
+	 * Checks character of element's name is allowed for specified set. It could
+	 * be override if you want change logic of camelCaseMatch methods.
+	 *
+	 * @param nameChar -
+	 *            name of searched element
+	 * @return if nameChar is in set of allowed characters for name of element
+	 */
+	protected boolean isNameCharAllowed(char nameChar) {
+		return Character.isUpperCase(nameChar);
+	}
+
+	/**
+	 * Returns the rule to apply for matching keys. Can be exact match, prefix
+	 * match, pattern match or camelcase match. Rule can also be combined with a
+	 * case sensitivity flag.
+	 *
+	 * @return one of RULE_EXACT_MATCH, RULE_PREFIX_MATCH, RULE_PATTERN_MATCH,
+	 *         RULE_CAMELCASE_MATCH, combined with RULE_CASE_SENSITIVE, e.g.
+	 *         RULE_EXACT_MATCH | RULE_CASE_SENSITIVE if an exact and case
+	 *         sensitive match is requested, or RULE_PREFIX_MATCH if a prefix
+	 *         non case sensitive match is requested.
+	 */
+	public final int getMatchRule() {
+		return this.matchRule;
+	}
+
+	/**
+	 * Validate compatibility between given string pattern and match rule. <br>
+	 * Optimized (ie. returned match rule is modified) combinations are:
+	 * <ul>
+	 * <li>{@link #RULE_PATTERN_MATCH} without any '*' or '?' in string pattern: pattern match bit
+	 * is unset,</li>
+	 * <li>{@link #RULE_PATTERN_MATCH} and {@link #RULE_PREFIX_MATCH} bits simultaneously set:
+	 * prefix match bit is unset,</li>
+	 * <li>{@link #RULE_PATTERN_MATCH} and {@link #RULE_CAMELCASE_MATCH} bits simultaneously set:
+	 * camel case match bit is unset,</li>
+	 * <li>{@link #RULE_CAMELCASE_MATCH} with invalid combination of uppercase and lowercase
+	 * characters: camel case match bit is unset and replaced with prefix match pattern,</li>
+	 * <li>{@link #RULE_CAMELCASE_MATCH} combined with {@link #RULE_PREFIX_MATCH} and
+	 * {@link #RULE_CASE_SENSITIVE} bits is reduced to only {@link #RULE_CAMELCASE_MATCH} as Camel
+	 * Case search is already prefix and case sensitive,</li>
+	 * </ul>
+	 * <br>
+	 * Rejected (ie. returned match rule -1) combinations are:
+	 * <ul>
+	 * <li>{@link #RULE_PATTERN_MATCH} with any other match mode bit set,</li>
+	 * </ul>
+	 *
+	 * @param stringPattern The string pattern
+	 * @param matchRule The match rule
+	 * @return Optimized valid match rule or -1 if an incompatibility was detected.
+	 */
+	private int validateMatchRule(String stringPattern, int matchRule) {
+
+		// Verify Pattern match rule
+		int starIndex = stringPattern.indexOf('*');
+		int questionIndex = stringPattern.indexOf('?');
+		if (starIndex < 0 && questionIndex < 0) {
+			// reset pattern match bit if any
+			matchRule &= ~RULE_PATTERN_MATCH;
+		} else {
+			// force Pattern rule
+			matchRule |= RULE_PATTERN_MATCH;
+		}
+		if ((matchRule & RULE_PATTERN_MATCH) != 0) {
+			// remove Camel Case and Prefix match bits if any
+			matchRule &= ~RULE_CAMELCASE_MATCH;
+			matchRule &= ~RULE_PREFIX_MATCH;
+		}
+
+		// Verify Camel Case match rule
+		if ((matchRule & RULE_CAMELCASE_MATCH) != 0) {
+			// Verify sting pattern validity
+			int length = stringPattern.length();
+			boolean validCamelCase = true;
+			for (int i = 0; i < length && validCamelCase; i++) {
+				char ch = stringPattern.charAt(i);
+				validCamelCase = isValidCamelCaseChar(ch);
+			}
+			validCamelCase = validCamelCase && Character.isUpperCase(stringPattern.charAt(0));
+			// Verify bits compatibility
+			if (validCamelCase) {
+				if ((matchRule & RULE_PREFIX_MATCH) != 0) {
+					if ((matchRule & RULE_CASE_SENSITIVE) != 0) {
+						// This is equivalent to Camel Case match rule
+						matchRule &= ~RULE_PREFIX_MATCH;
+						matchRule &= ~RULE_CASE_SENSITIVE;
+					}
+				}
+			} else {
+				matchRule &= ~RULE_CAMELCASE_MATCH;
+				if ((matchRule & RULE_PREFIX_MATCH) == 0) {
+					matchRule |= RULE_PREFIX_MATCH;
+					matchRule |= RULE_CASE_SENSITIVE;
+				}
+			}
+		}
+		return matchRule;
+	}
+
+	/**
+	 * Check if character is valid camelCase character
+	 *
+	 * @param ch
+	 *            character to be validated
+	 * @return true if character is valid
+	 */
+	protected boolean isValidCamelCaseChar(char ch) {
+		return true;
+	}
+
+	/**
+	 * Tells whether the given <code>SearchPattern</code> equals this pattern.
+	 *
+	 * @param pattern
+	 *            pattern to be checked
+	 * @return true if the given pattern equals this search pattern
+	 */
+	public boolean equalsPattern(SearchPattern pattern) {
+		return trimWildcardCharacters(pattern.initialPattern).equals(
+				trimWildcardCharacters(this.initialPattern));
+	}
+
+	/**
+	 * Tells whether the given <code>SearchPattern</code> is a sub-pattern of
+	 * this pattern.
+	 * <p>
+	 * <i>WARNING: This method is <b>not</b> defined in reading order, i.e.
+	 * <code>a.isSubPattern(b)</code> is <code>true</code> iff
+	 * <code>b</code> is a sub-pattern of <code>a</code>, and not vice-versa.
+	 * </i>
+	 * </p>
+	 *
+	 * @param pattern
+	 *            pattern to be checked
+	 * @return true if the given pattern is a sub pattern of this search pattern
+	 */
+	public boolean isSubPattern(SearchPattern pattern) {
+		return trimWildcardCharacters(pattern.initialPattern).startsWith(
+				trimWildcardCharacters(this.initialPattern));
+	}
+
+	/**
+	 * Trims sequences of '*' characters
+	 *
+	 * @param pattern
+	 *            string to be trimmed
+	 * @return trimmed pattern
+	 */
+	private String trimWildcardCharacters(String pattern) {
+		return Util.replaceAll(pattern, "\\*+", "\\*"); //$NON-NLS-1$ //$NON-NLS-2$		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ShowViewDialog.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ShowViewDialog.java
new file mode 100644
index 0000000..64a4925
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ShowViewDialog.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 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 - bug 128526, bug 128529
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 440381
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.swt.internal.copy;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator;
+import org.eclipse.e4.ui.model.LocalizationHelper;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogLabelKeys;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.PopupDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Point;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Based on org.eclipse.ui.internal.dialogs.ShowViewDialog.
+ */
+public class ShowViewDialog extends Dialog implements
+		ISelectionChangedListener, IDoubleClickListener {
+
+	private static final String DIALOG_SETTING_SECTION_NAME = "ShowViewDialog"; //$NON-NLS-1$
+
+	private static final int LIST_HEIGHT = 300;
+
+	private static final int LIST_WIDTH = 250;
+
+	private static final String STORE_EXPANDED_CATEGORIES_ID = DIALOG_SETTING_SECTION_NAME
+			+ ".STORE_EXPANDED_CATEGORIES_ID"; //$NON-NLS-1$
+
+	private static final String STORE_SELECTED_VIEW_ID = DIALOG_SETTING_SECTION_NAME
+			+ ".STORE_SELECTED_VIEW_ID"; //$NON-NLS-1$
+
+	private FilteredTree filteredTree;
+
+	private Button okButton;
+
+	private MApplication application;
+	private MPartDescriptor[] viewDescs = new MPartDescriptor[0];
+
+	private Label descriptionHint;
+
+	private IEclipseContext context;
+
+	/**
+	 * Constructs a new ShowViewDialog.
+	 *
+	 * @param window
+	 *            the workbench window
+	 * @param viewReg
+	 *            the view registry
+	 */
+	public ShowViewDialog(Shell shell, MApplication application,
+			IEclipseContext context) {
+		super(shell);
+		this.application = application;
+		this.context = context;
+	}
+
+	/**
+	 * This method is called if a button has been pressed.
+	 */
+	@Override
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			saveWidgetValues();
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	/**
+	 * Notifies that the cancel button of this dialog has been pressed.
+	 */
+	@Override
+	protected void cancelPressed() {
+		viewDescs = new MPartDescriptor[0];
+		super.cancelPressed();
+	}
+
+	@Override
+	protected void configureShell(Shell shell) {
+		super.configureShell(shell);
+		shell.setText(WorkbenchSWTMessages.ShowView_shellTitle);
+		// PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
+		// IWorkbenchHelpContextIds.SHOW_VIEW_DIALOG);
+	}
+
+	/**
+	 * Adds buttons to this dialog's button bar.
+	 * <p>
+	 * The default implementation of this framework method adds standard ok and
+	 * cancel buttons using the <code>createButton</code> framework method.
+	 * Subclasses may override.
+	 * </p>
+	 *
+	 * @param parent
+	 *            the button bar composite
+	 */
+	@Override
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID,
+				JFaceResources.getString(IDialogLabelKeys.OK_LABEL_KEY), true);
+		createButton(parent, IDialogConstants.CANCEL_ID,
+				JFaceResources.getString(IDialogLabelKeys.CANCEL_LABEL_KEY),
+				false);
+		updateButtons();
+	}
+
+	/**
+	 * Creates and returns the contents of the upper part of this dialog (above
+	 * the button bar).
+	 *
+	 * @param parent
+	 *            the parent composite to contain the dialog area
+	 * @return the dialog area control
+	 */
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		// Run super.
+		Composite composite = (Composite) super.createDialogArea(parent);
+		composite.setFont(parent.getFont());
+
+		createFilteredTreeViewer(composite);
+
+		layoutTopControl(filteredTree);
+
+		// Use F2... label
+		descriptionHint = new Label(composite, SWT.WRAP);
+		descriptionHint.setText(WorkbenchSWTMessages.ShowView_selectViewHelp);
+		descriptionHint.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
+				false));
+		descriptionHint.setVisible(false);
+
+		// Restore the last state
+		restoreWidgetValues();
+
+		applyDialogFont(composite);
+
+		// Return results.
+		return composite;
+	}
+
+	/**
+	 * Create a new filtered tree viewer in the parent.
+	 *
+	 * @param parent
+	 *            the parent <code>Composite</code>.
+	 */
+	private void createFilteredTreeViewer(Composite parent) {
+		PatternFilter filter = new ViewPatternFilter(context);
+		int styleBits = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
+		filteredTree = new FilteredTree(parent, styleBits, filter);
+		filteredTree.setBackground(parent.getDisplay().getSystemColor(
+				SWT.COLOR_WIDGET_BACKGROUND));
+
+		TreeViewer treeViewer = filteredTree.getViewer();
+
+		treeViewer.setLabelProvider(new ViewLabelProvider(context));
+		treeViewer.setContentProvider(new ViewContentProvider(application));
+		treeViewer.setComparator(new ViewComparator());
+		treeViewer.setInput(application);
+		treeViewer.addSelectionChangedListener(this);
+		treeViewer.addDoubleClickListener(this);
+		treeViewer.getControl().addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent e) {
+				handleTreeViewerKeyPressed(e);
+			}
+		});
+
+		// if the tree has only one or zero views, disable the filter text
+		// control
+		if (hasAtMostOneView(filteredTree.getViewer())) {
+			Text filterText = filteredTree.getFilterControl();
+			if (filterText != null) {
+				filterText.setEnabled(false);
+			}
+		}
+	}
+
+	/**
+	 * Return whether or not there are less than two views in the list.
+	 *
+	 * @param tree
+	 * @return <code>true</code> if there are less than two views in the list.
+	 */
+	private boolean hasAtMostOneView(TreeViewer tree) {
+		ITreeContentProvider contentProvider = (ITreeContentProvider) tree
+				.getContentProvider();
+		Object[] children = contentProvider.getElements(tree.getInput());
+
+		if (children.length <= 1) {
+			if (children.length == 0) {
+				return true;
+			}
+			return !contentProvider.hasChildren(children[0]);
+		}
+		return false;
+	}
+
+	@Override
+	public void doubleClick(DoubleClickEvent event) {
+		IStructuredSelection s = (IStructuredSelection) event.getSelection();
+		Object element = s.getFirstElement();
+		if (filteredTree.getViewer().isExpandable(element)) {
+			filteredTree.getViewer().setExpandedState(element,
+					!filteredTree.getViewer().getExpandedState(element));
+		} else if (viewDescs.length > 0) {
+			saveWidgetValues();
+			setReturnCode(OK);
+			close();
+		}
+	}
+
+	/**
+	 * Return the dialog store to cache values into
+	 */
+	protected IDialogSettings getDialogSettings() {
+		IDialogSettings workbenchSettings = WorkbenchSWTActivator.getDefault()
+				.getDialogSettings();
+		IDialogSettings section = workbenchSettings
+				.getSection(DIALOG_SETTING_SECTION_NAME);
+		if (section == null) {
+			section = workbenchSettings
+					.addNewSection(DIALOG_SETTING_SECTION_NAME);
+		}
+		return section;
+	}
+
+	/**
+	 * Returns the descriptors for the selected views.
+	 *
+	 * @return the descriptors for the selected views
+	 */
+	public MPartDescriptor[] getSelection() {
+		return viewDescs;
+	}
+
+	/**
+	 * Layout the top control.
+	 *
+	 * @param control
+	 *            the control.
+	 */
+	private void layoutTopControl(Control control) {
+		GridData spec = new GridData(GridData.FILL_BOTH);
+		spec.widthHint = LIST_WIDTH;
+		spec.heightHint = LIST_HEIGHT;
+		control.setLayoutData(spec);
+	}
+
+	/**
+	 * Use the dialog store to restore widget values to the values that they
+	 * held last time this dialog was used to completion.
+	 */
+	protected void restoreWidgetValues() {
+		IDialogSettings settings = getDialogSettings();
+
+		String[] expandedCategoryIds = settings
+				.getArray(STORE_EXPANDED_CATEGORIES_ID);
+		if (expandedCategoryIds == null)
+			return;
+
+		if (expandedCategoryIds.length > 0)
+			filteredTree.getViewer().setExpandedElements(expandedCategoryIds);
+
+		String selectedPartId = settings.get(STORE_SELECTED_VIEW_ID);
+		if (selectedPartId != null) {
+			List<MPartDescriptor> descriptors = application.getDescriptors();
+			for (MPartDescriptor descriptor : descriptors) {
+				if (selectedPartId.equals(descriptor.getElementId())) {
+					filteredTree.getViewer().setSelection(
+							new StructuredSelection(descriptor), true);
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Since OK was pressed, write widget values to the dialog store so that
+	 * they will persist into the next invocation of this dialog
+	 */
+	protected void saveWidgetValues() {
+		IDialogSettings settings = getDialogSettings();
+
+		// Collect the ids of the all expanded categories
+		Object[] expandedElements = filteredTree.getViewer()
+				.getExpandedElements();
+		String[] expandedCategoryIds = new String[expandedElements.length];
+		for (int i = 0; i < expandedElements.length; ++i) {
+			if (expandedElements[i] instanceof MPartDescriptor)
+				expandedCategoryIds[i] = ((MPartDescriptor) expandedElements[i])
+						.getElementId();
+			else
+				expandedCategoryIds[i] = expandedElements[i].toString();
+		}
+
+		// Save them for next time.
+		settings.put(STORE_EXPANDED_CATEGORIES_ID, expandedCategoryIds);
+
+		String selectedViewId = ""; //$NON-NLS-1$
+		if (viewDescs.length > 0) {
+			// in the case of a multi-selection, it's probably less confusing
+			// to store just the first rather than the whole multi-selection
+			selectedViewId = viewDescs[0].getElementId();
+		}
+		settings.put(STORE_SELECTED_VIEW_ID, selectedViewId);
+	}
+
+	/**
+	 * Notifies that the selection has changed.
+	 *
+	 * @param event
+	 *            event object describing the change
+	 */
+	@Override
+	public void selectionChanged(SelectionChangedEvent event) {
+		updateSelection(event);
+		updateButtons();
+		String tooltip = "";
+		if (viewDescs.length > 0) {
+			tooltip = viewDescs[0].getTooltip();
+			tooltip = LocalizationHelper.getLocalized(tooltip, viewDescs[0],
+					context);
+		}
+		boolean hasTooltip = (tooltip == null) ? false : tooltip.length() > 0;
+		descriptionHint.setVisible(viewDescs.length == 1 && hasTooltip);
+	}
+
+	/**
+	 * Update the button enablement state.
+	 */
+	protected void updateButtons() {
+		if (okButton != null) {
+			okButton.setEnabled(getSelection().length > 0);
+		}
+	}
+
+	/**
+	 * Update the selection object.
+	 */
+	protected void updateSelection(SelectionChangedEvent event) {
+		ArrayList<MPartDescriptor> descs = new ArrayList<>();
+		IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+		for (Iterator<?> i = sel.iterator(); i.hasNext();) {
+			Object o = i.next();
+			if (o instanceof MPartDescriptor) {
+				descs.add((MPartDescriptor) o);
+			}
+		}
+
+		viewDescs = new MPartDescriptor[descs.size()];
+		descs.toArray(viewDescs);
+	}
+
+	@Override
+	protected IDialogSettings getDialogBoundsSettings() {
+		return getDialogSettings();
+	}
+
+	void handleTreeViewerKeyPressed(KeyEvent event) {
+		// popup the description for the selected view
+		if (descriptionHint.isVisible() && event.keyCode == SWT.F2
+				&& event.stateMask == 0) {
+			// FIXME RAP getStructuredSelection()
+			ITreeSelection selection = (ITreeSelection) filteredTree.getViewer().getSelection();
+			// only show description if one view is selected
+			if (selection.size() == 1) {
+				Object o = selection.getFirstElement();
+				if (o instanceof MPartDescriptor) {
+					String description = ((MPartDescriptor) o).getTooltip();
+					description = LocalizationHelper.getLocalized(description,
+							(MPartDescriptor) o, context);
+					if (description != null && description.length() == 0)
+						description = WorkbenchSWTMessages.ShowView_noDesc;
+					popUp(description);
+				}
+			}
+		}
+	}
+
+	private void popUp(final String description) {
+		new PopupDialog(filteredTree.getShell(), PopupDialog.HOVER_SHELLSTYLE,
+				true, false, false, false, false, null, null) {
+			private static final int CURSOR_SIZE = 15;
+
+			@Override
+			protected Point getInitialLocation(Point initialSize) {
+				// show popup relative to cursor
+				Display display = getShell().getDisplay();
+				Point location = display.getCursorLocation();
+				location.x += CURSOR_SIZE;
+				location.y += CURSOR_SIZE;
+				return location;
+			}
+
+			@Override
+			protected Control createDialogArea(Composite parent) {
+				Label label = new Label(parent, SWT.WRAP);
+				label.setText(description);
+				label.addFocusListener(new FocusAdapter() {
+					@Override
+					public void focusLost(FocusEvent event) {
+						close();
+					}
+				});
+				// Use the compact margins employed by PopupDialog.
+				GridData gd = new GridData(GridData.BEGINNING
+						| GridData.FILL_BOTH);
+				gd.horizontalIndent = PopupDialog.POPUP_HORIZONTALSPACING;
+				gd.verticalIndent = PopupDialog.POPUP_VERTICALSPACING;
+				label.setLayoutData(gd);
+				return label;
+			}
+		}.open();
+	}
+
+	@Override
+	protected boolean isResizable() {
+		return true;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/StringMatcher.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/StringMatcher.java
new file mode 100644
index 0000000..670185d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/StringMatcher.java
@@ -0,0 +1,495 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 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.workbench.swt.internal.copy;
+
+import java.util.Vector;
+
+/**
+ * Based on org.eclipse.ui.internal.misc.StringMatcher.
+ */
+public class StringMatcher {
+	protected String fPattern;
+
+	protected int fLength; // pattern length
+
+	protected boolean fIgnoreWildCards;
+
+	protected boolean fIgnoreCase;
+
+	protected boolean fHasLeadingStar;
+
+	protected boolean fHasTrailingStar;
+
+	protected String fSegments[]; // the given pattern is split into * separated
+									// segments
+
+	/* boundary value beyond which we don't need to search in the text */
+	protected int fBound = 0;
+
+	protected static final char fSingleWildCard = '\u0000';
+
+	public static class Position {
+		int start; // inclusive
+
+		int end; // exclusive
+
+		public Position(int start, int end) {
+			this.start = start;
+			this.end = end;
+		}
+
+		public int getStart() {
+			return start;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+	}
+
+	/**
+	 * StringMatcher constructor takes in a String object that is a simple
+	 * pattern which may contain '*' for 0 and many characters and '?' for
+	 * exactly one character.
+	 *
+	 * Literal '*' and '?' characters must be escaped in the pattern e.g., "\*"
+	 * means literal "*", etc.
+	 *
+	 * Escaping any other character (including the escape character itself),
+	 * just results in that character in the pattern. e.g., "\a" means "a" and
+	 * "\\" means "\"
+	 *
+	 * If invoking the StringMatcher with string literals in Java, don't forget
+	 * escape characters are represented by "\\".
+	 *
+	 * @param pattern
+	 *            the pattern to match text against
+	 * @param ignoreCase
+	 *            if true, case is ignored
+	 * @param ignoreWildCards
+	 *            if true, wild cards and their escape sequences are ignored
+	 *            (everything is taken literally).
+	 */
+	public StringMatcher(String pattern, boolean ignoreCase,
+			boolean ignoreWildCards) {
+		if (pattern == null) {
+			throw new IllegalArgumentException();
+		}
+		fIgnoreCase = ignoreCase;
+		fIgnoreWildCards = ignoreWildCards;
+		fPattern = pattern;
+		fLength = pattern.length();
+
+		if (fIgnoreWildCards) {
+			parseNoWildCards();
+		} else {
+			parseWildCards();
+		}
+	}
+
+	/**
+	 * Find the first occurrence of the pattern between <code>start</code
+	 * )(inclusive) and <code>end</code>(exclusive).
+	 *
+	 * @param text
+	 *            the String object to search in
+	 * @param start
+	 *            the starting index of the search range, inclusive
+	 * @param end
+	 *            the ending index of the search range, exclusive
+	 * @return an <code>StringMatcher.Position</code> object that keeps the
+	 *         starting (inclusive) and ending positions (exclusive) of the
+	 *         first occurrence of the pattern in the specified range of the
+	 *         text; return null if not found or subtext is empty (start==end).
+	 *         A pair of zeros is returned if pattern is empty string Note that
+	 *         for pattern like "*abc*" with leading and trailing stars,
+	 *         position of "abc" is returned. For a pattern like"*??*" in text
+	 *         "abcdf", (1,3) is returned
+	 */
+	public StringMatcher.Position find(String text, int start, int end) {
+		if (text == null) {
+			throw new IllegalArgumentException();
+		}
+
+		int tlen = text.length();
+		if (start < 0) {
+			start = 0;
+		}
+		if (end > tlen) {
+			end = tlen;
+		}
+		if (end < 0 || start >= end) {
+			return null;
+		}
+		if (fLength == 0) {
+			return new Position(start, start);
+		}
+		if (fIgnoreWildCards) {
+			int x = posIn(text, start, end);
+			if (x < 0) {
+				return null;
+			}
+			return new Position(x, x + fLength);
+		}
+
+		int segCount = fSegments.length;
+		if (segCount == 0) {
+			return new Position(start, end);
+		}
+
+		int curPos = start;
+		int matchStart = -1;
+		int i;
+		for (i = 0; i < segCount && curPos < end; ++i) {
+			String current = fSegments[i];
+			int nextMatch = regExpPosIn(text, curPos, end, current);
+			if (nextMatch < 0) {
+				return null;
+			}
+			if (i == 0) {
+				matchStart = nextMatch;
+			}
+			curPos = nextMatch + current.length();
+		}
+		if (i < segCount) {
+			return null;
+		}
+		return new Position(matchStart, curPos);
+	}
+
+	/**
+	 * match the given <code>text</code> with the pattern
+	 *
+	 * @return true if matched otherwise false
+	 * @param text
+	 *            a String object
+	 */
+	public boolean match(String text) {
+		if (text == null) {
+			return false;
+		}
+		return match(text, 0, text.length());
+	}
+
+	/**
+	 * Given the starting (inclusive) and the ending (exclusive) positions in
+	 * the <code>text</code>, determine if the given substring matches with
+	 * aPattern
+	 *
+	 * @return true if the specified portion of the text matches the pattern
+	 * @param text
+	 *            a String object that contains the substring to match
+	 * @param start
+	 *            marks the starting position (inclusive) of the substring
+	 * @param end
+	 *            marks the ending index (exclusive) of the substring
+	 */
+	public boolean match(String text, int start, int end) {
+		if (null == text) {
+			throw new IllegalArgumentException();
+		}
+
+		if (start > end) {
+			return false;
+		}
+
+		if (fIgnoreWildCards) {
+			return (end - start == fLength)
+					&& fPattern.regionMatches(fIgnoreCase, 0, text, start,
+							fLength);
+		}
+		int segCount = fSegments.length;
+		if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) {
+			return true;
+		}
+		if (start == end) {
+			return fLength == 0;
+		}
+		if (fLength == 0) {
+			return start == end;
+		}
+
+		int tlen = text.length();
+		if (start < 0) {
+			start = 0;
+		}
+		if (end > tlen) {
+			end = tlen;
+		}
+
+		int tCurPos = start;
+		int bound = end - fBound;
+		if (bound < 0) {
+			return false;
+		}
+		int i = 0;
+		String current = fSegments[i];
+		int segLength = current.length();
+
+		/* process first segment */
+		if (!fHasLeadingStar) {
+			if (!regExpRegionMatches(text, start, current, 0, segLength)) {
+				return false;
+			}
+			++i;
+			tCurPos = tCurPos + segLength;
+		}
+		if ((fSegments.length == 1) && (!fHasLeadingStar)
+				&& (!fHasTrailingStar)) {
+			// only one segment to match, no wildcards specified
+			return tCurPos == end;
+		}
+		/* process middle segments */
+		while (i < segCount) {
+			current = fSegments[i];
+			int currentMatch;
+			int k = current.indexOf(fSingleWildCard);
+			if (k < 0) {
+				currentMatch = textPosIn(text, tCurPos, end, current);
+				if (currentMatch < 0) {
+					return false;
+				}
+			} else {
+				currentMatch = regExpPosIn(text, tCurPos, end, current);
+				if (currentMatch < 0) {
+					return false;
+				}
+			}
+			tCurPos = currentMatch + current.length();
+			i++;
+		}
+
+		/* process final segment */
+		if (!fHasTrailingStar && tCurPos != end) {
+			int clen = current.length();
+			return regExpRegionMatches(text, end - clen, current, 0, clen);
+		}
+		return i == segCount;
+	}
+
+	/**
+	 * This method parses the given pattern into segments seperated by wildcard
+	 * '*' characters. Since wildcards are not being used in this case, the
+	 * pattern consists of a single segment.
+	 */
+	private void parseNoWildCards() {
+		fSegments = new String[1];
+		fSegments[0] = fPattern;
+		fBound = fLength;
+	}
+
+	/**
+	 * Parses the given pattern into segments seperated by wildcard '*'
+	 * characters.
+	 *
+	 * @param p
+	 *            , a String object that is a simple regular expression with '*'
+	 *            and/or '?'
+	 */
+	private void parseWildCards() {
+		if (fPattern.startsWith("*")) { //$NON-NLS-1$
+			fHasLeadingStar = true;
+		}
+		if (fPattern.endsWith("*")) {//$NON-NLS-1$
+			/* make sure it's not an escaped wildcard */
+			if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+				fHasTrailingStar = true;
+			}
+		}
+
+		Vector<String> temp = new Vector<>();
+
+		int pos = 0;
+		StringBuffer buf = new StringBuffer();
+		while (pos < fLength) {
+			char c = fPattern.charAt(pos++);
+			switch (c) {
+			case '\\':
+				if (pos >= fLength) {
+					buf.append(c);
+				} else {
+					char next = fPattern.charAt(pos++);
+					/* if it's an escape sequence */
+					if (next == '*' || next == '?' || next == '\\') {
+						buf.append(next);
+					} else {
+						/* not an escape sequence, just insert literally */
+						buf.append(c);
+						buf.append(next);
+					}
+				}
+				break;
+			case '*':
+				if (buf.length() > 0) {
+					/* new segment */
+					temp.addElement(buf.toString());
+					fBound += buf.length();
+					buf.setLength(0);
+				}
+				break;
+			case '?':
+				/* append special character representing single match wildcard */
+				buf.append(fSingleWildCard);
+				break;
+			default:
+				buf.append(c);
+			}
+		}
+
+		/* add last buffer to segment list */
+		if (buf.length() > 0) {
+			temp.addElement(buf.toString());
+			fBound += buf.length();
+		}
+
+		fSegments = new String[temp.size()];
+		temp.copyInto(fSegments);
+	}
+
+	/**
+	 * @param text
+	 *            a string which contains no wildcard
+	 * @param start
+	 *            the starting index in the text for search, inclusive
+	 * @param end
+	 *            the stopping point of search, exclusive
+	 * @return the starting index in the text of the pattern , or -1 if not
+	 *         found
+	 */
+	protected int posIn(String text, int start, int end) {// no wild card in
+															// pattern
+		int max = end - fLength;
+
+		if (!fIgnoreCase) {
+			int i = text.indexOf(fPattern, start);
+			if (i == -1 || i > max) {
+				return -1;
+			}
+			return i;
+		}
+
+		for (int i = start; i <= max; ++i) {
+			if (text.regionMatches(true, i, fPattern, 0, fLength)) {
+				return i;
+			}
+		}
+
+		return -1;
+	}
+
+	/**
+	 * @param text
+	 *            a simple regular expression that may only contain '?'(s)
+	 * @param start
+	 *            the starting index in the text for search, inclusive
+	 * @param end
+	 *            the stopping point of search, exclusive
+	 * @param p
+	 *            a simple regular expression that may contains '?'
+	 * @return the starting index in the text of the pattern , or -1 if not
+	 *         found
+	 */
+	protected int regExpPosIn(String text, int start, int end, String p) {
+		int plen = p.length();
+
+		int max = end - plen;
+		for (int i = start; i <= max; ++i) {
+			if (regExpRegionMatches(text, i, p, 0, plen)) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	/**
+	 *
+	 * @return boolean
+	 * @param text
+	 *            a String to match
+	 * @param start
+	 *            int that indicates the starting index of match, inclusive
+	 * @param end
+	 *            </code> int that indicates the ending index of match,
+	 *            exclusive
+	 * @param p
+	 *            String, String, a simple regular expression that may contain
+	 *            '?'
+	 * @param ignoreCase
+	 *            boolean indicating wether code>p</code> is case sensitive
+	 */
+	protected boolean regExpRegionMatches(String text, int tStart, String p,
+			int pStart, int plen) {
+		while (plen-- > 0) {
+			char tchar = text.charAt(tStart++);
+			char pchar = p.charAt(pStart++);
+
+			/* process wild cards */
+			if (!fIgnoreWildCards) {
+				/* skip single wild cards */
+				if (pchar == fSingleWildCard) {
+					continue;
+				}
+			}
+			if (pchar == tchar) {
+				continue;
+			}
+			if (fIgnoreCase) {
+				if (Character.toUpperCase(tchar) == Character
+						.toUpperCase(pchar)) {
+					continue;
+				}
+				// comparing after converting to upper case doesn't handle all
+				// cases;
+				// also compare after converting to lower case
+				if (Character.toLowerCase(tchar) == Character
+						.toLowerCase(pchar)) {
+					continue;
+				}
+			}
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * @param text
+	 *            the string to match
+	 * @param start
+	 *            the starting index in the text for search, inclusive
+	 * @param end
+	 *            the stopping point of search, exclusive
+	 * @param p
+	 *            a pattern string that has no wildcard
+	 * @return the starting index in the text of the pattern , or -1 if not
+	 *         found
+	 */
+	protected int textPosIn(String text, int start, int end, String p) {
+
+		int plen = p.length();
+		int max = end - plen;
+
+		if (!fIgnoreCase) {
+			int i = text.indexOf(p, start);
+			if (i == -1 || i > max) {
+				return -1;
+			}
+			return i;
+		}
+
+		for (int i = start; i <= max; ++i) {
+			if (text.regionMatches(true, i, p, 0, plen)) {
+				return i;
+			}
+		}
+
+		return -1;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewComparator.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewComparator.java
new file mode 100644
index 0000000..d6a0590
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewComparator.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 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.workbench.swt.internal.copy;
+
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+
+/**
+ * Based on org.eclipse.ui.internal.dialogs.ViewComparator
+ */
+public class ViewComparator extends ViewerComparator {
+
+	private final static String EMPTY_STRING = "";
+
+	/**
+	 * ViewSorter constructor comment.
+	 *
+	 * @param reg
+	 *            an IViewRegistry
+	 */
+	public ViewComparator() {
+		super();
+	}
+
+	/**
+	 * Returns a negative, zero, or positive number depending on whether the
+	 * first element is less than, equal to, or greater than the second element.
+	 */
+	@Override
+	public int compare(Viewer viewer, Object e1, Object e2) {
+		// place "General" category first
+		if (WorkbenchSWTMessages.ICategory_general.equals(e1))
+			return -1;
+		if (WorkbenchSWTMessages.ICategory_general.equals(e2))
+			return 1;
+
+		String str1;
+		if (e1 instanceof MPartDescriptor)
+			str1 = ((MPartDescriptor) e1).getLocalizedLabel();
+		else
+			str1 = e1.toString();
+
+		String str2;
+		if (e2 instanceof MPartDescriptor)
+			str2 = ((MPartDescriptor) e2).getLocalizedLabel();
+		else
+			str2 = e2.toString();
+		if (str1 == null)
+			str1 = EMPTY_STRING;
+		if (str2 == null)
+			str2 = EMPTY_STRING;
+		return getComparator().compare(str1, str2);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewContentProvider.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewContentProvider.java
new file mode 100644
index 0000000..9d5651a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewContentProvider.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 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.workbench.swt.internal.copy;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Based on org.eclipse.ui.internal.dialogs.ViewContentProvider.
+ */
+public class ViewContentProvider implements ITreeContentProvider {
+
+	final private static String CATEGORY_TAG = "categoryTag:";
+	final private static int CATEGORY_TAG_LENGTH = CATEGORY_TAG.length();
+
+	/**
+	 * Child cache. Map from Object->Object[]. Our hasChildren() method is
+	 * expensive so it's better to cache the results of getChildren().
+	 */
+	private Map<Object, Object[]> childMap = new HashMap<Object, Object[]>();
+
+	private MApplication application;
+
+	public ViewContentProvider(MApplication application) {
+		this.application = application;
+	}
+
+	@Override
+	public void dispose() {
+		childMap.clear();
+	}
+
+	@Override
+	public Object getParent(Object element) {
+		return null;
+	}
+
+	@Override
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		childMap.clear();
+		application = (MApplication) newInput;
+	}
+
+	@Override
+	public Object[] getElements(Object element) {
+		return getChildren(element);
+	}
+
+	@Override
+	public boolean hasChildren(Object element) {
+		if (element instanceof MApplication) {
+			return true;
+		} else if (element instanceof String) {
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public Object[] getChildren(Object element) {
+		Object[] children = childMap.get(element);
+		if (children == null) {
+			children = createChildren(element);
+			childMap.put(element, children);
+		}
+		return children;
+	}
+
+	private Object[] createChildren(Object element) {
+		if (element instanceof MApplication) {
+			List<MPartDescriptor> descriptors = ((MApplication) element)
+					.getDescriptors();
+			Set<String> categoryTags = new HashSet<String>();
+			Set<MPartDescriptor> noCategoryDescriptors = new HashSet<MPartDescriptor>();
+			for (MPartDescriptor descriptor : descriptors) {
+				List<String> tags = descriptor.getTags();
+				String category = null;
+				boolean isView = false;
+				for (String tag : tags) {
+					if (tag.equals("View"))
+						isView = true;
+					else if (tag.startsWith(CATEGORY_TAG)) {
+						category = tag.substring(CATEGORY_TAG_LENGTH);
+					}
+				}
+				if (isView) {
+					if (category != null)
+						categoryTags.add(category);
+					else
+						noCategoryDescriptors.add(descriptor);
+				}
+			}
+
+			Set<Object> combinedTopElements = new HashSet<Object>();
+			combinedTopElements.addAll(categoryTags);
+			combinedTopElements.addAll(noCategoryDescriptors);
+			return combinedTopElements.toArray();
+		} else if (element instanceof String) {
+			List<MPartDescriptor> descriptors = application.getDescriptors();
+			Set<MPartDescriptor> categoryDescriptors = new HashSet<MPartDescriptor>();
+			for (MPartDescriptor descriptor : descriptors) {
+				List<String> tags = descriptor.getTags();
+				for (String tag : tags) {
+					if (!tag.startsWith(CATEGORY_TAG))
+						continue;
+					String categoryTag = tag.substring(CATEGORY_TAG_LENGTH);
+					if (element.equals(categoryTag))
+						categoryDescriptors.add(descriptor);
+				}
+			}
+			return categoryDescriptors.toArray();
+		}
+		return new Object[0];
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewLabelProvider.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewLabelProvider.java
new file mode 100644
index 0000000..77310d3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewLabelProvider.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ *     Benjamin Muskalla  - bug 77710
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.swt.internal.copy;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.framework.Bundle;
+
+/**
+ * Based on org.eclipse.ui.internal.dialogs.ViewLabelProvider.
+ */
+public class ViewLabelProvider extends ColumnLabelProvider {
+
+	/**
+	 * Image descriptor for enabled clear button.
+	 */
+	private static final String FOLDER_ICON = "org.eclipse.e4.descriptor.folder"; //$NON-NLS-1$
+
+	/**
+	 * Get image descriptors for the clear button.
+	 */
+	static {
+		Bundle bundle = org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator
+				.getDefault().getBundle();
+		IPath path = new Path("$nl$/icons/full/obj16/fldr_obj.gif");
+		URL url = FileLocator.find(bundle, path, null);
+		ImageDescriptor enabledDesc = ImageDescriptor.createFromURL(url);
+		if (enabledDesc != null)
+			JFaceResources.getImageRegistry().put(FOLDER_ICON, enabledDesc);
+	}
+
+	private Map<String, Image> imageMap = new HashMap<String, Image>();
+
+	private IEclipseContext context;
+
+	/**
+	 * @param window
+	 *            the workbench window
+	 * @param dimmedForeground
+	 *            the dimmed foreground color to use for views that are already
+	 *            open
+	 */
+	public ViewLabelProvider(IEclipseContext context) {
+		this.context = context;
+	}
+
+	@Override
+	public void dispose() {
+		for (Image image : imageMap.values()) {
+			image.dispose();
+		}
+		super.dispose();
+	}
+
+	@Override
+	public Image getImage(Object element) {
+		if (element instanceof MPartDescriptor) {
+			String iconURI = ((MPartDescriptor) element).getIconURI();
+			if (iconURI != null && iconURI.length() > 0) {
+				Image image = imageMap.get(iconURI);
+				if (image == null) {
+					ISWTResourceUtilities resUtils = (ISWTResourceUtilities) context
+							.get(IResourceUtilities.class.getName());
+					image = resUtils.imageDescriptorFromURI(
+							URI.createURI(iconURI)).createImage();
+					imageMap.put(iconURI, image);
+				}
+				return image;
+			}
+			return null;
+		} else if (element instanceof String) {
+			Image image = imageMap.get(FOLDER_ICON);
+			if (image == null) {
+				image = JFaceResources.getImageRegistry()
+						.getDescriptor(FOLDER_ICON).createImage();
+				imageMap.put(FOLDER_ICON, image);
+			}
+			return image;
+		}
+		return null;
+	}
+
+	@Override
+	public String getText(Object element) {
+		String label = WorkbenchSWTMessages.ViewLabel_unknown;
+		if (element instanceof String) {
+			label = (String) element;
+		} else if (element instanceof MPartDescriptor) {
+			label = ((MPartDescriptor) element).getLocalizedLabel();
+		}
+		return label;
+	}
+
+	@Override
+	public Color getBackground(Object element) {
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewPatternFilter.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewPatternFilter.java
new file mode 100644
index 0000000..d427a3e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/ViewPatternFilter.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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.workbench.swt.internal.copy;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.LocalizationHelper;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Based on of org.eclipse.ui.internal.dialogs.ViewPatternFilter.
+ */
+public class ViewPatternFilter extends PatternFilter {
+
+	private IEclipseContext context;
+
+	/**
+	 * Create a new instance of a ViewPatternFilter
+	 */
+	public ViewPatternFilter(IEclipseContext context) {
+		super();
+		this.context = context;
+	}
+
+	@Override
+	public boolean isElementSelectable(Object element) {
+		return element instanceof MPartDescriptor;
+	}
+
+	@Override
+	protected boolean isLeafMatch(Viewer viewer, Object element) {
+		if (element instanceof String) {
+			return false;
+		}
+
+		String text = null;
+		if (element instanceof MPartDescriptor) {
+			MPartDescriptor desc = (MPartDescriptor) element;
+			text = LocalizationHelper.getLocalized(desc.getLabel(), desc,
+					context);
+			if (wordMatches(text)) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/WorkbenchSWTMessages.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/WorkbenchSWTMessages.java
new file mode 100644
index 0000000..7c5fa09
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/WorkbenchSWTMessages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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 - Initial API and implementation
+ * Sebastian Davids - bug 128529
+ * Semion Chichelnitsky (semion@il.ibm.com) - bug 278064
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.swt.internal.copy;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Based on org.eclipse.ui.internal.WorkbenchMessages
+ */
+public class WorkbenchSWTMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.workbench.swt.internal.copy.messages";//$NON-NLS-1$
+
+	public static String FilteredTree_AccessibleListenerClearButton;
+	public static String FilteredTree_ClearToolTip;
+	public static String FilteredTree_FilterMessage;
+	public static String FilteredTree_AccessibleListenerFiltered;
+	public static String ViewLabel_unknown;
+	public static String ShowView_noDesc;
+	public static String ShowView_selectViewHelp;
+	public static String ICategory_other;
+	public static String ICategory_general;
+	public static String ShowView_shellTitle;
+
+	// IDEApplication messages
+	public static String IDEApplication_workspaceMandatoryTitle;
+	public static String IDEApplication_workspaceMandatoryMessage;
+	public static String IDEApplication_workspaceCannotLockTitle;
+	public static String IDEApplication_workspaceCannotLockMessage;
+	public static String IDEApplication_workspaceCannotBeSetTitle;
+	public static String IDEApplication_workspaceCannotBeSetMessage;
+	public static String InternalError;
+	public static String IDEApplication_versionTitle;
+	public static String IDEApplication_versionMessage;
+
+	static {
+		// load message values from bundle file
+		reloadMessages();
+	}
+
+	public static void reloadMessages() {
+		NLS.initializeMessages(BUNDLE_NAME, WorkbenchSWTMessages.class);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/messages.properties b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/messages.properties
new file mode 100644
index 0000000..8882c26
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/internal/copy/messages.properties
@@ -0,0 +1,43 @@
+###############################################################################
+# Copyright (c) 2000, 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
+#     Sebastian Davids (sdavids@gmx.de) 
+#        - Fix for Bug 57087
+#        - Fix for Bug 138034 [Preferences] Label decorations page - extra space
+#        - Fix for Bug 128529
+#     Semion Chichelnitsky (semion@il.ibm.com) - bug 278064
+###############################################################################
+
+# Based on /org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties
+
+FilteredTree_AccessibleListenerClearButton=Clear filter field
+FilteredTree_ClearToolTip=Clear
+FilteredTree_FilterMessage=type filter text
+FilteredTree_AccessibleListenerFiltered={0} {1} matches.
+ViewLabel_unknown = Unknown
+ShowView_noDesc = No description available.
+ShowView_selectViewHelp = Use F2 to display the description for a selected view.
+ICategory_other = Other
+ICategory_general = General
+ShowView_shellTitle = Show View
+
+# IDEApplication messages
+InternalError = Internal Error
+IDEApplication_workspaceMandatoryTitle=Workspace is Mandatory
+IDEApplication_workspaceMandatoryMessage=IDEs need a valid workspace. Restart without the @none option.
+IDEApplication_workspaceCannotLockTitle=Workspace Cannot Be Locked
+IDEApplication_workspaceCannotLockMessage=Could not launch the product because the associated workspace is currently in use by another Eclipse application.
+IDEApplication_workspaceCannotBeSetTitle=Workspace Cannot Be Created
+IDEApplication_workspaceCannotBeSetMessage=Could not launch the product because the specified workspace cannot be created.  The specified workspace directory is either invalid or read-only.
+IDEApplication_versionTitle = Different Workspace Version
+IDEApplication_versionMessage = \
+This workspace was written with a different version of the product and needs to be updated.\n\n\
+{0}\n\n\
+Updating the workspace may make it incompatible with other versions of the product.\n\
+Press OK to update the workspace and open it.  Press Cancel to select a different workspace.
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/BindingProcessingAddon.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/BindingProcessingAddon.java
new file mode 100644
index 0000000..6d2d6b0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/BindingProcessingAddon.java
@@ -0,0 +1,479 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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 429575
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench.swt.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.bindings.internal.BindingTable;
+import org.eclipse.e4.ui.bindings.internal.BindingTableManager;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.commands.MBindingContext;
+import org.eclipse.e4.ui.model.application.commands.MBindingTable;
+import org.eclipse.e4.ui.model.application.commands.MBindings;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MKeyBinding;
+import org.eclipse.e4.ui.model.application.commands.MParameter;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.services.EContextService;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.BindingManager;
+import org.eclipse.jface.bindings.Scheme;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Process contexts in the model, feeding them into the command service.
+ */
+public class BindingProcessingAddon {
+	private static final String[] DEFAULT_SCHEMES = { "org.eclipse.ui.defaultAcceleratorConfiguration" };
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	private IEventBroker broker;
+
+	@Inject
+	private ContextManager contextManager;
+
+	@Inject
+	private BindingTableManager bindingTables;
+
+	@Inject
+	@Optional
+	private BindingManager bindingManager;
+
+	@Inject
+	private ECommandService commandService;
+
+	@Inject
+	private EBindingService bindingService;
+
+	private EventHandler additionHandler;
+
+	private EventHandler contextHandler;
+
+	@PostConstruct
+	public void init() {
+		String[] schemes = DEFAULT_SCHEMES;
+		if (bindingManager != null) {
+			final Scheme activeScheme = bindingManager.getActiveScheme();
+			if (activeScheme != null) {
+				schemes = getSchemeIds(activeScheme.getId());
+			}
+		}
+		bindingTables.setActiveSchemes(schemes);
+		defineBindingTables();
+		activateContexts(application);
+		registerModelListeners();
+	}
+
+	private final String[] getSchemeIds(String schemeId) {
+		final List<String> strings = new ArrayList<String>();
+		while (schemeId != null) {
+			strings.add(schemeId);
+			try {
+				schemeId = getScheme(schemeId).getParentId();
+			} catch (final NotDefinedException e) {
+				return new String[0];
+			}
+		}
+
+		return strings.toArray(new String[strings.size()]);
+	}
+
+	private final Scheme getScheme(String schemeId) {
+		return bindingManager.getScheme(schemeId);
+	}
+
+	private void activateContexts(Object me) {
+		if (me instanceof MBindings) {
+			MContext contextModel = (MContext) me;
+			MBindings container = (MBindings) me;
+			List<MBindingContext> bindingContexts = container
+					.getBindingContexts();
+			IEclipseContext context = contextModel.getContext();
+			if (context != null && !bindingContexts.isEmpty()) {
+				EContextService cs = context.get(EContextService.class);
+				for (MBindingContext element : bindingContexts) {
+					cs.activateContext(element.getElementId());
+				}
+			}
+		}
+		if (me instanceof MElementContainer) {
+			@SuppressWarnings("unchecked")
+			List<MUIElement> children = ((MElementContainer<MUIElement>) me).getChildren();
+			Iterator<MUIElement> i = children.iterator();
+			while (i.hasNext()) {
+				MUIElement e = i.next();
+				activateContexts(e);
+			}
+		}
+	}
+
+	private void defineBindingTables() {
+		Activator.trace(Policy.DEBUG_CMDS,
+				"Initialize binding tables from model", null); //$NON-NLS-1$
+		for (MBindingTable bindingTable : application.getBindingTables()) {
+			defineBindingTable(bindingTable);
+		}
+	}
+
+	/**
+	 * @param bindingTable
+	 */
+	private void defineBindingTable(MBindingTable bindingTable) {
+		Assert.isNotNull(
+				bindingTable.getBindingContext(),
+				"Binding context referred to by the binding table \"" + bindingTable.getElementId() + "\""); //$NON-NLS-1$
+		Assert.isNotNull(bindingTable.getBindingContext().getElementId(),
+				"Element ID of binding table \"" + bindingTable.getElementId() + "\"."); //$NON-NLS-1$
+		final Context bindingContext = contextManager.getContext(bindingTable
+				.getBindingContext().getElementId());
+		BindingTable table = bindingTables.getTable(bindingTable
+				.getBindingContext().getElementId());
+		if (table == null) {
+			table = new BindingTable(bindingContext);
+			bindingTables.addTable(table);
+		}
+		for (MKeyBinding binding : bindingTable.getBindings()) {
+			defineBinding(table, bindingContext, binding);
+		}
+	}
+
+	/**
+	 * @param bindingTable
+	 * @param binding
+	 */
+	private void defineBinding(BindingTable bindingTable,
+			Context bindingContext, MKeyBinding binding) {
+		Binding keyBinding = createBinding(bindingContext,
+				binding.getCommand(), binding.getParameters(),
+				binding.getKeySequence(), binding);
+		if (keyBinding != null
+				&& !binding.getTags().contains(
+						EBindingService.DELETED_BINDING_TAG)) {
+			bindingTable.addBinding(keyBinding);
+		}
+	}
+
+	private Binding createBinding(Context bindingContext, MCommand cmdModel,
+			List<MParameter> modelParms, String keySequence, MKeyBinding binding) {
+		Binding keyBinding = null;
+
+		if (binding.getTransientData()
+				.get(EBindingService.MODEL_TO_BINDING_KEY) != null) {
+			try {
+				keyBinding = (Binding) binding.getTransientData().get(
+						EBindingService.MODEL_TO_BINDING_KEY);
+				return keyBinding;
+			} catch (ClassCastException cce) {
+				System.err
+						.println("Invalid type stored in transient data with the key "
+								+ EBindingService.MODEL_TO_BINDING_KEY);
+				return null;
+			}
+		}
+
+		if (cmdModel == null) {
+			Activator.log(IStatus.ERROR, "binding with no command: " + binding); //$NON-NLS-1$
+			return null;
+		}
+		Map<String, Object> parameters = null;
+		if (modelParms != null && !modelParms.isEmpty()) {
+			parameters = new HashMap<String, Object>();
+			for (MParameter mParm : modelParms) {
+				parameters.put(mParm.getName(), mParm.getValue());
+			}
+		}
+		ParameterizedCommand cmd = commandService.createCommand(
+				cmdModel.getElementId(), parameters);
+		TriggerSequence sequence = null;
+		sequence = bindingService.createSequence(keySequence);
+
+		if (cmd == null) {
+			System.err
+					.println("Failed to find command for binding: " + binding); //$NON-NLS-1$
+		} else if (sequence == null) {
+			System.err.println("Failed to map binding: " + binding); //$NON-NLS-1$
+		} else {
+			try {
+				String schemeId = null;
+				String locale = null;
+				String platform = null;
+
+				Map<String, String> attrs = new HashMap<String, String>();
+				List<String> tags = binding.getTags();
+				for (String tag : tags) {
+					// remember to skip the ':' in each tag!
+					if (tag.startsWith(EBindingService.SCHEME_ID_ATTR_TAG)) {
+						schemeId = tag.substring(9);
+						attrs.put(EBindingService.SCHEME_ID_ATTR_TAG, schemeId);
+					} else if (tag.startsWith(EBindingService.LOCALE_ATTR_TAG)) {
+						locale = tag.substring(7);
+						attrs.put(EBindingService.LOCALE_ATTR_TAG, locale);
+					} else if (tag
+							.startsWith(EBindingService.PLATFORM_ATTR_TAG)) {
+						platform = tag.substring(9);
+						attrs.put(EBindingService.PLATFORM_ATTR_TAG, platform);
+					} else if (tag.startsWith(EBindingService.TYPE_ATTR_TAG)) {
+						// system bindings won't pass this attr
+						attrs.put(EBindingService.TYPE_ATTR_TAG, "user");
+					}
+				}
+				keyBinding = bindingService.createBinding(sequence, cmd,
+						bindingContext.getId(), attrs);
+				binding.getTransientData().put(
+						EBindingService.MODEL_TO_BINDING_KEY, keyBinding);
+			} catch (IllegalArgumentException e) {
+				Activator.trace(Policy.DEBUG_MENUS,
+						"failed to create: " + binding, e); //$NON-NLS-1$
+				return null;
+			}
+
+		}
+		return keyBinding;
+	}
+
+	private void updateBinding(MKeyBinding binding, boolean add, Object eObj) {
+		Object parentObj = ((EObject) binding).eContainer();
+		if (!(parentObj instanceof MBindingTable)) {
+			// the link will already be broken for removes, so we'll try this
+			if (eObj instanceof MBindingTable) {
+				parentObj = eObj;
+			}
+		}
+
+		if (parentObj == null) {
+			return;
+		}
+
+		MBindingTable bt = (MBindingTable) parentObj;
+		final Context bindingContext = contextManager.getContext(bt
+				.getBindingContext().getElementId());
+		BindingTable table = bindingTables.getTable(bindingContext.getId());
+		if (table == null) {
+			Activator.log(IStatus.ERROR, "Trying to create \'" + binding //$NON-NLS-1$
+					+ "\' without binding table " + bindingContext.getId()); //$NON-NLS-1$
+			return;
+		}
+		Binding keyBinding = createBinding(bindingContext,
+				binding.getCommand(), binding.getParameters(),
+				binding.getKeySequence(), binding);
+		if (keyBinding != null) {
+			if (add) {
+				table.addBinding(keyBinding);
+			} else {
+				table.removeBinding(keyBinding);
+			}
+		}
+	}
+
+	@PreDestroy
+	public void dispose() {
+		unregsiterModelListeners();
+	}
+
+	private void registerModelListeners() {
+		additionHandler = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				Object elementObj = event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+				if (elementObj instanceof MApplication) {
+					if (UIEvents.isADD(event)) {
+						for (Object newObj : UIEvents.asIterable(event,
+								UIEvents.EventTags.NEW_VALUE)) {
+							if (newObj instanceof MBindingTable) {
+								MBindingTable bt = (MBindingTable) newObj;
+								final Context bindingContext = contextManager
+										.getContext(bt.getBindingContext()
+												.getElementId());
+								final BindingTable table = new BindingTable(
+										bindingContext);
+								bindingTables.addTable(table);
+								List<MKeyBinding> bindings = bt.getBindings();
+								for (MKeyBinding binding : bindings) {
+									Binding keyBinding = createBinding(
+											bindingContext,
+											binding.getCommand(),
+											binding.getParameters(),
+											binding.getKeySequence(), binding);
+									if (keyBinding != null) {
+										table.addBinding(keyBinding);
+									}
+								}
+							}
+						}
+					}
+				} else if (elementObj instanceof MBindingTable) {
+					// adding a binding
+					if (UIEvents.isADD(event)) {
+						for (Object newObj : UIEvents.asIterable(event,
+								UIEvents.EventTags.NEW_VALUE)) {
+							if (newObj instanceof MKeyBinding) {
+								MKeyBinding binding = (MKeyBinding) newObj;
+								updateBinding(binding, true, elementObj);
+							}
+						}
+					}
+					// removing a binding
+					else if (UIEvents.isREMOVE(event)) {
+						for (Object oldObj : UIEvents.asIterable(event,
+								UIEvents.EventTags.OLD_VALUE)) {
+							if (oldObj instanceof MKeyBinding) {
+								MKeyBinding binding = (MKeyBinding) oldObj;
+								updateBinding(binding, false, elementObj);
+							}
+						}
+					}
+				} else if (elementObj instanceof MKeyBinding) {
+					MKeyBinding binding = (MKeyBinding) elementObj;
+
+					String attrName = (String) event
+							.getProperty(UIEvents.EventTags.ATTNAME);
+
+					// System.out.println("MKeyBinding." + attrName + ": "
+					// + event.getProperty(UIEvents.EventTags.TYPE));
+					if (UIEvents.isSET(event)) {
+						Object oldObj = event
+								.getProperty(UIEvents.EventTags.OLD_VALUE);
+						if (UIEvents.KeyBinding.COMMAND.equals(attrName)) {
+							MKeyBinding oldBinding = (MKeyBinding) EcoreUtil
+									.copy((EObject) binding);
+							oldBinding.setCommand((MCommand) oldObj);
+							updateBinding(oldBinding, false,
+									((EObject) binding).eContainer());
+							updateBinding(binding, true, null);
+						} else if (UIEvents.KeySequence.KEYSEQUENCE
+								.equals(attrName)) {
+							MKeyBinding oldBinding = (MKeyBinding) EcoreUtil
+									.copy((EObject) binding);
+							oldBinding.setKeySequence((String) oldObj);
+							updateBinding(oldBinding, false,
+									((EObject) binding).eContainer());
+							updateBinding(binding, true, null);
+						}
+					} else if (UIEvents.KeyBinding.PARAMETERS.equals(attrName)) {
+						if (UIEvents.isADD(event)) {
+							Object newObj = event
+									.getProperty(UIEvents.EventTags.NEW_VALUE);
+							MKeyBinding oldBinding = (MKeyBinding) EcoreUtil
+									.copy((EObject) binding);
+							if (UIEvents.EventTypes.ADD_MANY.equals(event
+									.getProperty(UIEvents.EventTags.TYPE))) {
+								oldBinding.getParameters().removeAll(
+										(Collection<?>) newObj);
+							} else {
+								oldBinding.getParameters().remove(newObj);
+							}
+							updateBinding(oldBinding, false,
+									((EObject) binding).eContainer());
+							updateBinding(binding, true, null);
+						} else if (UIEvents.isREMOVE(event)) {
+							Object oldObj = event
+									.getProperty(UIEvents.EventTags.OLD_VALUE);
+							MKeyBinding oldBinding = (MKeyBinding) EcoreUtil
+									.copy((EObject) binding);
+							if (UIEvents.EventTypes.REMOVE_MANY.equals(event
+									.getProperty(UIEvents.EventTags.TYPE))) {
+								@SuppressWarnings("unchecked")
+								Collection<MParameter> parms = (Collection<MParameter>) oldObj;
+								oldBinding.getParameters().addAll(parms);
+							} else {
+								oldBinding.getParameters().add(
+										(MParameter) oldObj);
+							}
+
+							updateBinding(oldBinding, false,
+									((EObject) binding).eContainer());
+							updateBinding(binding, true, null);
+						}
+					}
+					// if we've updated the tags for an MKeyBinding
+					else if (UIEvents.ApplicationElement.TAGS.equals(attrName)) {
+						List<String> tags = binding.getTags();
+						// if we added a deleted tag to the MKeyBinding, then
+						// remove it from the runtime binding tables
+						if (tags.contains(EBindingService.DELETED_BINDING_TAG)) {
+							updateBinding(binding, false, elementObj);
+						}
+						// else we're adding the binding to the runtime tables
+						else {
+							updateBinding(binding, true, elementObj);
+						}
+					}
+				}
+			}
+		};
+		broker.subscribe(UIEvents.BindingTableContainer.TOPIC_BINDINGTABLES,
+				additionHandler);
+		broker.subscribe(UIEvents.BindingTable.TOPIC_BINDINGS, additionHandler);
+		broker.subscribe(UIEvents.KeyBinding.TOPIC_COMMAND, additionHandler);
+		broker.subscribe(UIEvents.KeyBinding.TOPIC_PARAMETERS, additionHandler);
+		broker.subscribe(UIEvents.KeySequence.TOPIC_KEYSEQUENCE,
+				additionHandler);
+		broker.subscribe(UIEvents.ApplicationElement.TOPIC_TAGS,
+				additionHandler);
+
+		contextHandler = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				Object elementObj = event
+						.getProperty(UIEvents.EventTags.ELEMENT);
+				Object newObj = event.getProperty(UIEvents.EventTags.NEW_VALUE);
+				if (UIEvents.EventTypes.SET.equals(event
+						.getProperty(UIEvents.EventTags.TYPE))
+						&& newObj instanceof IEclipseContext) {
+					activateContexts(elementObj);
+				}
+			}
+		};
+		broker.subscribe(UIEvents.Context.TOPIC_CONTEXT, contextHandler);
+	}
+
+	private void unregsiterModelListeners() {
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(contextHandler);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/ISWTResourceUtilities.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/ISWTResourceUtilities.java
new file mode 100644
index 0000000..3093c91
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/workbench/swt/util/ISWTResourceUtilities.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 BestSolution.at 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:
+ *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     IBM Corporation - ongoing development
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench.swt.util;
+
+import org.eclipse.e4.ui.workbench.IResourceUtilities;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+public interface ISWTResourceUtilities extends
+		IResourceUtilities<ImageDescriptor> {
+
+	/**
+	 * Low-level utility to stamp an adornment onto a given Image.
+	 *
+	 * @param toAdorn
+	 *            The image to be adorned (must not be null)
+	 * @param adornment
+	 *            The image to adorn with.
+	 *
+	 * @return The adorned image or 'toAdorn' if 'adornment' is null
+	 */
+	public Image adornImage(Image toAdorn, Image adornment);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/.classpath b/bundles/org.eclipse.e4.ui.workbench/.classpath
new file mode 100644
index 0000000..bd3096f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-rap"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.workbench/.options b/bundles/org.eclipse.e4.ui.workbench/.options
new file mode 100644
index 0000000..871b00f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.options
@@ -0,0 +1,7 @@
+org.eclipse.e4.ui.workbench/debug = false
+org.eclipse.e4.ui.workbench/trace/menus = false
+org.eclipse.e4.ui.workbench/trace/commands = false
+org.eclipse.e4.ui.workbench/trace/eclipse.context = false
+org.eclipse.e4.ui.workbench/trace/eclipse.context.verbose = false
+org.eclipse.e4.ui.workbench/trace/workbench = false
+org.eclipse.e4.ui.workbench/trace/renderer = false
diff --git a/bundles/org.eclipse.e4.ui.workbench/.project b/bundles/org.eclipse.e4.ui.workbench/.project
new file mode 100644
index 0000000..4d26891
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.workbench</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>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters b/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters
new file mode 100644
index 0000000..fbaf9c2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/.api_filters
@@ -0,0 +1,432 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.e4.ui.workbench" version="2">
+    <resource path="META-INF/MANIFEST.MF">
+        <filter comment="Bug 319463 - Remove dead code" id="923795461">
+            <message_arguments>
+                <message_argument value="1.1.0"/>
+                <message_argument value="1.0.1"/>
+            </message_arguments>
+        </filter>
+        <filter id="924844039">
+            <message_arguments>
+                <message_argument value="1.2.2"/>
+                <message_argument value="1.2.1"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="META-INF/MANIFEST.MF" type="org.eclipse.e4.ui.workbench.modeling.ModelService">
+        <filter comment="Bug 319463 - Remove dead code" id="305324134">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelService"/>
+                <message_argument value="org.eclipse.e4.ui.workbench_1.1.0"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/IPresentationEngine.java" type="org.eclipse.e4.ui.workbench.IPresentationEngine">
+        <filter id="1209008130">
+            <message_arguments>
+                <message_argument value="1.3"/>
+                <message_argument value="1.2"/>
+                <message_argument value="ACTIVE"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$Application">
+        <filter comment="New dialogs field in MApplication" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Application"/>
+                <message_argument value="DIALOGS"/>
+            </message_arguments>
+        </filter>
+        <filter comment="New dialogs field in MApplication" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Application"/>
+                <message_argument value="TOPIC_DIALOGS"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$Category">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Category"/>
+                <message_argument value="LOCALIZED_NAME"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Category"/>
+                <message_argument value="TOPIC_LOCALIZED_NAME"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$Command">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Command"/>
+                <message_argument value="LOCALIZED_COMMANDNAME"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Command"/>
+                <message_argument value="LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Command"/>
+                <message_argument value="TOPIC_LOCALIZED_COMMANDNAME"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Command"/>
+                <message_argument value="TOPIC_LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$Part">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Part"/>
+                <message_argument value="LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.Part"/>
+                <message_argument value="TOPIC_LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$PartDescriptor">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.PartDescriptor"/>
+                <message_argument value="LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.PartDescriptor"/>
+                <message_argument value="TOPIC_LOCALIZED_DESCRIPTION"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$UIElement">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UIElement"/>
+                <message_argument value="LOCALIZED_ACCESSIBILITYPHRASE"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UIElement"/>
+                <message_argument value="TOPIC_LOCALIZED_ACCESSIBILITYPHRASE"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$UILabel">
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILabel"/>
+                <message_argument value="LOCALIZED_LABEL"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILabel"/>
+                <message_argument value="LOCALIZED_TOOLTIP"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILabel"/>
+                <message_argument value="TOPIC_LOCALIZED_LABEL"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 423991 - Add support for Locale changes at runtime to the Application Model" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILabel"/>
+                <message_argument value="TOPIC_LOCALIZED_TOOLTIP"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/UIEvents.java" type="org.eclipse.e4.ui.workbench.UIEvents$UILifeCycle">
+        <filter id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
+                <message_argument value="APP_SHUTDOWN_STARTED"/>
+            </message_arguments>
+        </filter>
+        <filter id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
+                <message_argument value="PERSPECTIVE_RESET"/>
+            </message_arguments>
+        </filter>
+        <filter comment="All of the subinterfaces shouldn't be subclassed either" id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
+                <message_argument value="THEME_CHANGED"/>
+            </message_arguments>
+        </filter>
+        <filter id="403767336">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle"/>
+                <message_argument value="THEME_DEFINITION_CHANGED"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/EObjModelHandler.java" type="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="getAdapter(Object, Class)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="getAdapterList()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="getChildren(Object, String)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="getPropIds(Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="getProperty(Object, String)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="setProperty(Object, String, Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338948223">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler"/>
+                <message_argument value="EObjModelHandler()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/EPlaceholderResolver.java" type="org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver"/>
+                <message_argument value="resolvePlaceholderRef(MPlaceholder, MWindow)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/IDelta.java" type="org.eclipse.e4.ui.workbench.modeling.IDelta">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IDelta"/>
+                <message_argument value="apply()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IDelta"/>
+                <message_argument value="getObject()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/IModelReconcilingService.java" type="org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService"/>
+                <message_argument value="applyDeltas(Collection&lt;ModelDelta&gt;)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService"/>
+                <message_argument value="applyDeltas(Collection&lt;ModelDelta&gt;, String[])"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService"/>
+                <message_argument value="createModelReconciler()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/IPartListener.java" type="org.eclipse.e4.ui.workbench.modeling.IPartListener">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IPartListener"/>
+                <message_argument value="partActivated(MPart)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IPartListener"/>
+                <message_argument value="partBroughtToTop(MPart)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IPartListener"/>
+                <message_argument value="partDeactivated(MPart)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IPartListener"/>
+                <message_argument value="partHidden(MPart)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IPartListener"/>
+                <message_argument value="partVisible(MPart)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java" type="org.eclipse.e4.ui.workbench.modeling.ISaveHandler">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ISaveHandler"/>
+                <message_argument value="promptToSave(Collection&lt;MPart&gt;)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ISaveHandler"/>
+                <message_argument value="promptToSave(MPart)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ISaveHandler"/>
+                <message_argument value="save(MPart, boolean)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ISaveHandler"/>
+                <message_argument value="saveParts(Collection&lt;MPart&gt;, boolean)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/ISelectionListener.java" type="org.eclipse.e4.ui.workbench.modeling.ISelectionListener">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ISelectionListener"/>
+                <message_argument value="selectionChanged(MPart, Object)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/IWindowCloseHandler.java" type="org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="406052990">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler"/>
+                <message_argument value="close(MWindow)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/ModelDelta.java" type="org.eclipse.e4.ui.workbench.modeling.ModelDelta">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelDelta"/>
+                <message_argument value="convert(Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelDelta"/>
+                <message_argument value="getAttributeName()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelDelta"/>
+                <message_argument value="getAttributeValue()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelDelta"/>
+                <message_argument value="getObject()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338948223">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelDelta"/>
+                <message_argument value="ModelDelta(Object, String, Object)"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/ModelHandlerBase.java" type="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase"/>
+                <message_argument value="getChildren(Object, String)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase"/>
+                <message_argument value="getPropIds(Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase"/>
+                <message_argument value="getProperty(Object, String)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase"/>
+                <message_argument value="setProperty(Object, String, Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338948223">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase"/>
+                <message_argument value="ModelHandlerBase()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/e4/ui/workbench/modeling/ModelReconciler.java" type="org.eclipse.e4.ui.workbench.modeling.ModelReconciler">
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelReconciler"/>
+                <message_argument value="constructDeltas(Object, Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelReconciler"/>
+                <message_argument value="recordChanges(Object)"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338944126">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelReconciler"/>
+                <message_argument value="serialize()"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 411257 - .api_description files in Kepler release do not contain @noreference" id="338948223">
+            <message_arguments>
+                <message_argument value="org.eclipse.e4.ui.workbench.modeling.ModelReconciler"/>
+                <message_argument value="ModelReconciler()"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..c522e1f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1

+line.separator=\n

diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f5fbb19
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,391 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.launching.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.launching.prefs
new file mode 100644
index 0000000..d211d32
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.launching.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7b35580
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,124 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*******************************************************************************\n * Copyright (c) ${year} IBM Corporation and others.\n * All rights reserved. This program and the accompanying materials\n * are made available under the terms of the Eclipse Public License v1.0\n * which accompanies this distribution, and is available at\n * http\://www.eclipse.org/legal/epl-v10.html\n *\n * Contributors\:\n *     IBM Corporation - initial API and implementation\n ******************************************************************************/\n</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+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=false
+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_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=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=false
+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_redundant_type_arguments=false
+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=false
+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_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=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
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c70754b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
@@ -0,0 +1,43 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.e4.ui.workbench;singleton:=true
+Bundle-Version: 1.3.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
+ org.eclipse.equinox.common;bundle-version="[3.7.0,4.0.0)",
+ org.eclipse.osgi;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.e4.ui.services;bundle-version="0.9.0",
+ org.eclipse.equinox.registry;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.e4.core.services;bundle-version="0.9.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.0.0",
+ org.eclipse.e4.core.di;bundle-version="1.1.0",
+ org.eclipse.core.jobs;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.commands;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.osgi.services;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.e4.core.commands;bundle-version="0.9.0",
+ org.eclipse.emf.ecore.change;bundle-version="2.5.0",
+ org.eclipse.core.expressions;bundle-version="[3.4.200,4.0.0)",
+ org.eclipse.e4.ui.di;bundle-version="0.9.0",
+ org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",
+ org.eclipse.e4.core.di.extensions
+Require-Capability: org.eclipse.rap
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Export-Package: org.eclipse.e4.ui.internal.workbench;
+  x-friends:="org.eclipse.e4.ui.workbench.fragment,
+   org.eclipse.e4.ui.workbench.renderers.swt,
+   org.eclipse.e4.ui.workbench.swt,
+   org.eclipse.ui.workbench",
+ org.eclipse.e4.ui.internal.workbench.addons;x-internal:=true,
+ org.eclipse.e4.ui.internal.workbench.handlers;x-internal:=true,
+ org.eclipse.e4.ui.workbench,
+ org.eclipse.e4.ui.workbench.lifecycle;x-friends:="org.eclipse.e4.ui.workbench.swt",
+ org.eclipse.e4.ui.workbench.modeling
+Bundle-Activator: org.eclipse.e4.ui.internal.workbench.Activator
+Service-Component: OSGI-INF/progress.xml, OSGI-INF/partService.xml,
+ OSGI-INF/localechangeservice.xml
+Import-Package: com.ibm.icu.text;version="3.8.1",
+ javax.annotation;version="1.0.0",
+ javax.inject;version="1.0.0"
diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/p2.inf b/bundles/org.eclipse.e4.ui.workbench/META-INF/p2.inf
new file mode 100644
index 0000000..f4e1a27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/p2.inf
@@ -0,0 +1,13 @@
+# Ensure that modified RAP e4 platform bundles are only installed in RAP environment
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=491177
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=490922
+
+# Make sure that a RAP RWT implementation is available
+requires.0.namespace = org.eclipse.rap
+requires.0.name = org.eclipse.rap.rwt
+
+# Do not allow to install this IU in case the SWT bundle is available
+requires.1.namespace = org.eclipse.equinox.p2.iu
+requires.1.name = org.eclipse.swt
+requires.1.min = 0
+requires.1.max = 0
diff --git a/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/localechangeservice.xml b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/localechangeservice.xml
new file mode 100644
index 0000000..66fce50
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/localechangeservice.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="ILocaleChangeService context function">
+   <implementation class="org.eclipse.e4.ui.internal.LocaleChangeServiceContextFunction"/>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.services.nls.ILocaleChangeService"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/partService.xml b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/partService.xml
new file mode 100644
index 0000000..6d9054f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/partService.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.workbench.partService">
+   <implementation class="org.eclipse.e4.ui.internal.workbench.PartServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.ui.workbench.modeling.EPartService"/>
+</scr:component>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/progress.xml b/bundles/org.eclipse.e4.ui.workbench/OSGI-INF/progress.xml
new file mode 100644
index 0000000..37c7bef
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/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.workbench.progress">
+   <implementation class="org.eclipse.e4.ui.internal.workbench.ProgressMonitorFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.core.runtime.IProgressMonitor"/>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.ui.workbench/about.html b/bundles/org.eclipse.e4.ui.workbench/about.html
new file mode 100644
index 0000000..3ce4e7e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/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>November 20, 2008</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/build.properties b/bundles/org.eclipse.e4.ui.workbench/build.properties
new file mode 100644
index 0000000..b2a208e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/build.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 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
+###############################################################################
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               .options,\
+               OSGI-INF/,\
+               about.html,\
+               plugin.properties
+src.includes = schema/,\
+               about.html
+source.. = src/,\
+           src-rap/
+jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.e4.ui.workbench/forceQualifierUpdate.txt b/bundles/org.eclipse.e4.ui.workbench/forceQualifierUpdate.txt
new file mode 100644
index 0000000..d01ddc1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/forceQualifierUpdate.txt
@@ -0,0 +1,4 @@
+# To force a version qualifier update add the bug here
+Bug 403352 - Update all parent versions to match our build stream
+Bug 407961 - Comparator log shows special problem that will require "touches"
+
diff --git a/bundles/org.eclipse.e4.ui.workbench/plugin.properties b/bundles/org.eclipse.e4.ui.workbench/plugin.properties
new file mode 100644
index 0000000..f8ca7e4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/plugin.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2010, 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
+###############################################################################
+pluginName = Eclipse e4 Workbench
+providerName = Eclipse.org
+
+content-type.e4.name = e4 XMI
+extension-point.model.name = Model extensions
+extension-point.model.definition.enrichment.name = Model definition extensions
diff --git a/bundles/org.eclipse.e4.ui.workbench/plugin.xml b/bundles/org.eclipse.e4.ui.workbench/plugin.xml
new file mode 100644
index 0000000..b6f8104
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/plugin.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+   <extension-point id="org.eclipse.e4.workbench.model" name="%extension-point.model.name" schema="schema/org.eclipse.e4.workbench.model.exsd"/>
+   <extension-point id="org.eclipse.e4.workbench.model.definition.enrichment" name="%extension-point.model.definition.enrichment.name" schema="schema/org.eclipse.e4.workbench.model.definition.enrichment.exsd"/>
+   <extension
+         point="org.eclipse.core.runtime.adapters">
+      <factory
+            adaptableType="org.eclipse.core.runtime.IConfigurationElement"
+            class="org.eclipse.e4.ui.internal.workbench.ConfigurationElementAdapter">
+         <adapter
+               type="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase">
+         </adapter>
+      </factory>
+      <factory
+            adaptableType="org.eclipse.emf.ecore.EObject"
+            class="org.eclipse.e4.ui.workbench.modeling.EObjModelHandler">
+         <adapter
+               type="org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase">
+         </adapter>
+      </factory>
+   </extension>
+   <extension
+         point="org.eclipse.emf.ecore.extension_parser">
+      <parser
+            class="org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory"
+            type="e4xmi">
+      </parser>
+   </extension>
+   
+   <extension
+      point="org.eclipse.core.contenttype.contentTypes">
+     <content-type
+          base-type="org.eclipse.core.runtime.xml"
+          file-extensions="e4xmi"
+          id="org.eclipse.e4.content-type"
+          name="%content-type.e4.name"
+          priority="low">
+     </content-type>
+   </extension>
+   <extension
+         point="org.eclipse.e4.workbench.model.definition.enrichment">
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/commands">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/ui">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/ui/advanced">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/application/descriptor/basic">
+      </definitionEnrichment>
+      <definitionEnrichment
+            ePackageNS="http://www.eclipse.org/ui/2010/UIModel/fragment">
+      </definitionEnrichment>
+   </extension>
+</plugin>
diff --git a/bundles/org.eclipse.e4.ui.workbench/pom.xml b/bundles/org.eclipse.e4.ui.workbench/pom.xml
new file mode 100644
index 0000000..f06bb8c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.workbench</artifactId>
+  <version>1.3.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.definition.enrichment.exsd b/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.definition.enrichment.exsd
new file mode 100644
index 0000000..c8c8641
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.definition.enrichment.exsd
@@ -0,0 +1,107 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.e4.ui.workbench" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.e4.ui.workbench" id="model.definition.enrichment" name="Model definition extensions"/>
+      </appInfo>
+      <documentation>
+         &lt;strong&gt;This is not an API. The schema for this extension point is not frozen and might change in a non-backward compatible way in the future.&lt;/strong&gt;
+&lt;p&gt;
+This extension point provides a mechanism to enrich the UI model with custom UI model elements.
+&lt;p&gt;
+To find and create a custom UI model element via the EModelService#createModelElement(Class) method the elements have to be publisched via this ExtensionPoint.
+&lt;/p&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="definitionEnrichment"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="definitionEnrichment">
+      <complexType>
+         <attribute name="ePackageNS" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A namespace URI to the EPackage which contains custom application model classes.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         4.4
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         The following is an example to register a model definiton enrichment:
+
+&lt;extension
+  point=&quot;org.eclipse.e4.workbench.model.definition.enrichment&quot;&gt;
+  &lt;definitionEnrichment
+  ePackageNS=&quot;http://www.eclipse.org/ui/2010/UIModel/application/ui&quot;&gt;
+  &lt;/definitionEnrichment&gt;
+&lt;/extension&gt;
+      </documentation>
+   </annotation>
+
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2014 IBM Corporation and others.&lt;br&gt;
+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 &lt;a 
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.exsd b/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.exsd
new file mode 100644
index 0000000..fffe157
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/schema/org.eclipse.e4.workbench.model.exsd
@@ -0,0 +1,226 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.e4.ui.workbench" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.e4.ui.workbench" id="model" name="Model extensions"/>
+      </appInfo>
+      <documentation>
+         &lt;strong&gt;This is not an API. The schema for this extension point is not frozen and might change in a non-backward compatible way in the future.&lt;/strong&gt;
+&lt;p&gt;
+This extension point provides extensibility for the UI model of the running application. Modifications can be done in a declarative manner by using XML model fragments, or programmatically by supplying model processors.
+&lt;/p&gt;&lt;p&gt;
+Whenever possible, the model extensions of dependent bundles are processed before the extensions of bundles that depend on them.
+&lt;/p&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="fragment" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="processor" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="fragment">
+      <annotation>
+         <documentation>
+            The model fragment to be added to the UI model of the running application. The root element of the model fragment is expected to conform to the &lt;code&gt;org.eclipse.e4.ui.model.fragment.MModelFragments&lt;/code&gt;  interface.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="uri" type="string" use="required">
+            <annotation>
+               <documentation>
+                  URI describing location of the model fragment.  Can be of the form &lt;code&gt;platform:/plugin/bundle.id/...path&lt;/code&gt;.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="resource"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="apply" use="default" value="always">
+            <annotation>
+               <documentation>
+                  This attribute defines in which case a fragment is merged into the model:
+&lt;ul&gt;
+&lt;li&gt;always: each time the application started potentially replacing existing model elements and loosing information stored&lt;/li&gt;
+&lt;li&gt;initial: only when coming from a none persistent state&lt;/li&gt;
+&lt;li&gt;notexists: only if the given element does not exist already in the model&lt;/li&gt;
+&lt;/ul&gt;
+               </documentation>
+            </annotation>
+            <simpleType>
+               <restriction base="string">
+                  <enumeration value="always">
+                  </enumeration>
+                  <enumeration value="initial">
+                  </enumeration>
+                  <enumeration value="notexists">
+                  </enumeration>
+               </restriction>
+            </simpleType>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="processor">
+      <annotation>
+         <documentation>
+            Programmatic processor that gets called with the intention of modifying UI model.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="element" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Java class containing model processor. A class method with the qualifier &lt;code&gt;&quot;org.eclipse.e4.core.di.annotations.Execute&quot;&lt;/code&gt;  will be invoked as a part of the model processing.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="beforefragment" type="boolean" use="required">
+            <annotation>
+               <documentation>
+                  This flag specifies that the processor has to be invoked before model fragments are added.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="apply" use="default" value="always">
+            <annotation>
+               <documentation>
+                  This attribute defines in which case a processor is run
+&lt;ul&gt;
+&lt;li&gt;always: each time the application started&lt;/li&gt;
+&lt;li&gt;initial: only when coming from a none persistent state&lt;/li&gt;
+&lt;/ul&gt;
+               </documentation>
+            </annotation>
+            <simpleType>
+               <restriction base="string">
+                  <enumeration value="always">
+                  </enumeration>
+                  <enumeration value="initial">
+                  </enumeration>
+               </restriction>
+            </simpleType>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="element">
+      <annotation>
+         <documentation>
+            A model element to be added to the context used to invoke the processor.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Identifier of a model element to be added to the context.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="contextKey" type="string">
+            <annotation>
+               <documentation>
+                  A optional key under which to store the model element in the context. The value of &quot;id&quot; is used if this value is not specified.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         4.2
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         The following is an example for the preference extension point: 
+&lt;p&gt;
+&lt;pre&gt;
+   &lt;extension
+         id=&quot;themeContribution&quot;
+         point=&quot;org.eclipse.e4.workbench.model&quot;&gt;
+      &lt;processor
+            beforefragment=&quot;true&quot;
+            class=&quot;org.eclipse.e4.demo.simpleide.internal.ThemeMenuProcessor&quot;&gt;
+         &lt;element
+               id=&quot;simpleide.mainmenu&quot;&gt;
+         &lt;/element&gt;
+      &lt;/processor&gt;
+   &lt;/extension&gt;
+   &lt;extension
+         id=&quot;logContribution&quot;
+         point=&quot;org.eclipse.e4.workbench.model&quot;&gt;
+      &lt;snippet
+            uri=&quot;platform:/plugin/org.eclipse.e4.demo.log/xmi/components.e4xmi&quot;&gt;
+      &lt;/snippet&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;
+      </documentation>
+   </annotation>
+
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2010, 2014 IBM Corporation and others.&lt;br&gt;
+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 &lt;a 
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src-rap/org/eclipse/e4/ui/internal/workbench/addons/CommandProcessingAddon.java b/bundles/org.eclipse.e4.ui.workbench/src-rap/org/eclipse/e4/ui/internal/workbench/addons/CommandProcessingAddon.java
new file mode 100644
index 0000000..69d8768
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src-rap/org/eclipse/e4/ui/internal/workbench/addons/CommandProcessingAddon.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.addons;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.core.commands.CommandManagerEvent;
+import org.eclipse.core.commands.ICommandManagerListener;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.ParameterType;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.Parameter;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.model.LocalizationHelper;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.commands.MCategory;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MCommandParameter;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Process commands in the model, feeding them into the command service.
+ */
+public class CommandProcessingAddon {
+	@Inject
+	private ECommandService commandService;
+
+	@Inject
+	private CommandManager commandManager;
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	private IEventBroker broker;
+
+	@Inject
+	private EModelService modelService;
+
+	private Category undefinedCategory;
+
+	private EventHandler additionHandler;
+
+	private ICommandManagerListener cmListener;
+
+	private final IEclipseContext context;
+
+	@Inject
+	public CommandProcessingAddon(IEclipseContext context) {
+		this.context = context;
+	}
+
+	/**
+	 * @param cmd
+	 * @param modelService
+	 * @param categoryModel
+	 * @return a command model element
+	 * @throws NotDefinedException
+	 */
+	public static MCommand createCommand(Command cmd, EModelService modelService,
+			final MCategory categoryModel) throws NotDefinedException {
+		MCommand command = modelService.createModelElement(MCommand.class);
+		command.setElementId(cmd.getId());
+		command.setCategory(categoryModel);
+		command.setCommandName(cmd.getName());
+		command.setDescription(cmd.getDescription());
+
+		// deal with parameters
+		// command.getParameters().addAll(parameters);
+		IParameter[] cmdParms = cmd.getParameters();
+		if (cmdParms != null) {
+			for (IParameter cmdParm : cmdParms) {
+				MCommandParameter parmModel = modelService
+						.createModelElement(MCommandParameter.class);
+				parmModel.setElementId(cmdParm.getId());
+				parmModel.setName(cmdParm.getName());
+				parmModel.setOptional(cmdParm.isOptional());
+				ParameterType parmType = cmd.getParameterType(cmdParm.getId());
+				if (parmType != null) {
+					parmModel.setTypeId(parmType.getId());
+				}
+				command.getParameters().add(parmModel);
+			}
+		}
+		return command;
+	}
+
+	@PostConstruct
+	public void init() {
+		Activator.trace(Policy.DEBUG_CMDS, "Initialize commands from model", null); //$NON-NLS-1$
+		undefinedCategory = commandService.defineCategory(MApplication.class.getName(),
+				"Application Category", null); //$NON-NLS-1$
+		createCategories();
+		createCommands();
+		registerModelListeners();
+		registerCommandListener();
+	}
+
+	@PreDestroy
+	public void dispose() {
+		unregisterCommandListener();
+		unregsiterModelListeners();
+	}
+
+	private void registerModelListeners() {
+		additionHandler = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				if (application == event.getProperty(UIEvents.EventTags.ELEMENT)) {
+					if (UIEvents.isADD(event)) {
+						for (Object obj : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
+							if (obj instanceof MCommand) {
+								createCommand((MCommand) obj);
+							} else if (obj instanceof MCategory) {
+								createCategory((MCategory) obj);
+							}
+						}
+					}
+				}
+			}
+		};
+		broker.subscribe(UIEvents.Application.TOPIC_COMMANDS, additionHandler);
+		broker.subscribe(UIEvents.Application.TOPIC_CATEGORIES, additionHandler);
+	}
+
+	private void unregsiterModelListeners() {
+		broker.unsubscribe(additionHandler);
+		broker.unsubscribe(additionHandler);
+	}
+
+	private void registerCommandListener() {
+		cmListener = new ICommandManagerListener() {
+			@SuppressWarnings("restriction")
+			@Override
+			public void commandManagerChanged(CommandManagerEvent commandManagerEvent) {
+				if (commandManagerEvent.isCommandChanged()) {
+					if (commandManagerEvent.isCommandDefined()) {
+						final String commandId = commandManagerEvent.getCommandId();
+						if (findCommand(commandId) != null) {
+							return;
+						}
+						final Command command = commandManagerEvent.getCommandManager().getCommand(
+								commandId);
+						if (command.getHandler() == null) {
+							command.setHandler(HandlerServiceImpl.getHandler(commandId, context));
+						}
+						try {
+							MCategory categoryModel = findCategory(command.getCategory().getId());
+							final MCommand createdCommand = createCommand(command, modelService,
+									categoryModel);
+							application.getCommands().add(createdCommand);
+						} catch (NotDefinedException e) {
+							Activator.getDefault().getLogService()
+									.log(0, "Failed to create command " + commandId, e); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		};
+		commandManager.addCommandManagerListener(cmListener);
+	}
+
+	private void unregisterCommandListener() {
+		commandManager.removeCommandManagerListener(cmListener);
+	}
+
+	protected MCommand findCommand(String commandId) {
+		for (MCommand cmd : application.getCommands()) {
+			if (commandId.equals(cmd.getElementId())) {
+				return cmd;
+			}
+		}
+		return null;
+	}
+
+	protected MCategory findCategory(String id) {
+		final List<MCategory> categories = application.getCategories();
+		for (MCategory cat : categories) {
+			if (id.equals(cat.getElementId())) {
+				return cat;
+			}
+		}
+		return null;
+	}
+
+	private void createCommands() {
+		for (MCommand cmdModel : application.getCommands()) {
+			createCommand(cmdModel);
+		}
+	}
+
+	private void createCommand(MCommand cmdModel) {
+		IParameter[] parms = null;
+		String id = cmdModel.getElementId();
+		String name = localize(cmdModel.getCommandName(), cmdModel);
+		String desc = localize(cmdModel.getDescription(), cmdModel);
+		List<MCommandParameter> modelParms = cmdModel.getParameters();
+		if (modelParms != null && !modelParms.isEmpty()) {
+			ArrayList<Parameter> parmList = new ArrayList<Parameter>();
+			for (MCommandParameter cmdParm : modelParms) {
+				ParameterType parameterType = null;
+				if (cmdParm.getTypeId() != null && cmdParm.getTypeId().length() > 0) {
+					parameterType = commandManager.getParameterType(cmdParm.getTypeId());
+				}
+				parmList.add(new Parameter(cmdParm.getElementId(), cmdParm.getName(), null,
+						parameterType, cmdParm.isOptional()));
+			}
+			parms = parmList.toArray(new Parameter[parmList.size()]);
+		}
+		Category cat = undefinedCategory;
+		if (cmdModel.getCategory() != null) {
+			cat = commandService.getCategory(cmdModel.getCategory().getElementId());
+		}
+		commandService.defineCommand(id, name, desc, cat, parms);
+	}
+
+	private void createCategories() {
+		for (MCategory catModel : application.getCategories()) {
+			createCategory(catModel);
+		}
+	}
+
+	private void createCategory(MCategory catModel) {
+		Category category = commandService.getCategory(catModel.getElementId());
+		if (!category.isDefined()) {
+			category.define(localize(catModel.getName(), catModel),
+					localize(catModel.getDescription(), catModel));
+		}
+	}
+
+	/**
+	 * Attempt to localize the provided key. Return the localized variant if found or the key itself
+	 * otherwise.
+	 *
+	 * @param key
+	 *            the possible key reference
+	 * @param modelElement
+	 *            the defining model element
+	 * @return the localized variant if found, or the key
+	 */
+	private String localize(String key, MApplicationElement modelElement) {
+		if (key == null) {
+			return null;
+		}
+		String localized = LocalizationHelper.getLocalized(key, modelElement);
+		return localized == null ? key : localized;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceContextFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceContextFunction.java
new file mode 100644
index 0000000..4faeddf
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceContextFunction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Dirk Fauth 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:
+ *    Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal;
+
+import org.eclipse.e4.core.services.nls.ILocaleChangeService;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+
+/**
+ * Context function to provide the LocaleChangeServiceImpl to the application context.
+ */
+public class LocaleChangeServiceContextFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		ILocaleChangeService lcService = ContextInjectionFactory.make(
+				LocaleChangeServiceImpl.class, context);
+
+		// add the new object to the application context
+		MApplication application = context.get(MApplication.class);
+		IEclipseContext ctx = application.getContext();
+		ctx.set(ILocaleChangeService.class, lcService);
+		return lcService;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceImpl.java
new file mode 100644
index 0000000..4bd8af0
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/LocaleChangeServiceImpl.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 Dirk Fauth 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:
+ *    Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
+ *    Fabian Miehe - Bug 440435
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal;
+
+import java.util.List;
+import java.util.Locale;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.internal.services.ResourceBundleHelper;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.nls.ILocaleChangeService;
+import org.eclipse.e4.core.services.translation.TranslationService;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MLocalizable;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.osgi.service.log.LogService;
+
+/**
+ * Default implementation of {@link ILocaleChangeService} that changes the {@link Locale} in the
+ * specified {@link IEclipseContext} and additionally fires an event on the event bus.
+ *
+ * @author Dirk Fauth
+ *
+ */
+@SuppressWarnings("restriction")
+public class LocaleChangeServiceImpl implements ILocaleChangeService {
+
+	MApplication application;
+
+	@Inject
+	IEventBroker broker;
+
+	@Inject
+	@Optional
+	LogService logService;
+
+	/**
+	 * Create a new {@link LocaleChangeServiceImpl} for the given {@link IEclipseContext}.
+	 *
+	 * @param application
+	 *            The application to retrieve the context from.
+	 */
+	@Inject
+	public LocaleChangeServiceImpl(MApplication application) {
+		this.application = application;
+	}
+
+	@Override
+	public void changeApplicationLocale(Locale locale) {
+
+		// the TranslationService.LOCALE context parameter is specified as String
+		// so we put the String representation of the given Locale to the context
+		this.application.getContext().set(TranslationService.LOCALE, locale);
+
+		// update model
+		updateLocalization(this.application.getChildren());
+
+		// fire event
+		broker.post(LOCALE_CHANGE, locale);
+	}
+
+	@Override
+	public void changeApplicationLocale(String localeString) {
+		try {
+			Locale locale = ResourceBundleHelper.toLocale(localeString);
+
+			// set the locale to the application context
+			// use the resolved locale instead of the given locale string to avoid invalid locales
+			// in context
+			this.application.getContext().set(TranslationService.LOCALE, locale);
+
+			// update model
+			updateLocalization(this.application.getChildren());
+
+			// fire event
+			broker.post(LOCALE_CHANGE, locale);
+		} catch (Exception e) {
+			// performing a locale update failed
+			// there is no locale change performed
+			if (logService != null)
+				logService.log(LogService.LOG_ERROR, e.getMessage()
+						+ " - No Locale change will be performed."); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Will iterate over the given list of {@link MUIElement}s and inform them about the Locale
+	 * change if necessary.
+	 *
+	 * @param children
+	 *            The list of {@link MUIElement}s that should be checked for Locale updates.
+	 */
+	@SuppressWarnings({ "rawtypes" })
+	protected void updateLocalization(List<? extends MUIElement> children) {
+		for (MUIElement element : children) {
+			if (element instanceof MElementContainer) {
+				updateLocalization(((MElementContainer) element).getChildren());
+			}
+
+			if (element instanceof MWindow) {
+				MWindow window = (MWindow) element;
+				MMenu mainMenu = window.getMainMenu();
+				if (mainMenu != null) {
+					mainMenu.updateLocalization();
+					updateLocalization(mainMenu.getChildren());
+				}
+				updateLocalization(window.getSharedElements());
+				updateLocalization(window.getWindows());
+			}
+
+			if (element instanceof MTrimmedWindow) {
+				for (MTrimBar trimBar : ((MTrimmedWindow) element).getTrimBars()) {
+					trimBar.updateLocalization();
+					updateLocalization(trimBar.getChildren());
+				}
+			}
+
+			if (element instanceof MPerspective) {
+				updateLocalization(((MPerspective) element).getWindows());
+			}
+
+			if (element instanceof MPart) {
+				MPart mPart = (MPart) element;
+				MToolBar toolbar = mPart.getToolbar();
+				if (toolbar != null && toolbar.getChildren() != null) {
+					toolbar.updateLocalization();
+					updateLocalization(toolbar.getChildren());
+				}
+			}
+
+			((MLocalizable) element).updateLocalization();
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java
new file mode 100644
index 0000000..fdbb95f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.List;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.service.debug.DebugOptions;
+import org.eclipse.osgi.service.debug.DebugTrace;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * BundleActivator to access the required OSGi services.
+ */
+public class Activator implements BundleActivator {
+	/**
+	 * The bundle symbolic name.
+	 */
+	public static final String PI_WORKBENCH = "org.eclipse.e4.ui.workbench"; //$NON-NLS-1$
+
+	private static Activator activator;
+
+	private BundleContext context;
+	private ServiceTracker<Location, Location> locationTracker;
+
+	private ServiceTracker<DebugOptions, DebugOptions> debugTracker;
+	private ServiceTracker<LogService, LogService> logTracker;
+
+	/** Tracks all bundles which are in the state: RESOLVED, STARTING, ACTIVE or STOPPING. */
+	private BundleTracker<List<Bundle>> resolvedBundles;
+
+	/** A BundleTrackerCustomizer which is able to resolve a bundle to the a symbolic name. */
+	private final BundleFinder bundleFinder = new BundleFinder();
+
+	private DebugTrace trace;
+
+	/**
+	 * Get the default activator.
+	 *
+	 * @return a BundleActivator
+	 */
+	public static Activator getDefault() {
+		return activator;
+	}
+
+	/**
+	 * @return the bundle object
+	 */
+	public Bundle getBundle() {
+		return context.getBundle();
+	}
+
+	/**
+	 * @param bundleName
+	 *            the bundle symbolic name
+	 * @return A bundle if found, or <code>null</code>
+	 */
+	public Bundle getBundleForName(String bundleName) {
+		return bundleFinder.findBundle(bundleName);
+	}
+
+	/**
+	 * @return this bundles context
+	 */
+	public BundleContext getContext() {
+		return context;
+	}
+
+	/**
+	 * @return the instance Location service
+	 */
+	public Location getInstanceLocation() {
+		if (locationTracker == null) {
+			Filter filter = null;
+			try {
+				filter = context.createFilter(Location.INSTANCE_FILTER);
+			} catch (InvalidSyntaxException e) {
+				// ignore this. It should never happen as we have tested the
+				// above format.
+			}
+			locationTracker = new ServiceTracker<Location, Location>(context, filter, null);
+			locationTracker.open();
+		}
+		return locationTracker.getService();
+	}
+
+	@Override
+	public void start(BundleContext context) throws Exception {
+		activator = this;
+		this.context = context;
+
+		// track required bundles
+		resolvedBundles = new BundleTracker<List<Bundle>>(context, Bundle.RESOLVED
+				| Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING, bundleFinder);
+		resolvedBundles.open();
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		if (locationTracker != null) {
+			locationTracker.close();
+			locationTracker = null;
+		}
+		if (debugTracker != null) {
+			trace = null;
+			debugTracker.close();
+			debugTracker = null;
+		}
+		if (logTracker != null) {
+			logTracker.close();
+			logTracker = null;
+		}
+		if (resolvedBundles != null) {
+			// the close of the BundleTracker will also remove all entries form the BundleFinder
+			resolvedBundles.close();
+			resolvedBundles = null;
+		}
+	}
+
+	public DebugOptions getDebugOptions() {
+		if (debugTracker == null) {
+			if (context == null)
+				return null;
+			debugTracker = new ServiceTracker<DebugOptions, DebugOptions>(context,
+					DebugOptions.class.getName(), null);
+			debugTracker.open();
+		}
+		return debugTracker.getService();
+	}
+
+	public DebugTrace getTrace() {
+		if (trace == null) {
+			trace = getDebugOptions().newDebugTrace(PI_WORKBENCH);
+		}
+		return trace;
+	}
+
+	public static void trace(String option, String msg, Throwable error) {
+		final DebugOptions debugOptions = activator.getDebugOptions();
+		if (debugOptions.isDebugEnabled()
+				&& debugOptions.getBooleanOption(PI_WORKBENCH + option, false)) {
+			System.out.println(msg);
+			if (error != null) {
+				error.printStackTrace(System.out);
+			}
+		}
+		activator.getTrace().trace(option, msg, error);
+	}
+
+	public LogService getLogService() {
+		LogService logService = null;
+		if (logTracker != null) {
+			logService = logTracker.getService();
+		} else {
+			if (context != null) {
+				logTracker = new ServiceTracker<LogService, LogService>(context,
+						LogService.class.getName(), null);
+				logTracker.open();
+				logService = logTracker.getService();
+			}
+		}
+		if (logService == null) {
+			logService = new LogService() {
+				@Override
+				public void log(int level, String message) {
+					log(null, level, message, null);
+				}
+
+				@Override
+				public void log(int level, String message, Throwable exception) {
+					log(null, level, message, exception);
+				}
+
+				@Override
+				public void log(ServiceReference sr, int level, String message) {
+					log(sr, level, message, null);
+				}
+
+				@Override
+				public void log(ServiceReference sr, int level, String message, Throwable exception) {
+					if (level == LogService.LOG_ERROR) {
+						System.err.print("ERROR: "); //$NON-NLS-1$
+					} else if (level == LogService.LOG_WARNING) {
+						System.err.print("WARNING: "); //$NON-NLS-1$
+					} else if (level == LogService.LOG_INFO) {
+						System.err.print("INFO: "); //$NON-NLS-1$
+					} else if (level == LogService.LOG_DEBUG) {
+						System.err.print("DEBUG: "); //$NON-NLS-1$
+					} else {
+						System.err.print("log level " + level + ": "); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					System.err.println(message);
+					if (exception != null) {
+						exception.printStackTrace(System.err);
+					}
+				}
+			};
+		}
+		return logService;
+	}
+
+	public static void log(int level, String message) {
+		LogService logService = activator.getLogService();
+		if (logService != null)
+			logService.log(level, message);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		LogService logService = activator.getLogService();
+		if (logService != null)
+			logService.log(level, message, exception);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActiveChildLookupFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActiveChildLookupFunction.java
new file mode 100644
index 0000000..1547c8a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActiveChildLookupFunction.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ *
+ */
+public class ActiveChildLookupFunction extends ContextFunction {
+
+	private String localVar;
+	private String var;
+
+	public ActiveChildLookupFunction(String var, String localVar) {
+		this.var = var;
+		this.localVar = localVar;
+	}
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		IEclipseContext childContext = context.getActiveChild();
+		if (childContext != null) {
+			return childContext.get(var);
+		}
+		return context.get(localVar);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActivePartLookupFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActivePartLookupFunction.java
new file mode 100644
index 0000000..2294310
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ActivePartLookupFunction.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+
+/**
+ *
+ */
+public class ActivePartLookupFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		/**
+		 * This is the specific implementation. TODO: generalize it
+		 */
+		MContext window = context.get(MWindow.class);
+		if (window == null) {
+			window = context.get(MApplication.class);
+			if (window == null) {
+				return null;
+			}
+		}
+		IEclipseContext current = window.getContext();
+		if (current == null) {
+			return null;
+		}
+		return current.getActiveLeaf().get(MPart.class);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ApplicationPartServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ApplicationPartServiceImpl.java
new file mode 100644
index 0000000..5554f65
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ApplicationPartServiceImpl.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 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.internal.workbench;
+
+import java.util.Collection;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.IPartListener;
+
+public class ApplicationPartServiceImpl implements EPartService {
+
+	private MApplication application;
+
+	@Inject
+	ApplicationPartServiceImpl(MApplication application) {
+		this.application = application;
+	}
+
+	private EPartService getActiveWindowService() {
+		IEclipseContext activeWindowContext = application.getContext().getActiveChild();
+		if (activeWindowContext == null) {
+			throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
+		}
+		EPartService activeWindowPartService = activeWindowContext.get(EPartService.class);
+		if (activeWindowPartService == null) {
+			throw new IllegalStateException("Active window context is invalid"); //$NON-NLS-1$
+		}
+		if (activeWindowPartService == this) {
+			throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
+		}
+		return activeWindowPartService;
+	}
+
+	@Override
+	public void addPartListener(IPartListener listener) {
+		throw new UnsupportedOperationException(
+				"Listeners should only be attached/removed from a window's part service"); //$NON-NLS-1$
+	}
+
+	@Override
+	public void removePartListener(IPartListener listener) {
+		throw new UnsupportedOperationException(
+				"Listeners should only be attached/removed from a window's part service"); //$NON-NLS-1$
+	}
+
+	@Override
+	public boolean isPartOrPlaceholderInPerspective(String elementId, MPerspective perspective) {
+		return getActiveWindowService().isPartOrPlaceholderInPerspective(elementId, perspective);
+	}
+
+	@Override
+	public void switchPerspective(MPerspective perspective) {
+		getActiveWindowService().switchPerspective(perspective);
+	}
+
+	@Override
+	public void activate(MPart part) {
+		getActiveWindowService().activate(part);
+	}
+
+	@Override
+	public void activate(MPart part, boolean requiresFocus) {
+		getActiveWindowService().activate(part, requiresFocus);
+	}
+
+	@Override
+	public void requestActivation() {
+		getActiveWindowService().requestActivation();
+	}
+
+	@Override
+	public void bringToTop(MPart part) {
+		getActiveWindowService().bringToTop(part);
+	}
+
+	@Override
+	public MPart findPart(String id) {
+		return getActiveWindowService().findPart(id);
+	}
+
+	@Override
+	public Collection<MPart> getParts() {
+		return getActiveWindowService().getParts();
+	}
+
+	@Override
+	public MPart getActivePart() {
+		return getActiveWindowService().getActivePart();
+	}
+
+	@Override
+	public boolean isPartVisible(MPart part) {
+		return getActiveWindowService().isPartVisible(part);
+	}
+
+	@Override
+	public MPart createPart(String id) {
+		return getActiveWindowService().createPart(id);
+	}
+
+	@Override
+	public MPlaceholder createSharedPart(String id) {
+		return getActiveWindowService().createSharedPart(id);
+	}
+
+	@Override
+	public MPlaceholder createSharedPart(String id, boolean force) {
+		return getActiveWindowService().createSharedPart(id, force);
+	}
+
+	@Override
+	public MPart showPart(String id, PartState partState) {
+		return getActiveWindowService().showPart(id, partState);
+	}
+
+	@Override
+	public MPart showPart(MPart part, PartState partState) {
+		return getActiveWindowService().showPart(part, partState);
+	}
+
+	@Override
+	public void hidePart(MPart part) {
+		getActiveWindowService().hidePart(part);
+	}
+
+	@Override
+	public void hidePart(MPart part, boolean force) {
+		getActiveWindowService().hidePart(part, force);
+	}
+
+	@Override
+	public Collection<MPart> getDirtyParts() {
+		return getActiveWindowService().getDirtyParts();
+	}
+
+	@Override
+	public boolean savePart(MPart part, boolean confirm) {
+		return getActiveWindowService().savePart(part, confirm);
+	}
+
+	@Override
+	public boolean saveAll(boolean confirm) {
+		return getActiveWindowService().saveAll(confirm);
+	}
+
+	@Override
+	public Collection<MInputPart> getInputParts(String inputUri) {
+		return getActiveWindowService().getInputParts(inputUri);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java
new file mode 100644
index 0000000..6abe963
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+/**
+ * A simple {@link BundleTrackerCustomizer} which is able to resolve a bundle by its symbolic name.
+ */
+/*
+ * TODO: This implementation can probably be removed after a switch to OSGi 6 which will have the
+ * possibility to lookup bundles with the FrameworkWiring#findProviders(Requirement) method.
+ */
+final class BundleFinder implements BundleTrackerCustomizer<List<Bundle>> {
+
+	/** Map of bundle symbolic name to the corresponding bundles (hint: different versions). */
+	private final ConcurrentMap<String, List<Bundle>> trackedBundles = new ConcurrentHashMap<String, List<Bundle>>();
+
+	/**
+	 * Resolves the latest bundle with the given bundle symbolic name.
+	 * <p>
+	 * The latest means the bundle with the highest version.
+	 * </p>
+	 * @param symbolicName
+	 *            the bundle symbolic name
+	 * @return the latest bundle with the given bundle symbolic name
+	 */
+	public Bundle findBundle(String symbolicName) {
+		List<Bundle> bundlesWithSameSymName = trackedBundles.get(symbolicName);
+		if (bundlesWithSameSymName == null)
+			return null;
+
+		List<Bundle> snapshot = new ArrayList<Bundle>(bundlesWithSameSymName);
+
+		switch (snapshot.size()) {
+		case 0:
+			return null;
+		case 1:
+			return snapshot.get(0);
+		default:
+			Collections.sort(snapshot, VersionComperator.INSTANCE); // sort the snapshot by version
+			return snapshot.get(0); // the highest is the first entry in the list
+		}
+	}
+
+	@Override
+	public List<Bundle> addingBundle(Bundle bundle, BundleEvent event) {
+		String bundleSymName = bundle.getSymbolicName();
+		if (bundleSymName == null) {
+			return null;
+		}
+
+		List<Bundle> bundlesWithSameSymName = trackedBundles.get(bundleSymName);
+		if (bundlesWithSameSymName == null) {
+			bundlesWithSameSymName = new CopyOnWriteArrayList<Bundle>();
+
+			if (trackedBundles.putIfAbsent(bundleSymName, bundlesWithSameSymName) != null) {
+				// some other thread has won the race, so we use his List object
+				bundlesWithSameSymName = trackedBundles.get(bundleSymName);
+			}
+		}
+
+		bundlesWithSameSymName.add(bundle);
+
+		// return the list to mark that we want to be informed about other changes of the bundle and
+		// to remove the bundle in the #removedBundle() method without a lookup in the
+		// #trackedBundles map
+		return bundlesWithSameSymName;
+	}
+
+	@Override
+	public void modifiedBundle(Bundle bundle, BundleEvent event, List<Bundle> bundlesWithSameSymName) {
+		// not of interest
+	}
+
+	@Override
+	public void removedBundle(Bundle bundle, BundleEvent event, List<Bundle> bundlesWithSameSymName) {
+		// the object is the list which was returned inside the #addingBundle() method and so we
+		// don't need a lookup in the #trackedBundles to find the list
+		bundlesWithSameSymName.remove(bundle);
+	}
+
+	/**
+	 * A simple {@link Comparator} which orders the bundles by their version in ascending order.
+	 */
+	private static final class VersionComperator implements Comparator<Bundle> {
+		/** A Singleton instance of this {@link Comparator} (the compare is done state-less). */
+		public static final Comparator<Bundle> INSTANCE = new VersionComperator();
+
+		private VersionComperator() {
+		}
+
+		@Override
+		public int compare(Bundle bundle1, Bundle bundle2) {
+			if (bundle1 == null) {
+				return bundle2 == null ? 0 : 1; // null elements at the end of the list
+			}
+
+			if (bundle2 == null) {
+				return -1; // null elements at the end of the list
+			}
+
+			return bundle2.getVersion().compareTo(bundle1.getVersion()); // newest version first
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CommandLineOptionModelProcessor.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CommandLineOptionModelProcessor.java
new file mode 100644
index 0000000..8921e27
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CommandLineOptionModelProcessor.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import java.util.List;
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+/**
+ *
+ */
+public class CommandLineOptionModelProcessor {
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	private EModelService modelService;
+
+	@SuppressWarnings("javadoc")
+	public void process() {
+		selectForcedPerspective();
+	}
+
+	private void selectForcedPerspective() {
+		String forcedPerspectiveId = (String) context.get(E4Workbench.FORCED_PERSPECTIVE_ID);
+		if (forcedPerspectiveId == null) {
+			return;
+		}
+
+		List<MPerspectiveStack> perspStackList = modelService.findElements(application, null,
+				MPerspectiveStack.class, null);
+
+		if (perspStackList.isEmpty()) {
+			return;
+		}
+
+		MPerspectiveStack perspStack = perspStackList.get(0);
+		MPerspective selected = perspStack.getSelectedElement();
+
+		if (selected != null && selected.getElementId().equals(forcedPerspectiveId)) {
+			return;
+		}
+
+		for (MPerspective persp : perspStack.getChildren()) {
+			if (persp.getElementId().equals(forcedPerspectiveId)) {
+				perspStack.setSelectedElement(persp);
+				return;
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CompositeDelta.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CompositeDelta.java
new file mode 100644
index 0000000..4367572
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/CompositeDelta.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.LinkedList;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.workbench.modeling.IDelta;
+
+public class CompositeDelta implements IDelta {
+
+	private final Object object;
+
+	private final LinkedList<IDelta> deltas = new LinkedList<IDelta>();
+
+	public CompositeDelta(Object object) {
+		this.object = object;
+	}
+
+	public void add(IDelta delta) {
+		deltas.add(delta);
+	}
+
+	@Override
+	public IStatus apply() {
+		for (IDelta delta : deltas) {
+			delta.apply();
+		}
+		return Status.OK_STATUS;
+	}
+
+	@Override
+	public Object getObject() {
+		return object;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ConfigurationElementAdapter.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ConfigurationElementAdapter.java
new file mode 100644
index 0000000..853ef56
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ConfigurationElementAdapter.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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
+ *     Simon Scholz <simon.scholz@vogella.com> - Bug 460405
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.e4.ui.workbench.modeling.ModelHandlerBase;
+
+public class ConfigurationElementAdapter extends ModelHandlerBase implements IAdapterFactory {
+
+	public static final String CLASS_IMPL = "classImpl"; //$NON-NLS-1$
+
+	@Override
+	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
+		if (adapterType.isInstance(this)) {
+			return adapterType.cast(this);
+		}
+		return null;
+	}
+
+	@Override
+	public Class<?>[] getAdapterList() {
+		return new Class[] { ModelHandlerBase.class };
+	}
+
+	@Override
+	public Object[] getChildren(Object element, String id) {
+		IConfigurationElement ice = (IConfigurationElement) element;
+		IConfigurationElement[] kids = ice.getChildren(id);
+		return kids;
+	}
+
+	@Override
+	public Object getProperty(Object element, String id) {
+		IConfigurationElement ice = (IConfigurationElement) element;
+
+		// Construct a meaningful 'label'
+		if ("label".equals(id)) { //$NON-NLS-1$
+			String idVal = ice.getAttribute("id"); //$NON-NLS-1$
+			String nameVal = ice.getAttribute("name"); //$NON-NLS-1$
+
+			String constructedName = ""; //$NON-NLS-1$
+			if (nameVal != null) {
+				constructedName = nameVal;
+				if (idVal != null)
+					constructedName += " [" + idVal + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+			} else if (idVal != null) {
+				constructedName = idVal;
+			} else
+				constructedName = ice.getName();
+
+			return constructedName;
+		} else if (CLASS_IMPL.equals(id)) {
+			try {
+				return ice.createExecutableExtension("class"); //$NON-NLS-1$
+			} catch (CoreException e) {
+				e.printStackTrace();
+			}
+			return null;
+		}
+
+		return ice.getAttribute(id);
+	}
+
+	@Override
+	public String[] getPropIds(Object element) {
+		IConfigurationElement ice = (IConfigurationElement) element;
+		return ice.getAttributeNames();
+	}
+
+	@Override
+	public void setProperty(Object element, String id, Object value) {
+		super.setProperty(element, id, value);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ContributionsAnalyzer.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ContributionsAnalyzer.java
new file mode 100644
index 0000000..bfdc3b2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ContributionsAnalyzer.java
@@ -0,0 +1,770 @@
+/*******************************************************************************
+ * 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
+ *      Maxime Porhel <maxime.porhel@obeo.fr> Obeo - Bug 435949
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.core.internal.expressions.ReferenceExpression;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MExpression;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+public final class ContributionsAnalyzer {
+	public static void trace(String msg, Throwable error) {
+		Activator.trace("/trace/menus", msg, error); //$NON-NLS-1$
+	}
+
+	private static boolean DEBUG = true;
+
+	private static void trace(String msg, Object menu, Object menuModel) {
+		trace(msg + ": " + menu + ": " + menuModel, null); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	public static void gatherTrimContributions(MTrimBar trimModel,
+			List<MTrimContribution> trimContributions, String elementId,
+			ArrayList<MTrimContribution> toContribute, ExpressionContext eContext) {
+		if (elementId == null || elementId.length() == 0) {
+			return;
+		}
+		for (MTrimContribution contribution : trimContributions) {
+			String parentId = contribution.getParentId();
+			boolean filtered = isFiltered(trimModel, contribution);
+			if (filtered || !elementId.equals(parentId) || !contribution.isToBeRendered()) {
+				continue;
+			}
+			toContribute.add(contribution);
+		}
+	}
+
+	static boolean isFiltered(MTrimBar trimModel, MTrimContribution contribution) {
+		return false;
+	}
+
+	public static void XXXgatherToolBarContributions(final MToolBar toolbarModel,
+			final List<MToolBarContribution> toolbarContributionList, final String id,
+			final ArrayList<MToolBarContribution> toContribute) {
+		if (id == null || id.length() == 0) {
+			return;
+		}
+		for (MToolBarContribution toolBarContribution : toolbarContributionList) {
+			String parentID = toolBarContribution.getParentId();
+			boolean filtered = isFiltered(toolbarModel, toolBarContribution);
+			if (filtered || !id.equals(parentID) || !toolBarContribution.isToBeRendered()) {
+				continue;
+			}
+			toContribute.add(toolBarContribution);
+		}
+	}
+
+	public static void gatherToolBarContributions(final MToolBar toolbarModel,
+			final List<MToolBarContribution> toolbarContributionList, final String id,
+			final ArrayList<MToolBarContribution> toContribute, final ExpressionContext eContext) {
+		if (id == null || id.length() == 0) {
+			return;
+		}
+		for (MToolBarContribution toolBarContribution : toolbarContributionList) {
+			String parentID = toolBarContribution.getParentId();
+			boolean filtered = isFiltered(toolbarModel, toolBarContribution);
+			if (filtered || !id.equals(parentID) || !toolBarContribution.isToBeRendered()) {
+				continue;
+			}
+			toContribute.add(toolBarContribution);
+		}
+	}
+
+	static boolean isFiltered(MToolBar toolbarModel, MToolBarContribution toolBarContribution) {
+		return false;
+	}
+
+	public static void XXXgatherMenuContributions(final MMenu menuModel,
+			final List<MMenuContribution> menuContributionList, final String id,
+			final ArrayList<MMenuContribution> toContribute, final ExpressionContext eContext,
+			boolean includePopups) {
+		if (id == null || id.length() == 0) {
+			return;
+		}
+		ArrayList<String> popupIds = new ArrayList<String>();
+		if (includePopups) {
+			popupIds.add(id);
+			for (String tag : menuModel.getTags()) {
+				if (tag.startsWith("popup:")) { //$NON-NLS-1$
+					String tmp = tag.substring("popup:".length()); //$NON-NLS-1$
+					if (!popupIds.contains(tmp)) {
+						popupIds.add(tmp);
+					}
+				}
+			}
+		}
+		ArrayList<MMenuContribution> includedPopups = new ArrayList<MMenuContribution>();
+		for (MMenuContribution menuContribution : menuContributionList) {
+			String parentID = menuContribution.getParentId();
+			if (parentID == null) {
+				// it doesn't make sense for this to be null, temporary workaround for bug 320790
+				continue;
+			}
+			boolean popupTarget = includePopups && popupIds.contains(parentID);
+			boolean popupAny = includePopups && menuModel instanceof MPopupMenu
+					&& POPUP_PARENT_ID.equals(parentID);
+			boolean filtered = isFiltered(menuModel, menuContribution, includePopups);
+			if (!filtered && menuContribution.isToBeRendered() && popupAny) {
+				// process POPUP_ANY first
+				toContribute.add(menuContribution);
+			} else {
+				if (filtered || (!popupTarget && !parentID.equals(id))
+				|| !menuContribution.isToBeRendered()) {
+					continue;
+				}
+				includedPopups.add(menuContribution);
+			}
+		}
+		toContribute.addAll(includedPopups);
+	}
+
+	public static void gatherMenuContributions(final MMenu menuModel,
+			final List<MMenuContribution> menuContributionList, final String id,
+			final ArrayList<MMenuContribution> toContribute, final ExpressionContext eContext,
+			boolean includePopups) {
+		if (id == null || id.length() == 0) {
+			return;
+		}
+		boolean menuBar = (((MUIElement) ((EObject) menuModel).eContainer()) instanceof MWindow);
+		for (MMenuContribution menuContribution : menuContributionList) {
+			String parentID = menuContribution.getParentId();
+			if (parentID == null) {
+				// it doesn't make sense for this to be null, temporary workaround for bug 320790
+				continue;
+			}
+			boolean popup = parentID.equals(POPUP_PARENT_ID) && (menuModel instanceof MPopupMenu)
+					&& includePopups;
+			boolean filtered = isFiltered(menuModel, menuContribution, includePopups);
+			if (filtered || (!popup && !parentID.equals(id)) || !menuContribution.isToBeRendered()) {
+				continue;
+			}
+			if (menuBar || isVisible(menuContribution, eContext)) {
+				toContribute.add(menuContribution);
+			}
+		}
+	}
+
+	static boolean isFiltered(MMenu menuModel, MMenuContribution menuContribution,
+			boolean includePopups) {
+		if (includePopups || menuModel.getTags().contains(ContributionsAnalyzer.MC_POPUP)) {
+			return !menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP)
+					&& menuContribution.getTags().contains(ContributionsAnalyzer.MC_MENU);
+		}
+		if (menuModel.getTags().contains(ContributionsAnalyzer.MC_MENU)) {
+			return !menuContribution.getTags().contains(ContributionsAnalyzer.MC_MENU)
+					&& menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP);
+		}
+		if (!includePopups) {
+			// not including popups, so filter out popup menu contributions if the menu is a regular
+			// menu
+			return menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP);
+		}
+		return false;
+	}
+
+	public static void collectInfo(ExpressionInfo info, MExpression exp) {
+		if (!(exp instanceof MCoreExpression)) {
+			return;
+		}
+		MCoreExpression expr = (MCoreExpression) exp;
+		Expression ref = null;
+		if (expr.getCoreExpression() instanceof Expression) {
+			ref = (Expression) expr.getCoreExpression();
+		} else {
+			ref = new ReferenceExpression(expr.getCoreExpressionId());
+			expr.setCoreExpression(ref);
+		}
+		ref.collectExpressionInfo(info);
+	}
+
+	public static boolean isVisible(MMenuContribution menuContribution, ExpressionContext eContext) {
+		if (menuContribution.getVisibleWhen() == null) {
+			return true;
+		}
+		return isVisible((MCoreExpression) menuContribution.getVisibleWhen(), eContext);
+	}
+
+	public static boolean isVisible(MToolBarContribution contribution, ExpressionContext eContext) {
+		if (contribution.getVisibleWhen() == null) {
+			return true;
+		}
+		return isVisible((MCoreExpression) contribution.getVisibleWhen(), eContext);
+	}
+
+	public static boolean isVisible(MTrimContribution contribution, ExpressionContext eContext) {
+		if (contribution.getVisibleWhen() == null) {
+			return true;
+		}
+		return isVisible((MCoreExpression) contribution.getVisibleWhen(), eContext);
+	}
+
+	public static boolean isVisible(MCoreExpression exp, final ExpressionContext eContext) {
+		final Expression ref;
+		if (exp.getCoreExpression() instanceof Expression) {
+			ref = (Expression) exp.getCoreExpression();
+		} else {
+			ref = new ReferenceExpression(exp.getCoreExpressionId());
+			exp.setCoreExpression(ref);
+		}
+		// Creates dependency on a predefined value that can be "poked" by the evaluation
+		// service
+		ExpressionInfo info = ref.computeExpressionInfo();
+		String[] names = info.getAccessedPropertyNames();
+		for (String name : names) {
+			eContext.getVariable(name + ".evaluationServiceLink"); //$NON-NLS-1$
+		}
+		boolean ret = false;
+		try {
+			ret = ref.evaluate(eContext) != EvaluationResult.FALSE;
+		} catch (Exception e) {
+			trace("isVisible exception", e); //$NON-NLS-1$
+		}
+		return ret;
+	}
+
+	public static void addMenuContributions(final MMenu menuModel,
+			final ArrayList<MMenuContribution> toContribute,
+			final ArrayList<MMenuElement> menuContributionsToRemove) {
+
+		HashSet<String> existingMenuIds = new HashSet<String>();
+		HashSet<String> existingSeparatorNames = new HashSet<String>();
+		for (MMenuElement child : menuModel.getChildren()) {
+			String elementId = child.getElementId();
+			if (child instanceof MMenu && elementId != null) {
+				existingMenuIds.add(elementId);
+			} else if (child instanceof MMenuSeparator && elementId != null) {
+				existingSeparatorNames.add(elementId);
+			}
+		}
+
+		boolean done = toContribute.size() == 0;
+		while (!done) {
+			ArrayList<MMenuContribution> curList = new ArrayList<MMenuContribution>(toContribute);
+			int retryCount = toContribute.size();
+			toContribute.clear();
+
+			for (MMenuContribution menuContribution : curList) {
+				if (!processAddition(menuModel, menuContributionsToRemove, menuContribution,
+						existingMenuIds, existingSeparatorNames)) {
+					toContribute.add(menuContribution);
+				}
+			}
+			// We're done if the retryList is now empty (everything done) or
+			// if the list hasn't changed at all (no hope)
+			done = (toContribute.size() == 0) || (toContribute.size() == retryCount);
+		}
+	}
+
+	public static boolean processAddition(final MMenu menuModel,
+			final ArrayList<MMenuElement> menuContributionsToRemove,
+			MMenuContribution menuContribution, final HashSet<String> existingMenuIds,
+			HashSet<String> existingSeparatorNames) {
+		int idx = getIndex(menuModel, menuContribution.getPositionInParent());
+		if (idx == -1) {
+			return false;
+		}
+		for (MMenuElement item : menuContribution.getChildren()) {
+			if (item instanceof MMenu && existingMenuIds.contains(item.getElementId())) {
+				// skip this, it's already there
+				continue;
+			} else if (item instanceof MMenuSeparator
+					&& existingSeparatorNames.contains(item.getElementId())) {
+				// skip this, it's already there
+				continue;
+			}
+			MMenuElement copy = (MMenuElement) EcoreUtil.copy((EObject) item);
+			if (DEBUG) {
+				trace("addMenuContribution " + copy, menuModel.getWidget(), menuModel); //$NON-NLS-1$
+			}
+			menuContributionsToRemove.add(copy);
+			menuModel.getChildren().add(idx++, copy);
+			if (copy instanceof MMenu && copy.getElementId() != null) {
+				existingMenuIds.add(copy.getElementId());
+			} else if (copy instanceof MMenuSeparator && copy.getElementId() != null) {
+				existingSeparatorNames.add(copy.getElementId());
+			}
+		}
+		return true;
+	}
+
+	public static boolean processAddition(final MToolBar toolBarModel,
+			MToolBarContribution toolBarContribution, List<MToolBarElement> contributions,
+			HashSet<String> existingSeparatorNames) {
+		int idx = getIndex(toolBarModel, toolBarContribution.getPositionInParent());
+		if (idx == -1) {
+			return false;
+		}
+		for (MToolBarElement item : toolBarContribution.getChildren()) {
+			if (item instanceof MToolBarSeparator
+					&& existingSeparatorNames.contains(item.getElementId())) {
+				// skip this, it's already there
+				continue;
+			}
+			MToolBarElement copy = (MToolBarElement) EcoreUtil.copy((EObject) item);
+			if (DEBUG) {
+				trace("addToolBarContribution " + copy, toolBarModel.getWidget(), toolBarModel); //$NON-NLS-1$
+			}
+			toolBarModel.getChildren().add(idx++, copy);
+			contributions.add(copy);
+			if (copy instanceof MToolBarSeparator && copy.getElementId() != null) {
+				existingSeparatorNames.add(copy.getElementId());
+			}
+		}
+		return true;
+	}
+
+	public static boolean processAddition(final MTrimBar trimBar, MTrimContribution contribution,
+			List<MTrimElement> contributions, HashSet<String> existingToolbarIds) {
+		int idx = getIndex(trimBar, contribution.getPositionInParent());
+		if (idx == -1) {
+			return false;
+		}
+		for (MTrimElement item : contribution.getChildren()) {
+			if (item instanceof MToolBar && existingToolbarIds.contains(item.getElementId())) {
+				// skip this, it's already there
+				continue;
+			}
+			MTrimElement copy = (MTrimElement) EcoreUtil.copy((EObject) item);
+			if (DEBUG) {
+				trace("addTrimContribution " + copy, trimBar.getWidget(), trimBar); //$NON-NLS-1$
+			}
+			trimBar.getChildren().add(idx++, copy);
+			contributions.add(copy);
+			if (copy instanceof MToolBar && copy.getElementId() != null) {
+				existingToolbarIds.add(copy.getElementId());
+			}
+		}
+		return true;
+	}
+
+	private static int getIndex(MElementContainer<?> menuModel, String positionInParent) {
+		String id = null;
+		String modifier = null;
+		if (positionInParent != null && positionInParent.length() > 0) {
+			String[] array = positionInParent.split("="); //$NON-NLS-1$
+			modifier = array[0];
+			// may have an invalid position, check for this
+			if (array.length > 1) {
+				id = array[1];
+			}
+		}
+		if (id == null) {
+			return menuModel.getChildren().size();
+		}
+
+		int idx = 0;
+		int size = menuModel.getChildren().size();
+		while (idx < size) {
+			if (id.equals(menuModel.getChildren().get(idx).getElementId())) {
+				if ("after".equals(modifier)) { //$NON-NLS-1$
+					idx++;
+				}
+				return idx;
+			}
+			idx++;
+		}
+		return id.equals("additions") ? menuModel.getChildren().size() : -1; //$NON-NLS-1$
+	}
+
+	public static MCommand getCommandById(MApplication app, String cmdId) {
+		final List<MCommand> cmds = app.getCommands();
+		for (MCommand cmd : cmds) {
+			if (cmdId.equals(cmd.getElementId())) {
+				return cmd;
+			}
+		}
+		return null;
+	}
+
+	static class Key {
+		private int tag = -1;
+		private int hc = -1;
+		private String parentId;
+		private String position;
+		private MCoreExpression vexp;
+		private Object factory;
+
+		public Key(String parentId, String position, List<String> tags, MCoreExpression vexp,
+				Object factory) {
+			this.parentId = parentId;
+			this.position = position;
+			this.vexp = vexp;
+			this.factory = factory;
+			if (tags.contains("scheme:menu")) { //$NON-NLS-1$
+				tag = 1;
+			} else if (tags.contains("scheme:popup")) { //$NON-NLS-1$
+				tag = 2;
+			} else if (tags.contains("scheme:toolbar")) { //$NON-NLS-1$
+				tag = 3;
+			} else {
+				tag = 0;
+			}
+		}
+
+		int getSchemeTag() {
+			return tag;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (!(obj instanceof Key)) {
+				return false;
+			}
+			Key other = (Key) obj;
+			Object exp1 = vexp == null ? null : vexp.getCoreExpression();
+			Object exp2 = other.vexp == null ? null : other.vexp.getCoreExpression();
+			return Util.equals(parentId, other.parentId) && Util.equals(position, other.position)
+					&& getSchemeTag() == other.getSchemeTag() && Util.equals(exp1, exp2)
+					&& Util.equals(factory, other.factory);
+		}
+
+		@Override
+		public int hashCode() {
+			if (hc == -1) {
+				Object exp1 = vexp == null ? null : vexp.getCoreExpression();
+				hc = Util.hashCode(parentId);
+				hc = hc * 87 + Util.hashCode(position);
+				hc = hc * 87 + getSchemeTag();
+				hc = hc * 87 + Util.hashCode(exp1);
+				hc = hc * 87 + Util.hashCode(factory);
+			}
+			return hc;
+		}
+
+		@Override
+		public String toString() {
+			return getClass().getName() + " " + parentId + "--" + position //$NON-NLS-1$ //$NON-NLS-2$
+					+ "--" + getSchemeTag() + "--" + vexp; //$NON-NLS-1$//$NON-NLS-2$
+		}
+	}
+
+	static class MenuKey extends Key {
+		static final String FACTORY = "ContributionFactory"; //$NON-NLS-1$
+		private MMenuContribution contribution;
+
+		public MenuKey(MMenuContribution mc) {
+			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
+					.getVisibleWhen(), mc.getTransientData().get(FACTORY));
+			this.contribution = mc;
+			mc.setWidget(this);
+		}
+
+		public MMenuContribution getContribution() {
+			return contribution;
+		}
+	}
+
+	static class ToolBarKey extends Key {
+		static final String FACTORY = "ToolBarContributionFactory"; //$NON-NLS-1$
+		private MToolBarContribution contribution;
+
+		public ToolBarKey(MToolBarContribution mc) {
+			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
+					.getVisibleWhen(), mc.getTransientData().get(FACTORY));
+			this.contribution = mc;
+			mc.setWidget(this);
+		}
+
+		public MToolBarContribution getContribution() {
+			return contribution;
+		}
+	}
+
+	static class TrimKey extends Key {
+		private MTrimContribution contribution;
+
+		public TrimKey(MTrimContribution mc) {
+			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
+					.getVisibleWhen(), null);
+			this.contribution = mc;
+			mc.setWidget(this);
+		}
+
+		public MTrimContribution getContribution() {
+			return contribution;
+		}
+	}
+
+	private static MenuKey getKey(MMenuContribution contribution) {
+		if (contribution.getWidget() instanceof MenuKey) {
+			return (MenuKey) contribution.getWidget();
+		}
+		return new MenuKey(contribution);
+	}
+
+	private static ToolBarKey getKey(MToolBarContribution contribution) {
+		if (contribution.getWidget() instanceof ToolBarKey) {
+			return (ToolBarKey) contribution.getWidget();
+		}
+		return new ToolBarKey(contribution);
+	}
+
+	private static TrimKey getKey(MTrimContribution contribution) {
+		if (contribution.getWidget() instanceof TrimKey) {
+			return (TrimKey) contribution.getWidget();
+		}
+		return new TrimKey(contribution);
+	}
+
+	public static void printContributions(ArrayList<MMenuContribution> contributions) {
+		for (MMenuContribution c : contributions) {
+			trace("\n" + c, null); //$NON-NLS-1$
+			for (MMenuElement element : c.getChildren()) {
+				printElement(1, element);
+			}
+		}
+	}
+
+	private static void printElement(int level, MMenuElement element) {
+		StringBuilder buf = new StringBuilder();
+		for (int i = 0; i < level; i++) {
+			buf.append('\t');
+		}
+		buf.append(element.toString());
+		trace(buf.toString(), null);
+		if (element instanceof MMenu) {
+			for (MMenuElement item : ((MMenu) element).getChildren()) {
+				printElement(level + 1, item);
+			}
+		}
+	}
+
+	public static void mergeToolBarContributions(ArrayList<MToolBarContribution> contributions,
+			ArrayList<MToolBarContribution> result) {
+		HashMap<ToolBarKey, ArrayList<MToolBarContribution>> buckets = new HashMap<ToolBarKey, ArrayList<MToolBarContribution>>();
+		trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
+		// first pass, sort by parentId?position,scheme,visibleWhen
+		for (MToolBarContribution contribution : contributions) {
+			ToolBarKey key = getKey(contribution);
+			ArrayList<MToolBarContribution> slot = buckets.get(key);
+			if (slot == null) {
+				slot = new ArrayList<MToolBarContribution>();
+				buckets.put(key, slot);
+			}
+			slot.add(contribution);
+		}
+		Iterator<MToolBarContribution> i = contributions.iterator();
+		while (i.hasNext() && !buckets.isEmpty()) {
+			MToolBarContribution contribution = i.next();
+			ToolBarKey key = getKey(contribution);
+			ArrayList<MToolBarContribution> slot = buckets.remove(key);
+			if (slot == null) {
+				continue;
+			}
+			MToolBarContribution toContribute = null;
+			for (MToolBarContribution item : slot) {
+				if (toContribute == null) {
+					toContribute = item;
+					continue;
+				}
+				Object[] array = item.getChildren().toArray();
+				for (int c = 0; c < array.length; c++) {
+					MToolBarElement me = (MToolBarElement) array[c];
+					if (!containsMatching(toContribute.getChildren(), me)) {
+						toContribute.getChildren().add(me);
+					}
+				}
+			}
+			if (toContribute != null) {
+				toContribute.setWidget(null);
+				result.add(toContribute);
+			}
+		}
+		trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
+	}
+
+	public static void mergeContributions(ArrayList<MMenuContribution> contributions,
+			ArrayList<MMenuContribution> result) {
+		HashMap<MenuKey, ArrayList<MMenuContribution>> buckets = new HashMap<MenuKey, ArrayList<MMenuContribution>>();
+		trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
+		printContributions(contributions);
+		// first pass, sort by parentId?position,scheme,visibleWhen
+		for (MMenuContribution contribution : contributions) {
+			MenuKey key = getKey(contribution);
+			ArrayList<MMenuContribution> slot = buckets.get(key);
+			if (slot == null) {
+				slot = new ArrayList<MMenuContribution>();
+				buckets.put(key, slot);
+			}
+			slot.add(contribution);
+		}
+		Iterator<MMenuContribution> i = contributions.iterator();
+		while (i.hasNext() && !buckets.isEmpty()) {
+			MMenuContribution contribution = i.next();
+			MenuKey key = getKey(contribution);
+			ArrayList<MMenuContribution> slot = buckets.remove(key);
+			if (slot == null) {
+				continue;
+			}
+			MMenuContribution toContribute = null;
+			for (MMenuContribution item : slot) {
+				if (toContribute == null) {
+					toContribute = item;
+					continue;
+				}
+				Object[] array = item.getChildren().toArray();
+				int idx = getIndex(toContribute, item.getPositionInParent());
+				if (idx == -1) {
+					idx = 0;
+				}
+				for (int c = 0; c < array.length; c++) {
+					MMenuElement me = (MMenuElement) array[c];
+					if (!containsMatching(toContribute.getChildren(), me)) {
+						toContribute.getChildren().add(idx, me);
+						idx++;
+					}
+				}
+			}
+			if (toContribute != null) {
+				toContribute.setWidget(null);
+				result.add(toContribute);
+			}
+		}
+		trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
+	}
+
+	private static boolean containsMatching(List<MMenuElement> children, MMenuElement me) {
+		for (MMenuElement element : children) {
+			if (Util.equals(me.getElementId(), element.getElementId())
+					&& element.getClass().isInstance(me)
+					&& (element instanceof MMenuSeparator || element instanceof MMenu)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private static boolean containsMatching(List<MToolBarElement> children, MToolBarElement me) {
+		for (MToolBarElement element : children) {
+			if (Util.equals(me.getElementId(), element.getElementId())
+					&& element.getClass().isInstance(me)
+					&& (element instanceof MToolBarSeparator || element instanceof MToolBar)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private static boolean containsMatching(List<MTrimElement> children, MTrimElement me) {
+		for (MTrimElement element : children) {
+			if (Util.equals(me.getElementId(), element.getElementId())
+					&& element.getClass().isInstance(me)
+					&& (element instanceof MToolBarSeparator || element instanceof MToolBar)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public static int indexForId(MElementContainer<MMenuElement> parentMenu, String id) {
+		if (id == null || id.length() == 0) {
+			return -1;
+		}
+		int i = 0;
+		for (MMenuElement item : parentMenu.getChildren()) {
+			if (id.equals(item.getElementId())) {
+				return i;
+			}
+			i++;
+		}
+		return -1;
+	}
+
+	public static final String MC_POPUP = "menuContribution:popup"; //$NON-NLS-1$
+	public static final String MC_MENU = "menuContribution:menu"; //$NON-NLS-1$
+	public static final String MC_TOOLBAR = "menuContribution:toolbar"; //$NON-NLS-1$
+	public static final String POPUP_PARENT_ID = "popup"; //$NON-NLS-1$
+
+	public static void mergeTrimContributions(ArrayList<MTrimContribution> contributions,
+			ArrayList<MTrimContribution> result) {
+		HashMap<TrimKey, ArrayList<MTrimContribution>> buckets = new HashMap<TrimKey, ArrayList<MTrimContribution>>();
+		trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
+		// first pass, sort by parentId?position,scheme,visibleWhen
+		for (MTrimContribution contribution : contributions) {
+			TrimKey key = getKey(contribution);
+			ArrayList<MTrimContribution> slot = buckets.get(key);
+			if (slot == null) {
+				slot = new ArrayList<MTrimContribution>();
+				buckets.put(key, slot);
+			}
+			slot.add(contribution);
+		}
+		Iterator<MTrimContribution> i = contributions.iterator();
+		while (i.hasNext() && !buckets.isEmpty()) {
+			MTrimContribution contribution = i.next();
+			TrimKey key = getKey(contribution);
+			ArrayList<MTrimContribution> slot = buckets.remove(key);
+			if (slot == null) {
+				continue;
+			}
+			MTrimContribution toContribute = null;
+			for (MTrimContribution item : slot) {
+				if (toContribute == null) {
+					toContribute = item;
+					continue;
+				}
+				Object[] array = item.getChildren().toArray();
+				for (int c = 0; c < array.length; c++) {
+					MTrimElement me = (MTrimElement) array[c];
+					if (!containsMatching(toContribute.getChildren(), me)) {
+						toContribute.getChildren().add(me);
+					}
+				}
+			}
+			if (toContribute != null) {
+				toContribute.setWidget(null);
+				result.add(toContribute);
+			}
+		}
+		trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
+	}
+
+	public static void populateModelInterfaces(Object modelObject, IEclipseContext context,
+			Class<?>[] interfaces) {
+		for (Class<?> intf : interfaces) {
+			Activator.trace(Policy.DEBUG_CONTEXTS, "Adding " + intf.getName() + " for " //$NON-NLS-1$ //$NON-NLS-2$
+					+ modelObject.getClass().getName(), null);
+			context.set(intf.getName(), modelObject);
+
+			populateModelInterfaces(modelObject, context, intf.getInterfaces());
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/DefaultLoggerProvider.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/DefaultLoggerProvider.java
new file mode 100644
index 0000000..c36d709
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/DefaultLoggerProvider.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.log.ILoggerProvider;
+import org.eclipse.e4.core.services.log.Logger;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ *
+ */
+public class DefaultLoggerProvider implements ILoggerProvider {
+	@Inject
+	private IEclipseContext context;
+
+	@Override
+	public Logger getClassLogger(Class<?> clazz) {
+		IEclipseContext childContext = context.createChild();
+		childContext.set("logger.bundlename", FrameworkUtil.getBundle(clazz).getSymbolicName()); //$NON-NLS-1$
+		return ContextInjectionFactory.make(WorkbenchLogger.class, childContext);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4Workbench.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4Workbench.java
new file mode 100644
index 0000000..0f8995a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4Workbench.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2014 BestSolution.at 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:
+ *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     IBM Corporation - initial API and implementation
+ *     Christian Georgi (SAP)                   - Bug 432480
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.UUID;
+import org.eclipse.e4.core.commands.ExpressionContext;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Default implementation of {@link IWorkbench}
+ */
+public class E4Workbench implements IWorkbench {
+	/**
+	 * The argument for the locale active shell <br>
+	 * <br>
+	 * Value is: <code>localActiveShell</code>
+	 */
+	public static final String LOCAL_ACTIVE_SHELL = "localActiveShell"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the initial workbench model <br>
+	 * <br>
+	 * Value is: <code>initialWorkbenchModelURI</code>
+	 */
+	public static final String INITIAL_WORKBENCH_MODEL_URI = "initialWorkbenchModelURI"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link Location} of the running instance <br>
+	 * <br>
+	 * Value is: <code>instanceLocation</code>
+	 */
+	public static final String INSTANCE_LOCATION = "instanceLocation"; //$NON-NLS-1$
+	/**
+	 * The argument for the renderer factory to use <br>
+	 * <br>
+	 * Value is: <code>rendererFactoryUri</code>
+	 */
+	public static final String RENDERER_FACTORY_URI = "rendererFactoryUri"; //$NON-NLS-1$
+	/**
+	 * The argument for setting the delta store location <br>
+	 * <br>
+	 * Value is: <code>deltaRestore</code>
+	 *
+	 * @deprecated
+	 */
+	@Deprecated
+	public static final String DELTA_RESTORE = "deltaRestore"; //$NON-NLS-1$
+	/**
+	 * The argument for setting RTL mode <br>
+	 * <br>
+	 * Value is: <code>dir</code>
+	 */
+	public static final String RTL_MODE = "dir"; //$NON-NLS-1$
+	/**
+	 * The argument for the perspective to activate <br>
+	 * <br>
+	 * Value is: <code>perspectiveId</code>
+	 */
+	public static final String FORCED_PERSPECTIVE_ID = "forcedPerspetiveId"; //$NON-NLS-1$
+
+	public static final String NO_SAVED_MODEL_FOUND = "NO_SAVED_MODEL_FOUND"; //$NON-NLS-1$
+	/**
+	 * The argument for the whether to forcefully show the location in the window title (set on the
+	 * command line)<br>
+	 * <br>
+	 * Value is: <code>forcedShowLocation</code>
+	 */
+	public static final String FORCED_SHOW_LOCATION = "forcedShowLocation"; //$NON-NLS-1$
+
+	private final String id;
+	private ServiceRegistration<?> osgiRegistration;
+
+	IEclipseContext appContext;
+	IPresentationEngine renderer;
+	MApplication appModel = null;
+	private UIEventPublisher uiEventPublisher;
+
+	private boolean restart;
+
+	/**
+	 * @return the {@link IEclipseContext} for the main application
+	 */
+	public IEclipseContext getContext() {
+		return appContext;
+	}
+
+	/**
+	 * Constructor
+	 *
+	 * @param uiRoot
+	 *            the root UI element
+	 * @param applicationContext
+	 *            the root context
+	 */
+	public E4Workbench(MApplicationElement uiRoot, IEclipseContext applicationContext) {
+		id = createId();
+		appContext = applicationContext;
+		appContext.set(IWorkbench.class.getName(), this);
+		if (uiRoot instanceof MApplication) {
+			appModel = (MApplication) uiRoot;
+		}
+
+		if (uiRoot instanceof MApplication) {
+			init((MApplication) uiRoot);
+		}
+
+		uiEventPublisher = new UIEventPublisher(appContext);
+		appContext.set(UIEventPublisher.class, uiEventPublisher);
+		((Notifier) uiRoot).eAdapters().add(uiEventPublisher);
+		Hashtable<String, Object> properties = new Hashtable<String, Object>();
+		properties.put("id", getId()); //$NON-NLS-1$
+
+		osgiRegistration = Activator.getDefault().getContext()
+				.registerService(IWorkbench.class.getName(), this, properties);
+	}
+
+	@Override
+	public final String getId() {
+		return id;
+	}
+
+	protected String createId() {
+		return UUID.randomUUID().toString();
+	}
+
+	/**
+	 * @param uiRoot
+	 */
+	public void createAndRunUI(MApplicationElement uiRoot) {
+		// Has someone already created one ?
+		instantiateRenderer();
+
+		if (renderer != null) {
+			renderer.run(uiRoot, appContext);
+		}
+	}
+
+	/**
+	 *
+	 */
+	public void instantiateRenderer() {
+		renderer = (IPresentationEngine) appContext.get(IPresentationEngine.class.getName());
+		if (renderer == null) {
+			String presentationURI = (String) appContext.get(IWorkbench.PRESENTATION_URI_ARG);
+			if (presentationURI != null) {
+				IContributionFactory factory = (IContributionFactory) appContext
+						.get(IContributionFactory.class.getName());
+				renderer = (IPresentationEngine) factory.create(presentationURI, appContext);
+				appContext.set(IPresentationEngine.class.getName(), renderer);
+			}
+			if (renderer == null) {
+				Logger logger = (Logger) appContext.get(Logger.class.getName());
+				logger.error("Failed to create the presentation engine for URI: " + presentationURI); //$NON-NLS-1$
+			}
+		}
+	}
+
+	private void init(MApplication appElement) {
+		Activator.trace(Policy.DEBUG_WORKBENCH, "init() workbench", null); //$NON-NLS-1$
+
+		IEclipseContext context = appElement.getContext();
+		if (context != null) {
+			context.set(ExpressionContext.ALLOW_ACTIVATION, Boolean.TRUE);
+		}
+	}
+
+	@Override
+	public boolean close() {
+		if (renderer != null) {
+			renderer.stop();
+		}
+		if (uiEventPublisher != null && appModel != null) {
+			((Notifier) appModel).eAdapters().remove(uiEventPublisher);
+			uiEventPublisher = null;
+		}
+		if (osgiRegistration != null) {
+			osgiRegistration.unregister();
+			osgiRegistration = null;
+		}
+		return true;
+	}
+
+	@Override
+	public boolean restart() {
+		this.restart = true;
+		return close();
+	}
+
+	/**
+	 * @return <code>true</code> when the workbench should be restarted
+	 */
+	public boolean isRestart() {
+		return restart;
+	}
+	// TODO: Remove in RAP
+	// /**
+	// * @return a context that can be used to lookup OSGi services
+	// */
+	// public static IEclipseContext getServiceContext() {
+	// return
+	// EclipseContextFactory.getServiceContext(Activator.getDefault().getContext());
+	// }
+
+	@Override
+	public MApplication getApplication() {
+		return appModel;
+	}
+
+	/**
+	 * Create the context chain. It both creates the chain for the current model, and adds eAdapters
+	 * so it can add new contexts when new model items are added.
+	 *
+	 * @param parentContext
+	 *            The parent context
+	 * @param contextModel
+	 *            needs a context created
+	 * @return a chained {@link IEclipseContext}
+	 */
+	public static IEclipseContext initializeContext(IEclipseContext parentContext,
+			MContext contextModel) {
+		final IEclipseContext context;
+		if (contextModel.getContext() != null) {
+			context = contextModel.getContext();
+		} else {
+			context = parentContext.createChild("PartContext(" + contextModel + ')'); //$NON-NLS-1$
+		}
+
+		Activator.trace(Policy.DEBUG_CONTEXTS, "initializeContext(" //$NON-NLS-1$
+				+ parentContext.toString() + ", " + contextModel + ")", null); //$NON-NLS-1$ //$NON-NLS-2$
+		// fill in the interfaces, so MContributedPart.class.getName() will
+		// return the model element, for example.
+		ContributionsAnalyzer.populateModelInterfaces(contextModel, context, contextModel
+				.getClass().getInterfaces());
+
+		// declares modifiable variables from the model
+		List<String> containedProperties = contextModel.getVariables();
+		for (String name : containedProperties) {
+			context.declareModifiable(name);
+		}
+
+		contextModel.setContext(context);
+		return context;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResource.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResource.java
new file mode 100644
index 0000000..8aee75c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResource.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.XMLHelper;
+import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
+
+public class E4XMIResource extends XMIResourceImpl {
+
+	private Map<EObject, String> objectMap = new WeakHashMap<EObject, String>();
+	private Set<String> knownIds = new HashSet<String>();
+
+	public E4XMIResource() {
+	}
+
+	public E4XMIResource(URI uri) {
+		super(uri);
+	}
+
+	public void setInternalId(EObject object, String id) {
+		objectMap.put(object, id);
+		knownIds.add(id);
+	}
+
+	public String getInternalId(EObject object) {
+		return objectMap.get(object);
+	}
+
+	@Override
+	protected boolean useIDs() {
+		return true;
+	}
+
+	private String createId() {
+		return EcoreUtil.generateUUID();
+	}
+
+	private String getUniqueId() {
+		String id = createId();
+		while (knownIds.contains(id)) {
+			id = createId();
+		}
+		return id;
+	}
+
+	@Override
+	public void setID(EObject eObject, String id) {
+		if (id != null) {
+			String internalId = objectMap.get(eObject);
+			if (internalId != null) {
+				super.setID(eObject, internalId);
+			}
+			objectMap.put(eObject, id);
+			knownIds.add(id);
+		}
+		super.setID(eObject, id);
+	}
+
+	@Override
+	public String getID(EObject eObject) {
+		if (eObject instanceof Entry<?, ?>) {
+			return null;
+		}
+
+		String id = super.getID(eObject);
+		if (id != null) {
+			return id;
+		}
+
+		id = objectMap.get(eObject);
+		if (id != null) {
+			return id;
+		}
+
+		id = getUniqueId();
+		setID(eObject, id);
+		return id;
+	}
+
+	/**
+	 * Functional interface for creating objects
+	 */
+	private interface ObjectCreator {
+		MApplicationElement create();
+	}
+
+	static final Map<String, ObjectCreator> deprecatedTypeMappings = new HashMap<String, ObjectCreator>();
+	static {
+		deprecatedTypeMappings.put("OpaqueMenu", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return OpaqueElementUtil.createOpaqueMenu();
+					}
+				});
+		deprecatedTypeMappings.put("OpaqueMenuItem", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return OpaqueElementUtil.createOpaqueMenuItem();
+					}
+				});
+		deprecatedTypeMappings.put("OpaqueMenuSeparator", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return OpaqueElementUtil.createOpaqueMenuSeparator();
+					}
+				});
+		deprecatedTypeMappings.put("OpaqueToolItem", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return OpaqueElementUtil.createOpaqueToolItem();
+					}
+				});
+		deprecatedTypeMappings.put("RenderedMenu", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return RenderedElementUtil.createRenderedMenu();
+					}
+				});
+		deprecatedTypeMappings.put("RenderedMenuItem", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return RenderedElementUtil.createRenderedMenuItem();
+					}
+				});
+		deprecatedTypeMappings.put("RenderedToolBar", new ObjectCreator() { //$NON-NLS-1$
+
+					@Override
+					public MApplicationElement create() {
+						return RenderedElementUtil.createRenderedToolBar();
+					}
+				});
+	}
+
+	@Override
+	protected XMLHelper createXMLHelper() {
+		// Handle mapping of deprecated types
+		return new XMIHelperImpl(this) {
+
+			@Override
+			public EObject createObject(EFactory eFactory, EClassifier type) {
+				if (MMenuFactory.INSTANCE == eFactory && type != null && type.getName() != null) {
+					final ObjectCreator objectCreator = deprecatedTypeMappings.get(type.getName());
+					if (objectCreator != null) {
+						return (EObject) objectCreator.create();
+					}
+				}
+				return super.createObject(eFactory, type);
+			}
+
+			@Override
+			public EClassifier getType(EFactory eFactory, String typeName) {
+				if (deprecatedTypeMappings.containsKey(typeName)) {
+					// need a temp instance of the now removed EClass so that
+					// createObject, above, can do it's work.
+					final EClass tempEClass = EcoreFactory.eINSTANCE.createEClass();
+					tempEClass.setName(typeName);
+					return tempEClass;
+				}
+				return super.getType(eFactory, typeName);
+			}
+
+		};
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResourceFactory.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResourceFactory.java
new file mode 100644
index 0000000..e46a5df
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/E4XMIResourceFactory.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.List;
+import java.util.Map;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.XMLParserPool;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
+
+/**
+ * Resource factory for {@link E4XMIResource}.
+ */
+public class E4XMIResourceFactory extends XMIResourceFactoryImpl {
+
+	/**
+	 * List used for EMF {@link XMLResource#OPTION_USE_CACHED_LOOKUP_TABLE} option value. Packaged
+	 * in a ThreadLocal per EMF recommendation for thread safety.
+	 */
+	private final ThreadLocal<List<Object>> lookupTable = new ThreadLocal<List<Object>>();
+	/**
+	 * Parser pool object for {@link XMLResource#OPTION_USE_PARSER_POOL} option. Also needed for
+	 * setting {@link XMLResource#OPTION_USE_DEPRECATED_METHODS} for false.
+	 */
+	private final XMLParserPool parserPool = new XMLParserPoolImpl();
+	/**
+	 * Map used for {@link XMLResource#OPTION_USE_XML_NAME_TO_FEATURE_MAP}. Per EMF documentation,
+	 * the map is hosted within a ThreadLocale for thread safety.
+	 */
+	private final ThreadLocal<Map<Object, Object>> nameToFeatureMap = new ThreadLocal<Map<Object, Object>>();
+
+	@Override
+	public Resource createResource(URI uri) {
+		final E4XMIResource resource = new E4XMIResource(uri);
+
+		// configure default save/load options, as suggested by
+		// EMF: Eclipse Modeling Framework, Second Edition
+		// Section 15.5.1
+		final Map<Object, Object> saveOptions = resource.getDefaultSaveOptions();
+		saveOptions.put(XMLResource.OPTION_CONFIGURATION_CACHE, Boolean.TRUE);
+		saveOptions.put(XMLResource.OPTION_USE_CACHED_LOOKUP_TABLE, lookupTable.get());
+
+		final Map<Object, Object> loadOptions = resource.getDefaultLoadOptions();
+		loadOptions.put(XMLResource.OPTION_DEFER_ATTACHMENT, Boolean.TRUE);
+		loadOptions.put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);
+		loadOptions.put(XMLResource.OPTION_USE_PARSER_POOL, parserPool);
+		loadOptions.put(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP, nameToFeatureMap.get());
+		loadOptions.put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.FALSE);
+		return resource;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaEntrySet.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaEntrySet.java
new file mode 100644
index 0000000..5b6d1bf
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaEntrySet.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public class EMFDeltaEntrySet extends ModelDelta {
+
+	protected EStructuralFeature feature;
+	protected String key;
+	protected String value;
+
+	public EMFDeltaEntrySet(EObject object, EStructuralFeature feature, String key, String value) {
+		super(object, feature.getName(), null);
+		this.feature = feature;
+		this.key = key;
+		this.value = value;
+	}
+
+	@Override
+	public IStatus apply() {
+		@SuppressWarnings("unchecked")
+		EMap<String, String> map = (EMap<String, String>) ((EObject) getObject()).eGet(feature);
+		map.put(key, value);
+		return Status.OK_STATUS;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaMapSet.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaMapSet.java
new file mode 100644
index 0000000..14c691e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFDeltaMapSet.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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.internal.workbench;
+
+import java.util.Map;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+class EMFDeltaMapSet extends ModelDelta {
+
+	private EStructuralFeature feature;
+	private Map<String, String> deltaMap;
+
+	EMFDeltaMapSet(EObject object, EStructuralFeature feature, Map<String, String> deltaMap) {
+		super(object, feature.getName(), null);
+		this.feature = feature;
+		this.deltaMap = deltaMap;
+	}
+
+	@Override
+	public IStatus apply() {
+		@SuppressWarnings("unchecked")
+		EMap<String, String> map = (EMap<String, String>) ((EObject) getObject()).eGet(feature);
+		map.clear();
+		map.putAll(deltaMap);
+		return Status.OK_STATUS;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaDelayedSet.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaDelayedSet.java
new file mode 100644
index 0000000..d2b06a3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaDelayedSet.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.List;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public class EMFModelDeltaDelayedSet extends EMFModelDeltaSet {
+
+	private Object root;
+	private String id;
+
+	private Object value;
+
+	public EMFModelDeltaDelayedSet(Object object, EStructuralFeature feature, Object root, String id) {
+		super(object, feature, null);
+		this.root = root;
+		this.id = id;
+	}
+
+	@Override
+	public Object getAttributeValue() {
+		return value;
+	}
+
+	@Override
+	public IStatus apply() {
+		List<Object> references = XMLModelReconciler.getReferences(root);
+		value = XMLModelReconciler.findReference(references, id);
+		if (value == null) {
+			return Status.CANCEL_STATUS;
+		}
+		return super.apply();
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaSet.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaSet.java
new file mode 100644
index 0000000..236cc11
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaSet.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public class EMFModelDeltaSet extends ModelDelta {
+
+	private final EStructuralFeature feature;
+
+	public EMFModelDeltaSet(Object object, EStructuralFeature feature, Object value) {
+		super(object, feature.getName(), value);
+		this.feature = feature;
+	}
+
+	@Override
+	public IStatus apply() {
+		EObject eObject = (EObject) getObject();
+		eObject.eSet(feature, getAttributeValue());
+		return Status.OK_STATUS;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaThreeWayDelayedSet.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaThreeWayDelayedSet.java
new file mode 100644
index 0000000..a92f8c4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaThreeWayDelayedSet.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.List;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public final class EMFModelDeltaThreeWayDelayedSet extends EMFModelDeltaSet {
+
+	private List<?> originalReferences;
+	private List<?> userReferences;
+	private List<?> currentReferences;
+
+	public EMFModelDeltaThreeWayDelayedSet(Object object, EStructuralFeature feature,
+			List<?> originalReferences, List<?> userReferences, List<?> currentReferences) {
+		super(object, feature, null);
+		this.originalReferences = originalReferences;
+		this.userReferences = userReferences;
+		this.currentReferences = currentReferences;
+	}
+
+	@Override
+	public Object getAttributeValue() {
+		userReferences = (List<?>) convert(userReferences);
+		return XMLModelReconciler.threeWayMerge(originalReferences, userReferences,
+				currentReferences);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaUnset.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaUnset.java
new file mode 100644
index 0000000..604e9a9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/EMFModelDeltaUnset.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public final class EMFModelDeltaUnset extends ModelDelta {
+
+	private final EStructuralFeature feature;
+
+	public EMFModelDeltaUnset(EObject eObject, EStructuralFeature feature) {
+		super(eObject, feature.getName(), null);
+		this.feature = feature;
+	}
+
+	@Override
+	public IStatus apply() {
+		EObject eObject = (EObject) getObject();
+		eObject.eUnset(feature);
+		return Status.OK_STATUS;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExceptionHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExceptionHandler.java
new file mode 100644
index 0000000..706dce6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExceptionHandler.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.e4.ui.workbench.IExceptionHandler;
+
+public class ExceptionHandler implements IExceptionHandler {
+
+	@Override
+	public void handleException(Throwable e) {
+		e.printStackTrace();
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionPointProxy.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionPointProxy.java
new file mode 100644
index 0000000..e3d3912
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionPointProxy.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import java.lang.reflect.Field;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+
+public class ExtensionPointProxy {
+
+	private IConfigurationElement element;
+	private String propertyName;
+	private IDelegateInitializer delegateInitializer;
+
+	private boolean failed = false;
+	private Object delegate;
+
+	public ExtensionPointProxy(IConfigurationElement element, String propertyName) {
+		this(element, propertyName, null);
+	}
+
+	public ExtensionPointProxy(IConfigurationElement element, String propertyName,
+			IDelegateInitializer delegateInitializer) {
+		this.element = element;
+		this.propertyName = propertyName;
+		this.delegateInitializer = delegateInitializer;
+	}
+
+	public Object getDelegate() {
+		return delegate;
+	}
+
+	public Object createDelegate(MApplicationElement model) {
+		if (delegate == null && !failed) {
+			try {
+				delegate = element.createExecutableExtension(propertyName);
+				if (delegateInitializer != null) {
+					delegateInitializer.initialize(model, delegate);
+				}
+			} catch (CoreException e) {
+				failed = true;
+			}
+		}
+		return delegate;
+	}
+
+	public boolean setField(String name, Object value) {
+		if (delegate != null) {
+			Field field = getField(delegate.getClass(), name);
+			if (field != null) {
+				boolean accessible = field.isAccessible();
+				try {
+					field.setAccessible(true);
+					field.set(delegate, value);
+					return true;
+				} catch (IllegalAccessException e) {
+					return false;
+				} finally {
+					field.setAccessible(accessible);
+				}
+			}
+		}
+		return false;
+	}
+
+	private Field getField(Class<?> cls, String name) {
+		try {
+			return cls.getDeclaredField(name);
+		} catch (SecurityException e) {
+			return null;
+		} catch (NoSuchFieldException e) {
+			return getField(cls.getSuperclass(), name);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionsSort.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionsSort.java
new file mode 100644
index 0000000..73499a4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ExtensionsSort.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Manumitting Technologies Inc 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:
+ *     Brian de Alwis (MTI) - initial API and implementation
+ *     René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.eclipse.core.runtime.IContributor;
+import org.eclipse.core.runtime.IExtension;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+/**
+ * Sort {@link IExtension}s by their plug-in dependencies such that any extension from bundle A
+ * should be sorted before any extensions from any bundles that depend on A.
+ * <p>
+ * Consider having extensions from bundles A, B, and C, where A depends on B, and B depends on C.
+ * The result of this sort should be the extensions from C, then from B, and finally from A.
+ */
+public class ExtensionsSort extends TopologicalSort<IExtension, Bundle> {
+
+	@Override
+	protected Bundle getId(IExtension extension) {
+		IContributor contributor = extension.getContributor();
+		return Activator.getDefault().getBundleForName(contributor.getName());
+	}
+
+	/**
+	 * Returns the bundles that the given bundle requires.
+	 *
+	 * @return An unmodifiable {@link Iterable} set of bundles currently required by the geiven
+	 *         bundle. An empty {@link Iterable} will be returned if the given {@code Bundle} object
+	 *         has become stale or there are no bundles required.
+	 * @throws NullPointerException
+	 *             if {@code bundle} is <code>null</code>
+	 */
+	@Override
+	protected Collection<Bundle> getRequirements(Bundle bundle) {
+		// punt to getDependents()
+		return null;
+	}
+
+	/**
+	 * Recursively collects all bundles which depend-on/require the given {@link BundleWiring}.
+	 * <p>
+	 * All re-exports will be followed and also be contained in the result.
+	 * </p>
+	 *
+	 * @param dependents
+	 *            the result which will contain all the bundles which require the given
+	 *            {@link BundleWiring}
+	 * @param providerWiring
+	 *            the {@link BundleWiring} for which the requirers should be resolved
+	 * @throws NullPointerException
+	 *             if either the requiring or the providerWiring is <code>null</code>
+	 */
+	private static void addDependents(Set<Bundle> dependents, BundleWiring providerWiring) {
+		List<BundleWire> requirerWires = providerWiring
+				.getProvidedWires(BundleNamespace.BUNDLE_NAMESPACE);
+		if (requirerWires == null) {
+			// we don't hold locks while checking the graph, just return if no longer isInUse
+			return;
+		}
+		for (BundleWire requireBundleWire : requirerWires) {
+			Bundle requirer = requireBundleWire.getRequirer().getBundle();
+			if (dependents.contains(requirer)) {
+				continue;
+			}
+			dependents.add(requirer);
+			String reExport = requireBundleWire.getRequirement().getDirectives()
+					.get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+			if (BundleNamespace.VISIBILITY_REEXPORT.equals(reExport)) {
+				addDependents(dependents, requireBundleWire.getRequirerWiring());
+			}
+		}
+	}
+
+	/**
+	 * Returns the bundles that currently require the given bundle.
+	 * <p>
+	 * If {@code bundle} is required and then re-exported by another bundle then all the requiring
+	 * bundles of the re-exporting bundle are included in the returned array as they transitively
+	 * depend on {@code bundle}.
+	 * </p>
+	 *
+	 * @return An unmodifiable {@link Iterable} set of bundles currently requiring {@code bundle}.
+	 *         An empty {@link Iterable} will be returned if the {@code bundle} has become stale or
+	 *         has no dependents.
+	 * @throws NullPointerException
+	 *             if {@code bundle} is <code>null</code>
+	 */
+	@Override
+	protected Collection<Bundle> getDependencies(Bundle bundle) {
+		BundleWiring providerWiring = bundle.adapt(BundleWiring.class);
+		if (!providerWiring.isInUse()) {
+			return Collections.emptySet();
+		}
+
+		Set<Bundle> required = new HashSet<Bundle>();
+		addDependents(required, providerWiring);
+		return Collections.unmodifiableSet(required);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/GenericMApplicationElementFactoryImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/GenericMApplicationElementFactoryImpl.java
new file mode 100644
index 0000000..b72854c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/GenericMApplicationElementFactoryImpl.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IRegistryEventListener;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.osgi.service.log.LogService;
+
+/**
+ * A factory which is able to build the EMF based EObjects for the given {@link MApplicationElement}
+ * class.
+ *
+ * <p>
+ * This factory checks the Eclipse ExtensionRegistry for all registered EMF-packages, via the
+ * {@code "org.eclipse.emf.ecore.generated_package"} ExtensionPoint generated by EMF. It uses the
+ * EPackage Namespace URI mentioned in this ExtensionPoint to build a mapping between normal java
+ * class and the corresponding {@link EClass}.
+ * </p>
+ *
+ * <p>
+ * <b>Important:</b> The mapping will only contain {@link EClass}es which extend the
+ * {@link MApplicationElement} and are neither abstract nor an interface.
+ * </p>
+ */
+final class GenericMApplicationElementFactoryImpl {
+
+	/**
+	 * An ExtensionRegistryListener which will build the required {@link Class} to {@link EClass}
+	 * mapping.
+	 */
+	private final MApplicationElementClassToEClass emfGeneratedPackages;
+
+	/**
+	 * Sole constructor.
+	 *
+	 * @param extensionRegistry
+	 *            the Eclipse ExtensionRegistry
+	 * @throws NullPointerException
+	 *             if the given Eclipse ExtensionRegistry is {@code null}
+	 */
+	GenericMApplicationElementFactoryImpl(IExtensionRegistry extensionRegistry) {
+		if (extensionRegistry == null)
+			throw new NullPointerException("No ExtensionRegistry given!"); //$NON-NLS-1$
+
+		emfGeneratedPackages = new MApplicationElementClassToEClass();
+
+		// A clean-up would be nice but the only using service is realized as a singleton-service
+		// which is used throughout the running application and so this instance will also life as
+		// long as the application is running.
+		extensionRegistry.addListener(emfGeneratedPackages,
+				MApplicationElementClassToEClass.EP_MODEL_DEFINITION_ENRICHMENT);
+		emfGeneratedPackages.initialize(extensionRegistry);
+	}
+
+	/**
+	 * Takes the given class and creates the corresponding {@link EObject} implementation for it.
+	 *
+	 * @param clazz
+	 *            the class for which the corresponding {@link EObject} should be created
+	 * @return the corresponding {@link EObject} or {@code null} if it wasn't able to create one
+	 *         (e.g.: no {@link EClass} maps to the given {@link Class})
+	 */
+	public EObject createEObject(Class<? extends MApplicationElement> clazz) {
+		EClass eClass = emfGeneratedPackages.getEClass(clazz);
+		if (eClass != null) {
+			return EcoreUtil.create(eClass);
+		}
+
+		return null;
+	}
+
+	/**
+	 * An Eclipse ExtensionRegistry-Listener which will build the required map to find the
+	 * {@link EClass} for the given {@link Class}.
+	 *
+	 * <p>
+	 * This Listener must be registered on EMF's {@value #EP_MODEL_DEFINITION_ENRICHMENT} extension
+	 * point to build the appropriate mapping between {@link Class} and {@link EClass}.
+	 * </p>
+	 *
+	 * <p>
+	 * <b>Info:</b> This map will only contain concrete {@link EClass} objects which extend the
+	 * {@link MApplicationElement}.
+	 * </p>
+	 */
+	private static final class MApplicationElementClassToEClass implements IRegistryEventListener {
+
+		/** The extension point name which holds the required information. */
+		public static final String EP_MODEL_DEFINITION_ENRICHMENT = "org.eclipse.e4.workbench.model.definition.enrichment"; //$NON-NLS-1$
+
+		/**
+		 * The configuration element inside the extension point which holds the required
+		 * information.
+		 */
+		private static final String CONFIG_ELEMENT_NAME = "definitionEnrichment"; //$NON-NLS-1$
+
+		/** Attribute name which holds the EMF EPackage Namespace URI. */
+		private static final String CONFIG_ATTR_EPACKAGE_URI = "ePackageNS"; //$NON-NLS-1$
+
+		/** Holds the mapping between {@link Class} and {@link EClass}. */
+		private final ConcurrentMap<Class<? extends MApplicationElement>, EClass> classToEClass = new ConcurrentHashMap<Class<? extends MApplicationElement>, EClass>();
+
+		/**
+		 * Holds the required information per extension point which needs to be clean-up in the
+		 * {@link #removed(IExtension[])} method.
+		 */
+		private final ConcurrentMap<IExtension, List<Class<? extends MApplicationElement>>> registeredClasses = new ConcurrentHashMap<IExtension, List<Class<? extends MApplicationElement>>>();
+
+		/** A reference to the {@link MApplicationElement}-EClass. */
+		private final EClass mApplicationElementEClass = ApplicationPackageImpl.eINSTANCE
+				.getApplicationElement();
+
+		/**
+		 * Method which will initialize the mapping with the information from the given Eclipse
+		 * ExtensionRegistry.
+		 *
+		 * <p>
+		 * The method will retrieve all {@link #EP_MODEL_DEFINITION_ENRICHMENT} extensions form the
+		 * given Eclipse ExtensionRegistry and initializes the basic mapping.
+		 * </p>
+		 *
+		 * @param extensionRegistry
+		 *            the Eclipse ExtensionRegistry on which the listener is already registered
+		 */
+		void initialize(IExtensionRegistry extensionRegistry) {
+			if (extensionRegistry == null) { // just for safety's sake
+				throw new IllegalArgumentException("No ExtensionRegistry given!"); //$NON-NLS-1$
+			}
+
+			IExtensionPoint epGeneratedPackage = extensionRegistry
+					.getExtensionPoint(EP_MODEL_DEFINITION_ENRICHMENT);
+			if (epGeneratedPackage != null) {
+				added(epGeneratedPackage.getExtensions());
+			}
+		}
+
+		/**
+		 * Lookup the {@link EClass} for the given {@link Class}.
+		 *
+		 * @param elementType
+		 *            the {@link Class} to which the {@link EClass} should be found
+		 * @return the corresponding {@link EClass} or {@code null} if none was found
+		 */
+		public EClass getEClass(Class<? extends MApplicationElement> elementType) {
+			return classToEClass.get(elementType);
+		}
+
+		@Override
+		public void added(IExtension[] extensions) {
+			for (IExtension extension : extensions) {
+				List<Class<? extends MApplicationElement>> elementsToCleanup = addToMapping(extension
+						.getConfigurationElements());
+
+				if (elementsToCleanup != null) {
+					// keep the list of registered class per extension to remove them in the
+					// #remove(IExtension[]) method
+					registeredClasses.put(extension, elementsToCleanup);
+				}
+			}
+		}
+
+		@Override
+		public void removed(IExtension[] extensions) {
+			for (IExtension extension : extensions) {
+				List<Class<? extends MApplicationElement>> modelClassesToRemove = registeredClasses
+						.remove(extension);
+
+				if (modelClassesToRemove != null) {
+					// clean-up
+					for (Class<? extends MApplicationElement> modelClass : modelClassesToRemove) {
+						classToEClass.remove(modelClass);
+					}
+				}
+			}
+		}
+
+		@Override
+		public void added(IExtensionPoint[] extensionPoints) {
+			// not of interest
+		}
+
+		@Override
+		public void removed(IExtensionPoint[] extensionPoints) {
+			// not of interest
+		}
+
+		/**
+		 * Reads the information from the given {@link IConfigurationElement}s and updates the
+		 * mapping.
+		 *
+		 * @param configurationElements
+		 *            the elements to read the information from
+		 * @return the list of {@link Class}es which were put to the {@link #classToEClass} mapping
+		 *         or <code>null</code> if none were put into that list
+		 */
+		private List<Class<? extends MApplicationElement>> addToMapping(
+				IConfigurationElement[] configurationElements) {
+			if (configurationElements == null) {
+				return null;
+			}
+
+			List<Class<? extends MApplicationElement>> allMappedEntried = new ArrayList<Class<? extends MApplicationElement>>();
+
+			for (IConfigurationElement configElement : configurationElements) {
+				if (configElement.getName().equals(CONFIG_ELEMENT_NAME)) {
+					String emfNsURI = configElement.getAttribute(CONFIG_ATTR_EPACKAGE_URI);
+
+					// find EPackage
+					EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(emfNsURI);
+
+					// build Class to EClass mapping from the classes in the EPackage
+					Map<Class<? extends MApplicationElement>, EClass> mapping = buildMapping(ePackage);
+
+					if (mapping != null) {
+						for (Map.Entry<Class<? extends MApplicationElement>, EClass> entry : mapping
+								.entrySet()) {
+
+							// if the current thread added the mapping we keep the key so it can be
+							// removed afterwards in the #remove(IExtension[]) method
+							if (classToEClass.putIfAbsent(entry.getKey(), entry.getValue()) == null) {
+								allMappedEntried.add(entry.getKey());
+							}
+						}
+					}
+				}
+			}
+
+			// null means nothing from the given configurationElementes was added to the Class to
+			// EClass map
+			return allMappedEntried.isEmpty() ? null : allMappedEntried;
+		}
+
+		/**
+		 * Utility method which walks through all {@link EClass} of the given {@link EPackage} to
+		 * build a Class-To-EClass map.
+		 * <p>
+		 * This method will only take {@link EClass}es into account which extend the
+		 * {@link MApplicationElement} and are neither a abstract class nor an interface. Which
+		 * means the mapping will only contain {@link EModelService#createModelElement(Class)}
+		 * relevant classes.
+		 * </p>
+		 *
+		 * @param ePackage
+		 *            the EPackage to scan
+		 * @return a map containing all {@link Class}es and their corresponding {@link EClass} which
+		 *         are provided by the given {@link EPackage} and extend the
+		 *         {@link MApplicationElement}; {@code null} otherwise
+		 */
+		private final Map<Class<? extends MApplicationElement>, EClass> buildMapping(
+				EPackage ePackage) {
+			if (ePackage == null)
+				return null;
+
+			List<EClassifier> eClassifiers = ePackage.getEClassifiers();
+			Map<Class<? extends MApplicationElement>, EClass> mapping = new HashMap<Class<? extends MApplicationElement>, EClass>();
+
+			for (EClassifier eClassifier : eClassifiers) {
+				if (eClassifier instanceof EClass) {
+					EClass eClass = (EClass) eClassifier;
+
+					if (mApplicationElementEClass.isSuperTypeOf(eClass) && !eClass.isAbstract()
+							&& !eClass.isInterface()) {
+						@SuppressWarnings("unchecked")
+						Class<? extends MApplicationElement> instanceClass = (Class<? extends MApplicationElement>) eClass
+								.getInstanceClass();
+
+						// the Map.Entry check is just for safety, because of the EMF special for
+						// Key/Value pairs in HashMaps
+						// (see: UIElements.ecore/application/StringToStringMap)
+						if (!instanceClass.equals(Map.Entry.class)) {
+							// add the entry, but if there was already a mapping we should log it
+							EClass previousEntry = mapping.put(instanceClass, eClass);
+
+							if (previousEntry != null) {
+								Activator
+										.log(LogService.LOG_WARNING,
+												instanceClass
+														+ " is mapped to multiple EClasses (" + eClass.getName() + ", " + previousEntry.getName() + ")!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+							}
+						}
+					}
+
+				}
+			}
+
+			return mapping.isEmpty() ? null : mapping;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/IDelegateInitializer.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/IDelegateInitializer.java
new file mode 100644
index 0000000..3ff3a89
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/IDelegateInitializer.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+
+/**
+ *
+ */
+public interface IDelegateInitializer {
+
+	public void initialize(MApplicationElement model, Object delegate);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
new file mode 100644
index 0000000..8336fd5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 BestSolution.at 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:
+ *     Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
+ *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 430075, 430080, 431464, 433336
+ *     René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ *     Brian de Alwis (MTI) - Bug 433053
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IContributor;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.fragment.MModelFragment;
+import org.eclipse.e4.ui.model.fragment.MModelFragments;
+import org.eclipse.e4.ui.model.fragment.impl.FragmentPackageImpl;
+import org.eclipse.e4.ui.model.internal.ModelUtils;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EContentsEList;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+/**
+ *
+ */
+public class ModelAssembler {
+	@Inject
+	private Logger logger;
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	private IExtensionRegistry registry;
+
+	final private static String extensionPointID = "org.eclipse.e4.workbench.model"; //$NON-NLS-1$
+
+	//	private static final String ALWAYS = "always"; //$NON-NLS-1$
+	private static final String INITIAL = "initial"; //$NON-NLS-1$
+	private static final String NOTEXISTS = "notexists"; //$NON-NLS-1$
+
+	/**
+	 * Process the model
+	 */
+	public void processModel(boolean initial) {
+		IExtensionPoint extPoint = registry.getExtensionPoint(extensionPointID);
+		IExtension[] extensions = new ExtensionsSort().sort(extPoint.getExtensions());
+
+		List<MApplicationElement> imports = new ArrayList<MApplicationElement>();
+		List<MApplicationElement> addedElements = new ArrayList<MApplicationElement>();
+
+		// run processors which are marked to run before fragments
+		runProcessors(extensions, initial, false);
+		processFragments(extensions, imports, addedElements, initial);
+		// run processors which are marked to run after fragments
+		runProcessors(extensions, initial, true);
+
+		resolveImports(imports, addedElements);
+	}
+
+	/**
+	 * @param extensions
+	 * @param imports
+	 * @param addedElements
+	 */
+	private void processFragments(IExtension[] extensions, List<MApplicationElement> imports,
+			List<MApplicationElement> addedElements, boolean initial) {
+
+		for (IExtension extension : extensions) {
+			IConfigurationElement[] ces = extension.getConfigurationElements();
+			for (IConfigurationElement ce : ces) {
+				if ("fragment".equals(ce.getName())) { //$NON-NLS-1$
+					if (initial || !INITIAL.equals(ce.getAttribute("apply"))) { //$NON-NLS-1$
+						processFragment(ce, imports, addedElements, initial);
+					}
+				}
+			}
+		}
+	}
+
+	private void processFragment(IConfigurationElement ce, List<MApplicationElement> imports,
+			List<MApplicationElement> addedElements, boolean initial) {
+		E4XMIResource applicationResource = (E4XMIResource) ((EObject) application).eResource();
+		ResourceSet resourceSet = applicationResource.getResourceSet();
+		IContributor contributor = ce.getContributor();
+		String attrURI = ce.getAttribute("uri"); //$NON-NLS-1$
+		String bundleName = contributor.getName();
+		if (attrURI == null) {
+			logger.warn("Unable to find location for the model extension \"{0}\"", bundleName); //$NON-NLS-1$
+			return;
+		}
+
+		URI uri;
+		try {
+			// check if the attrURI is already a platform URI
+			if (URIHelper.isPlatformURI(attrURI)) {
+				uri = URI.createURI(attrURI);
+			} else {
+				String path = bundleName + '/' + attrURI;
+				uri = URI.createPlatformPluginURI(path, false);
+			}
+		} catch (RuntimeException e) {
+			logger.warn(e, "Invalid location \"" + attrURI + "\" of model extension \"" + bundleName + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return;
+		}
+
+		String contributorURI = URIHelper.constructPlatformURI(contributor);
+		Resource resource;
+		try {
+			resource = resourceSet.getResource(uri, true);
+		} catch (RuntimeException e) {
+			logger.warn(e, "Unable to read model extension from \"" + uri.toString() +"\" of \"" + bundleName + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return;
+		}
+
+		EList<?> contents = resource.getContents();
+		if (contents.isEmpty()) {
+			return;
+		}
+
+		Object extensionRoot = contents.get(0);
+
+		if (!(extensionRoot instanceof MModelFragments)) {
+			logger.warn("Unable to create model extension \"{0}\"", bundleName); //$NON-NLS-1$
+			return;
+		}
+		boolean checkExist = !initial && NOTEXISTS.equals(ce.getAttribute("apply")); //$NON-NLS-1$
+
+		MModelFragments fragmentsContainer = (MModelFragments) extensionRoot;
+		List<MModelFragment> fragments = fragmentsContainer.getFragments();
+		boolean evalImports = false;
+		for (MModelFragment fragment : fragments) {
+			List<MApplicationElement> elements = fragment.getElements();
+			if (elements.size() == 0) {
+				continue;
+			}
+
+			for (MApplicationElement el : elements) {
+				EObject o = (EObject) el;
+
+				E4XMIResource r = (E4XMIResource) o.eResource();
+
+				if (checkExist && applicationResource.getIDToEObjectMap().containsKey(r.getID(o))) {
+					continue;
+				}
+
+				applicationResource.setID(o, r.getID(o));
+
+				if (contributorURI != null)
+					el.setContributorURI(contributorURI);
+
+				// Remember IDs of subitems
+				TreeIterator<EObject> treeIt = EcoreUtil.getAllContents(o, true);
+				while (treeIt.hasNext()) {
+					EObject eObj = treeIt.next();
+					r = (E4XMIResource) eObj.eResource();
+					if (contributorURI != null && (eObj instanceof MApplicationElement))
+						((MApplicationElement) eObj).setContributorURI(contributorURI);
+					applicationResource.setID(eObj, r.getInternalId(eObj));
+				}
+			}
+
+			List<MApplicationElement> merged = fragment.merge(application);
+
+			if (merged.size() > 0) {
+				evalImports = true;
+				addedElements.addAll(merged);
+			}
+		}
+
+		if (evalImports) {
+			List<MApplicationElement> localImports = fragmentsContainer.getImports();
+			if (localImports != null) {
+				imports.addAll(localImports);
+			}
+		}
+	}
+
+	/**
+	 * @param extensions
+	 * @param afterFragments
+	 */
+	private void runProcessors(IExtension[] extensions, boolean initial, boolean afterFragments) {
+		for (IExtension extension : extensions) {
+			IConfigurationElement[] ces = extension.getConfigurationElements();
+			for (IConfigurationElement ce : ces) {
+				boolean parseBoolean = Boolean.parseBoolean(ce.getAttribute("beforefragment")); //$NON-NLS-1$
+				if ("processor".equals(ce.getName()) && afterFragments != parseBoolean) { //$NON-NLS-1$
+					if (initial || !INITIAL.equals(ce.getAttribute("apply"))) { //$NON-NLS-1$
+						runProcessor(ce);
+					}
+				}
+			}
+		}
+	}
+
+	private void runProcessor(IConfigurationElement ce) {
+		IEclipseContext localContext = EclipseContextFactory.create();
+		IContributionFactory factory = context.get(IContributionFactory.class);
+
+		for (IConfigurationElement ceEl : ce.getChildren("element")) { //$NON-NLS-1$
+			String id = ceEl.getAttribute("id"); //$NON-NLS-1$
+
+			if (id == null) {
+				logger.warn("No element id given"); //$NON-NLS-1$
+				continue;
+			}
+
+			String key = ceEl.getAttribute("contextKey"); //$NON-NLS-1$
+			if (key == null) {
+				key = id;
+			}
+
+			MApplicationElement el = ModelUtils.findElementById(application, id);
+			if (el == null) {
+				logger.warn("Could not find element with id '" + id + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			localContext.set(key, el);
+		}
+
+		try {
+			Object o = factory
+					.create("bundleclass://" + ce.getContributor().getName() + "/" + ce.getAttribute("class"), //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+							context, localContext);
+			if (o == null) {
+				logger.warn("Unable to create processor " + ce.getAttribute("class") + " from " + ce.getContributor().getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			} else {
+				ContextInjectionFactory.invoke(o, Execute.class, context, localContext);
+			}
+		} catch (Exception e) {
+			logger.warn(e, "Could not run processor"); //$NON-NLS-1$
+		}
+	}
+
+	private void resolveImports(List<MApplicationElement> imports,
+			List<MApplicationElement> addedElements) {
+		if (imports.isEmpty())
+			return;
+		// now that we have all components loaded, resolve imports
+		Map<MApplicationElement, MApplicationElement> importMaps = new HashMap<MApplicationElement, MApplicationElement>();
+		for (MApplicationElement importedElement : imports) {
+			MApplicationElement realElement = ModelUtils.findElementById(application,
+					importedElement.getElementId());
+			if (realElement == null) {
+				logger.warn("Could not resolve an import element for '" + realElement + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+
+			importMaps.put(importedElement, realElement);
+		}
+
+		TreeIterator<EObject> it = EcoreUtil.getAllContents(addedElements);
+		List<Runnable> commands = new ArrayList<Runnable>();
+
+		// TODO Probably use EcoreUtil.UsageCrossReferencer
+		while (it.hasNext()) {
+			EObject o = it.next();
+
+			EContentsEList.FeatureIterator<EObject> featureIterator = (EContentsEList.FeatureIterator<EObject>) o
+					.eCrossReferences().iterator();
+			while (featureIterator.hasNext()) {
+				EObject importObject = featureIterator.next();
+				if (importObject.eContainmentFeature() == FragmentPackageImpl.Literals.MODEL_FRAGMENTS__IMPORTS) {
+					EStructuralFeature feature = featureIterator.feature();
+
+					MApplicationElement el = importMaps.get(importObject);
+					if (el == null) {
+						logger.warn("Could not resolve import for " + el); //$NON-NLS-1$
+					}
+
+					final EObject interalTarget = o;
+					final EStructuralFeature internalFeature = feature;
+					final MApplicationElement internalElment = el;
+					final EObject internalImportObject = importObject;
+
+					commands.add(new Runnable() {
+
+						@Override
+						public void run() {
+							if (internalFeature.isMany()) {
+								logger.error("Replacing"); //$NON-NLS-1$
+								@SuppressWarnings("unchecked")
+								List<Object> l = (List<Object>) interalTarget.eGet(internalFeature);
+								int index = l.indexOf(internalImportObject);
+								if (index >= 0) {
+									l.set(index, internalElment);
+								}
+							} else {
+								interalTarget.eSet(internalFeature, internalElment);
+							}
+						}
+					});
+				}
+			}
+		}
+
+		for (Runnable cmd : commands) {
+			cmd.run();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelReconcilingService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelReconcilingService.java
new file mode 100644
index 0000000..a839102
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelReconcilingService.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.e4.ui.workbench.modeling.ModelReconciler;
+
+public class ModelReconcilingService implements IModelReconcilingService {
+
+	@Inject
+	private Logger logger;
+
+	@Override
+	public ModelReconciler createModelReconciler() {
+		return new XMLModelReconciler();
+	}
+
+	@Override
+	public IStatus applyDeltas(Collection<ModelDelta> deltas) {
+		return applyDeltas(deltas, null);
+	}
+
+	@Override
+	public IStatus applyDeltas(Collection<ModelDelta> deltas, String[] filters) {
+		if (filters == null) {
+			filters = new String[0];
+		}
+
+		MultiStatus multiStatus = new MultiStatus(Activator.PI_WORKBENCH, 0, "", null); //$NON-NLS-1$
+		LinkedList<ModelDelta> delayedDeltas = new LinkedList<ModelDelta>();
+
+		deltaIterationLoop: for (final ModelDelta delta : deltas) {
+			for (String filter : filters) {
+				if (delta.getAttributeName().equals(filter)) {
+					continue deltaIterationLoop;
+				}
+			}
+
+			final IStatus[] status = new IStatus[1];
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					status[0] = delta.apply();
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					status[0] = new Status(IStatus.ERROR, Activator.PI_WORKBENCH,
+							"Failed to apply delta", exception); //$NON-NLS-1$
+				}
+			});
+
+			if (status[0].getSeverity() == IStatus.CANCEL) {
+				delayedDeltas.add(delta);
+				continue;
+			}
+			multiStatus.add(status[0]);
+
+			switch (status[0].getCode()) {
+			case IStatus.INFO:
+				logger.info(status[0].getMessage());
+				break;
+			case IStatus.WARNING:
+				logger.warn(status[0].getMessage());
+				break;
+			case IStatus.ERROR:
+				logger.error(status[0].getMessage());
+				break;
+			}
+		}
+
+		for (Iterator<ModelDelta> it = delayedDeltas.iterator(); it.hasNext();) {
+			final ModelDelta delta = it.next();
+			final IStatus[] status = new IStatus[1];
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					status[0] = delta.apply();
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					status[0] = new Status(IStatus.ERROR, Activator.PI_WORKBENCH,
+							"Failed to apply delta", exception); //$NON-NLS-1$
+				}
+			});
+
+			if (status[0].getSeverity() == IStatus.CANCEL) {
+				continue;
+			}
+
+			multiStatus.add(status[0]);
+
+			switch (status[0].getCode()) {
+			case IStatus.INFO:
+				logger.info(status[0].getMessage());
+				break;
+			case IStatus.WARNING:
+				logger.warn(status[0].getMessage());
+				break;
+			case IStatus.ERROR:
+				logger.error(status[0].getMessage());
+				break;
+			}
+		}
+
+		return multiStatus;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
new file mode 100644
index 0000000..98f8778
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
@@ -0,0 +1,1012 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2015 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 434611
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.commands.MBindingContext;
+import org.eclipse.e4.ui.model.application.commands.MBindingTable;
+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.commands.MKeyBinding;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MSnippetContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MAdvancedFactory;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MBasicFactory;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindowElement;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl;
+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.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.model.internal.ModelUtils;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.Selector;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;
+import org.eclipse.e4.ui.workbench.modeling.ElementMatcher;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ *
+ */
+public class ModelServiceImpl implements EModelService {
+	private static String HOSTED_ELEMENT = "HostedElement"; //$NON-NLS-1$
+
+	private IEclipseContext appContext;
+
+	/** Factory which is able to create {@link MApplicationElement}s in a generic way. */
+	private GenericMApplicationElementFactoryImpl mApplicationElementFactory;
+
+	// Cleans up after a hosted element is disposed
+	private EventHandler hostedElementHandler = new EventHandler() {
+
+		@Override
+		public void handleEvent(Event event) {
+			final MUIElement changedElement = (MUIElement) event.getProperty(EventTags.ELEMENT);
+			if (!changedElement.getTags().contains(HOSTED_ELEMENT)) {
+				return;
+			}
+
+			if (changedElement.getWidget() != null) {
+				return;
+			}
+
+			EObject eObj = (EObject) changedElement;
+			if (!(eObj.eContainer() instanceof MWindow)) {
+				return;
+			}
+
+			MWindow hostingWindow = (MWindow) eObj.eContainer();
+			hostingWindow.getSharedElements().remove(changedElement);
+			changedElement.getTags().remove(HOSTED_ELEMENT);
+		}
+	};
+
+	/**
+	 * This is a singleton service. One instance is used throughout the running application
+	 *
+	 * @param appContext
+	 *            The applicationContext to get the eventBroker from
+	 *
+	 * @throws NullPointerException
+	 *             if the given appContext is <code>null</code>
+	 */
+	public ModelServiceImpl(IEclipseContext appContext) {
+		if (appContext == null)
+		 {
+			throw new NullPointerException("No application context given!"); //$NON-NLS-1$
+		}
+
+		this.appContext = appContext;
+		IEventBroker eventBroker = appContext.get(IEventBroker.class);
+		eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, hostedElementHandler);
+
+		mApplicationElementFactory = new GenericMApplicationElementFactoryImpl(
+				appContext.get(IExtensionRegistry.class));
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public final <T extends MApplicationElement> T createModelElement(Class<T> elementType) {
+		if (elementType == null) {
+			throw new NullPointerException("Argument cannot be null."); //$NON-NLS-1$
+		}
+
+		T back = (T) mApplicationElementFactory.createEObject(elementType);
+		if (back != null) {
+			return back;
+		}
+
+		throw new IllegalArgumentException(
+				"Unsupported model object type: " + elementType.getCanonicalName()); //$NON-NLS-1$
+	}
+
+	private <T> void findElementsRecursive(MApplicationElement searchRoot, Class<T> clazz,
+			Selector matcher, List<T> elements, int searchFlags) {
+		Assert.isLegal(searchRoot != null);
+		if (searchFlags == 0) {
+			return;
+		}
+
+		// are *we* a match ?
+		boolean classMatch = clazz == null ? true : clazz.isInstance(searchRoot);
+		if (classMatch && matcher.select(searchRoot)) {
+			if (!elements.contains(searchRoot)) {
+				@SuppressWarnings("unchecked")
+				T element = (T) searchRoot;
+				elements.add(element);
+			}
+		}
+		if (searchRoot instanceof MApplication && (searchFlags == ANYWHERE)) {
+			MApplication app = (MApplication) searchRoot;
+
+			List<MApplicationElement> children = new ArrayList<MApplicationElement>();
+			if (clazz != null) {
+				if (clazz.equals(MHandler.class)) {
+					children.addAll(app.getHandlers());
+				} else if (clazz.equals(MCommand.class)) {
+					children.addAll(app.getCommands());
+				} else if (clazz.equals(MBindingContext.class)) {
+					children.addAll(app.getBindingContexts());
+				} else if (clazz.equals(MBindingTable.class) || clazz.equals(MKeyBinding.class)) {
+					children.addAll(app.getBindingTables());
+				}
+				// } else { only look for these if specifically asked.
+				// children.addAll(app.getHandlers());
+				// children.addAll(app.getCommands());
+				// children.addAll(app.getBindingContexts());
+				// children.addAll(app.getBindingTables());
+			}
+
+			for (MApplicationElement child : children) {
+				findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+			}
+		}
+
+		if (searchRoot instanceof MBindingContext && (searchFlags == ANYWHERE)) {
+			MBindingContext bindingContext = (MBindingContext) searchRoot;
+			for (MBindingContext child : bindingContext.getChildren()) {
+				findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+			}
+		}
+
+		if (searchRoot instanceof MBindingTable) {
+			MBindingTable bindingTable = (MBindingTable) searchRoot;
+			for (MKeyBinding child : bindingTable.getBindings()) {
+				findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+			}
+		}
+
+		// Check regular containers
+		if (searchRoot instanceof MElementContainer<?>) {
+			if (searchRoot instanceof MPerspectiveStack) {
+				if ((searchFlags & IN_ANY_PERSPECTIVE) != 0) {
+					// Search *all* the perspectives
+					MElementContainer<? extends MUIElement> container = (MPerspectiveStack) searchRoot;
+					List<? extends MUIElement> children = container.getChildren();
+					for (MUIElement child : children) {
+						findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+					}
+				} else if ((searchFlags & IN_ACTIVE_PERSPECTIVE) != 0) {
+					// Only search the currently active perspective, if any
+					MPerspective active = ((MPerspectiveStack) searchRoot).getSelectedElement();
+					if (active != null) {
+						findElementsRecursive(active, clazz, matcher, elements, searchFlags);
+					}
+				} else if ((searchFlags & IN_SHARED_AREA) != 0 && searchRoot instanceof MUIElement) {
+					// Only recurse through the shared areas
+					List<MArea> areas = findElements((MUIElement) searchRoot, null, MArea.class,
+							null);
+					for (MArea area : areas) {
+						findElementsRecursive(area, clazz, matcher, elements, searchFlags);
+					}
+				}
+			} else {
+				@SuppressWarnings("unchecked")
+				MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) searchRoot;
+				List<MUIElement> children = container.getChildren();
+				for (MUIElement child : children) {
+					findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+				}
+			}
+		}
+
+		// Search Trim
+		if (searchRoot instanceof MTrimmedWindow && (searchFlags & IN_TRIM) != 0) {
+			MTrimmedWindow tw = (MTrimmedWindow) searchRoot;
+			List<MTrimBar> bars = tw.getTrimBars();
+			for (MTrimBar bar : bars) {
+				findElementsRecursive(bar, clazz, matcher, elements, searchFlags);
+			}
+		}
+
+		// Search Detached Windows
+		if (searchRoot instanceof MWindow) {
+			MWindow window = (MWindow) searchRoot;
+			for (MWindow dw : window.getWindows()) {
+				findElementsRecursive(dw, clazz, matcher, elements, searchFlags);
+			}
+
+			MMenu menu = window.getMainMenu();
+			if (menu != null && (searchFlags & IN_MAIN_MENU) != 0) {
+				findElementsRecursive(menu, clazz, matcher, elements, searchFlags);
+			}
+			// Check for Handlers
+			if (searchFlags == ANYWHERE && MHandler.class.equals(clazz)) {
+				for (MHandler child : window.getHandlers()) {
+					findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+				}
+			}
+		}
+
+		if (searchRoot instanceof MPerspective) {
+			MPerspective persp = (MPerspective) searchRoot;
+			for (MWindow dw : persp.getWindows()) {
+				findElementsRecursive(dw, clazz, matcher, elements, searchFlags);
+			}
+		}
+		// Search shared elements
+		if (searchRoot instanceof MPlaceholder) {
+			MPlaceholder ph = (MPlaceholder) searchRoot;
+
+			// Don't search in shared areas unless the flag is set
+			if (ph.getRef() != null
+					&& (!(ph.getRef() instanceof MArea) || (searchFlags & IN_SHARED_AREA) != 0)) {
+				findElementsRecursive(ph.getRef(), clazz, matcher, elements, searchFlags);
+			}
+		}
+
+		if (searchRoot instanceof MPart && (searchFlags & IN_PART) != 0) {
+			MPart part = (MPart) searchRoot;
+
+			for (MMenu menu : part.getMenus()) {
+				findElementsRecursive(menu, clazz, matcher, elements, searchFlags);
+			}
+
+			MToolBar toolBar = part.getToolbar();
+			if (toolBar != null) {
+				findElementsRecursive(toolBar, clazz, matcher, elements, searchFlags);
+			}
+			if (MHandler.class.equals(clazz)) {
+				for (MHandler child : part.getHandlers()) {
+					findElementsRecursive(child, clazz, matcher, elements, searchFlags);
+				}
+			}
+		}
+	}
+
+	@Override
+	public <T> List<T> findElements(MUIElement searchRoot, String id, Class<T> clazz,
+			List<String> tagsToMatch) {
+		ElementMatcher matcher = new ElementMatcher(id, clazz, tagsToMatch);
+		return findElements(searchRoot, clazz, ANYWHERE, matcher);
+	}
+
+	@Override
+	public <T> List<T> findElements(MUIElement searchRoot, String id, Class<T> clazz,
+			List<String> tagsToMatch, int searchFlags) {
+		ElementMatcher matcher = new ElementMatcher(id, clazz, tagsToMatch);
+		return findElements(searchRoot, clazz, searchFlags, matcher);
+	}
+
+	@Override
+	public <T> List<T> findElements(MApplicationElement searchRoot, Class<T> clazz,
+			int searchFlags, Selector matcher) {
+		List<T> elements = new ArrayList<T>();
+		findElementsRecursive(searchRoot, clazz, matcher, elements, searchFlags);
+		return elements;
+	}
+
+	private <T> List<T> findPerspectiveElements(MUIElement searchRoot, String id,
+			Class<T> clazz,
+			List<String> tagsToMatch) {
+		List<T> elements = new ArrayList<T>();
+		ElementMatcher matcher = new ElementMatcher(id, clazz, tagsToMatch);
+		findElementsRecursive(searchRoot, clazz, matcher, elements, PRESENTATION);
+		return elements;
+	}
+
+	@Override
+	public MUIElement find(String id, MUIElement searchRoot) {
+		if (id == null || id.length() == 0) {
+			return null;
+		}
+
+		List<MUIElement> elements = findElements(searchRoot, id, MUIElement.class, null);
+		if (elements.size() > 0) {
+			return elements.get(0);
+		}
+		return null;
+	}
+
+	@Override
+	public int countRenderableChildren(MUIElement element) {
+		if (!(element instanceof MElementContainer<?>)) {
+			return 0;
+		}
+
+		@SuppressWarnings("unchecked")
+		MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
+		int count = 0;
+		List<MUIElement> kids = container.getChildren();
+		for (MUIElement kid : kids) {
+			if (kid.isToBeRendered()) {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	@Override
+	public IEclipseContext getContainingContext(MUIElement element) {
+		return ModelUtils.getContainingContext(element);
+	}
+
+	@Override
+	public MUIElement cloneElement(MUIElement element, MSnippetContainer snippetContainer) {
+		EObject eObj = (EObject) element;
+		MUIElement clone = (MUIElement) EcoreUtil.copy(eObj);
+
+		// null out all the references
+		List<MPlaceholder> phList = findElements(clone, null, MPlaceholder.class, null);
+		for (MPlaceholder ph : phList) {
+			// Skip placeholders in the sharedArea
+			int location = getElementLocation(ph);
+			if ((location & IN_SHARED_AREA) != 0) {
+				continue;
+			}
+
+			ph.setRef(null);
+		}
+
+		if (snippetContainer != null) {
+			MUIElement snippet = findSnippet(snippetContainer, element.getElementId());
+			if (snippet != null) {
+				snippetContainer.getSnippets().remove(snippet);
+			}
+			snippetContainer.getSnippets().add(clone);
+		}
+
+		// Cache the original element in the clone's transientData
+		clone.getTransientData().put(CLONED_FROM_KEY, element);
+
+		return clone;
+	}
+
+	@Override
+	public MUIElement cloneSnippet(MSnippetContainer snippetContainer, String snippetId,
+			MWindow refWin) {
+		if (snippetContainer == null || snippetId == null || snippetId.length() == 0) {
+			return null;
+		}
+
+		MApplicationElement elementToClone = null;
+		for (MApplicationElement snippet : snippetContainer.getSnippets()) {
+			if (snippetId.equals(snippet.getElementId())) {
+				elementToClone = snippet;
+				break;
+			}
+		}
+		if (elementToClone == null) {
+			return null;
+		}
+
+		EObject eObj = (EObject) elementToClone;
+		MUIElement element = (MUIElement) EcoreUtil.copy(eObj);
+
+		MUIElement appElement = refWin == null ? null : refWin.getParent();
+		if (appElement instanceof MApplication) {
+			// use appContext as MApplication.getContext() is null during the processing of
+			// the model processor classes
+			EPlaceholderResolver resolver = appContext.get(EPlaceholderResolver.class);
+			// Re-resolve any placeholder references
+			List<MPlaceholder> phList = findElements(element, null, MPlaceholder.class, null);
+			for (MPlaceholder ph : phList) {
+				resolver.resolvePlaceholderRef(ph, refWin);
+			}
+		}
+
+		return element;
+	}
+
+	@Override
+	public MUIElement findSnippet(MSnippetContainer snippetContainer, String id) {
+		if (snippetContainer == null || id == null || id.length() == 0) {
+			return null;
+		}
+
+		List<MUIElement> snippets = snippetContainer.getSnippets();
+		for (MUIElement snippet : snippets) {
+			if (id.equals(snippet.getElementId())) {
+				return snippet;
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public void bringToTop(MUIElement element) {
+		if (element instanceof MApplication) {
+			return;
+		}
+
+		MWindow window = getTopLevelWindowFor(element);
+		if (window == element) {
+			if (!element.isToBeRendered()) {
+				element.setToBeRendered(true);
+			}
+
+			window.getParent().setSelectedElement(window);
+		} else {
+			showElementInWindow(window, element);
+		}
+		UIEvents.publishEvent(UIEvents.UILifeCycle.BRINGTOTOP, element);
+	}
+
+	private void showElementInWindow(MWindow window, MUIElement element) {
+		MUIElement parent = element.getParent();
+		if (parent == null) {
+			MPlaceholder ph = findPlaceholderFor(window, element);
+			if (ph != null) {
+				element = ph;
+				parent = element.getParent();
+			}
+		}
+
+		if (parent == null && element instanceof MWindow) {
+			// no parent but is a window, could be a detached window then
+			parent = (MUIElement) ((EObject) element).eContainer();
+			if (parent != null) {
+				// Force the element to be rendered
+				if (!element.isToBeRendered()) {
+					element.setToBeRendered(true);
+				}
+
+				if (window != parent) {
+					showElementInWindow(window, parent);
+				}
+			}
+		} else if (parent != null) {
+			// Force the element to be rendered
+			if (!element.isToBeRendered()) {
+				element.setToBeRendered(true);
+			}
+
+			@SuppressWarnings("unchecked")
+			MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) parent;
+			container.setSelectedElement(element);
+			if (window != parent) {
+				showElementInWindow(window, parent);
+			}
+		}
+	}
+
+	@Override
+	public MPlaceholder findPlaceholderFor(MWindow window, MUIElement element) {
+		List<MPlaceholder> phList = findPerspectiveElements(window, null, MPlaceholder.class, null);
+		List<MPlaceholder> elementRefs = new ArrayList<MPlaceholder>();
+		for (MPlaceholder ph : phList) {
+			if (ph.getRef() == element) {
+				elementRefs.add(ph);
+			}
+		}
+
+		if (elementRefs.size() == 0) {
+			return null;
+		}
+
+		if (elementRefs.size() == 1) {
+			return elementRefs.get(0);
+		}
+
+		// If there is more than one placeholder then return the one in the shared area
+		for (MPlaceholder refPh : elementRefs) {
+			int loc = getElementLocation(refPh);
+			if ((loc & IN_SHARED_AREA) != 0) {
+				return refPh;
+			}
+		}
+
+		// Just return the first one
+		return elementRefs.get(0);
+	}
+
+	@Override
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent) {
+		move(element, newParent, -1, false);
+	}
+
+	@Override
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent,
+			boolean leavePlaceholder) {
+		move(element, newParent, -1, leavePlaceholder);
+	}
+
+	@Override
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent, int index) {
+		move(element, newParent, index, false);
+	}
+
+	@Override
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent, int index,
+			boolean leavePlaceholder) {
+		// Cache where we were
+		MElementContainer<MUIElement> curParent = element.getParent();
+		int curIndex = curParent.getChildren().indexOf(element);
+
+		// Move the model element
+		if (index == -1) {
+			newParent.getChildren().add(element);
+		} else {
+			newParent.getChildren().add(index, element);
+		}
+
+		if (leavePlaceholder) {
+			MPlaceholder ph = MAdvancedFactory.INSTANCE.createPlaceholder();
+			ph.setRef(element);
+			curParent.getChildren().add(curIndex, ph);
+		}
+	}
+
+	private void combine(MPartSashContainerElement toInsert, MPartSashContainerElement relTo,
+			MPartSashContainer newSash, boolean newFirst, float ratio) {
+		MElementContainer<MUIElement> curParent = relTo.getParent();
+		int index = curParent.getChildren().indexOf(relTo);
+		curParent.getChildren().remove(relTo);
+		if (newFirst) {
+			newSash.getChildren().add(toInsert);
+			newSash.getChildren().add(relTo);
+		} else {
+			newSash.getChildren().add(relTo);
+			newSash.getChildren().add(toInsert);
+		}
+
+		// Set up the container data before adding the new sash to the model
+		// To raise the granularity assume 100% == 10,000
+		int adjustedPct = (int) (ratio * 10000);
+		toInsert.setContainerData(Integer.toString(adjustedPct));
+		relTo.setContainerData(Integer.toString(10000 - adjustedPct));
+
+		// add the new sash at the same location
+		curParent.getChildren().add(index, newSash);
+	}
+
+	@Override
+	public void insert(MPartSashContainerElement toInsert, MPartSashContainerElement relTo,
+			int where, float ratio) {
+		assert (toInsert != null && relTo != null);
+		assert (ratio > 0 && ratio < 100);
+
+		// determine insertion order
+		boolean insertBefore = where == ABOVE || where == LEFT_OF;
+		boolean horizontal = where == LEFT_OF || where == RIGHT_OF;
+
+		MPartSashContainer newSash = BasicFactoryImpl.eINSTANCE.createPartSashContainer();
+		newSash.setHorizontal(horizontal);
+
+		// Maintain the existing weight in the new sash
+		newSash.setContainerData(relTo.getContainerData());
+
+		combine(toInsert, relTo, newSash, insertBefore, ratio);
+	}
+
+	@Override
+	public void detach(MPartSashContainerElement element, int x, int y, int width, int height) {
+		// If we're showing through a placehoilder then detach it...
+		if (element.getCurSharedRef() != null) {
+			element = element.getCurSharedRef();
+		}
+
+		// Determine the correct parent for the new window
+		MWindow window = getTopLevelWindowFor(element);
+		MPerspective thePersp = getPerspectiveFor(element);
+
+		MTrimmedWindow newWindow = MBasicFactory.INSTANCE.createTrimmedWindow();
+
+		newWindow.setX(x);
+		newWindow.setY(y);
+		newWindow.setWidth(width);
+		newWindow.setHeight(height);
+
+		element.getParent().getChildren().remove(element);
+		MWindowElement uiRoot = wrapElementForWindow(element);
+		newWindow.getChildren().add(uiRoot);
+
+		if (thePersp != null) {
+			thePersp.getWindows().add(newWindow);
+		} else if (window != null) {
+			window.getWindows().add(newWindow);
+		}
+	}
+
+	/**
+	 * Wraps an element in a PartStack if it's a MPart or an MPlaceholder that references an MPart
+	 *
+	 * @param element
+	 *            The element to be wrapped
+	 * @return The wrapper for the given element
+	 */
+	private MWindowElement wrapElementForWindow(MPartSashContainerElement element) {
+		if (element instanceof MPlaceholder) {
+			MUIElement ref = ((MPlaceholder) element).getRef();
+			if (ref instanceof MPart) {
+				MPartStack newPS = MBasicFactory.INSTANCE.createPartStack();
+				newPS.getChildren().add((MPlaceholder) element);
+				return newPS;
+			}
+		} else if (element instanceof MPart) {
+			MPartStack newPS = MBasicFactory.INSTANCE.createPartStack();
+			newPS.getChildren().add((MPart) element);
+			return newPS;
+		} else if (element instanceof MWindowElement) {
+			return (MWindowElement) element;
+		}
+		return null;
+	}
+
+	@Override
+	public MTrimBar getTrim(MTrimmedWindow window, SideValue sv) {
+		List<MTrimBar> bars = window.getTrimBars();
+		for (MTrimBar bar : bars) {
+			if (bar.getSide() == sv) {
+				return bar;
+			}
+		}
+
+		// Didn't find a trim bar for the side, make one
+		MTrimBar newBar = BasicFactoryImpl.eINSTANCE.createTrimBar();
+
+		// Assign default ids to the trim bars to match legacy eclipse
+		if (sv == SideValue.TOP) {
+			newBar.setElementId("org.eclipse.ui.main.menu"); //$NON-NLS-1$
+		} else if (sv == SideValue.BOTTOM) {
+			newBar.setElementId("org.eclipse.ui.trim.status"); //$NON-NLS-1$
+		} else if (sv == SideValue.LEFT) {
+			newBar.setElementId("org.eclipse.ui.trim.vertical1"); //$NON-NLS-1$
+		} else if (sv == SideValue.RIGHT) {
+			newBar.setElementId("org.eclipse.ui.trim.vertical2"); //$NON-NLS-1$
+		}
+
+		newBar.setSide(sv);
+		window.getTrimBars().add(newBar);
+		return newBar;
+	}
+
+	@Override
+	public MWindow getTopLevelWindowFor(MUIElement element) {
+		EObject eObj = (EObject) element;
+		while (eObj != null && !(eObj.eContainer() instanceof MApplication)) {
+			eObj = eObj.eContainer();
+		}
+
+		if (eObj instanceof MWindow) {
+			return (MWindow) eObj;
+		}
+
+		return null; // Ooops!
+	}
+
+	@Override
+	public MPerspective getPerspectiveFor(MUIElement element) {
+
+		while (true) {
+			// if we have a placeholder, reassign ourselves
+			MPlaceholder placeholder = element.getCurSharedRef();
+			if (placeholder != null) {
+				element = placeholder;
+			}
+			EObject container = ((EObject) element).eContainer();
+			if (container == null || container instanceof MApplication) {
+				// climbed to the top and found nothing, return null
+				return null;
+			} else if (container instanceof MPerspectiveStack) {
+				// parent is a perspective stack, we ourselves should be a perspective
+				return (MPerspective) element;
+			}
+
+			// climb up
+			element = (MUIElement) container;
+		}
+	}
+
+	@Override
+	public void resetPerspectiveModel(MPerspective persp, MWindow window) {
+		resetPerspectiveModel(persp, window, true);
+	}
+
+	private void resetPerspectiveModel(MPerspective persp, MWindow window,
+			boolean removeSharedPlaceholders) {
+		if (persp == null) {
+			return;
+		}
+
+		if (removeSharedPlaceholders) {
+			// Remove any views (Placeholders) from the shared area
+			EPartService ps = window.getContext().get(EPartService.class);
+			List<MArea> areas = findElements(window, null, MArea.class, null);
+			if (areas.size() == 1) {
+				MArea area = areas.get(0);
+
+				// Strip out the placeholders in visible stacks
+				List<MPlaceholder> phList = findElements(area, null, MPlaceholder.class, null);
+				for (MPlaceholder ph : phList) {
+					ps.hidePart((MPart) ph.getRef());
+					ph.getParent().getChildren().remove(ph);
+				}
+
+				// Prevent shared stacks ids from clashing with the ones in the perspective
+				List<MPartStack> stacks = findElements(area, null, MPartStack.class, null);
+				for (MPartStack stack : stacks) {
+					String generatedId = "PartStack@" + Integer.toHexString(stack.hashCode()); //$NON-NLS-1$
+					stack.setElementId(generatedId);
+				}
+
+				// Also remove any min/max tags on the area (or its placeholder)
+				MUIElement areaPresentation = area;
+				if (area.getCurSharedRef() != null) {
+					areaPresentation = area.getCurSharedRef();
+				}
+
+				areaPresentation.getTags().remove(IPresentationEngine.MAXIMIZED);
+				areaPresentation.getTags().remove(IPresentationEngine.MINIMIZED);
+				areaPresentation.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM);
+			}
+		}
+
+		// Remove any minimized stacks for this perspective
+		List<MTrimBar> bars = findElements(window, null, MTrimBar.class, null);
+		List<MToolControl> toRemove = new ArrayList<MToolControl>();
+		for (MTrimBar bar : bars) {
+			for (MUIElement barKid : bar.getChildren()) {
+				if (!(barKid instanceof MToolControl)) {
+					continue;
+				}
+				String id = barKid.getElementId();
+				if (id != null && id.contains(persp.getElementId())) {
+					toRemove.add((MToolControl) barKid);
+				}
+			}
+		}
+
+		for (MToolControl toolControl : toRemove) {
+			// Close any open fast view
+			toolControl.setToBeRendered(false);
+			toolControl.getParent().getChildren().remove(toolControl);
+		}
+	}
+
+	@Override
+	public void removePerspectiveModel(MPerspective persp, MWindow window) {
+		// pick a new perspective to become active (if any)
+		MUIElement psElement = persp.getParent();
+		MPerspectiveStack ps = (MPerspectiveStack) psElement;
+		boolean foundNewSelection = false;
+		if (ps.getSelectedElement() == persp) {
+			for (MPerspective p : ps.getChildren()) {
+				if (p != persp && p.isToBeRendered()) {
+					ps.setSelectedElement(p);
+					foundNewSelection = true;
+					break;
+				}
+			}
+
+			if (!foundNewSelection) {
+				ps.setSelectedElement(null);
+			}
+		}
+
+		// Remove transient elements (minimized stacks, detached windows)
+		resetPerspectiveModel(persp, window, false);
+
+		// unrender the perspective and remove it
+		persp.setToBeRendered(false);
+		ps.getChildren().remove(persp);
+	}
+
+	@Override
+	public MPerspective getActivePerspective(MWindow window) {
+		List<MPerspectiveStack> pStacks = findElements(window, null, MPerspectiveStack.class, null);
+		if (pStacks.size() == 1) {
+			return pStacks.get(0).getSelectedElement();
+		}
+
+		return null;
+	}
+
+	@Override
+	public int toBeRenderedCount(MElementContainer<?> container) {
+		int count = 0;
+		for (MUIElement child : container.getChildren()) {
+			if (child.isToBeRendered()) {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	@Override
+	public MUIElement getContainer(MUIElement element) {
+		if (element == null) {
+			return null;
+		}
+
+		return (MUIElement) ((EObject) element).eContainer();
+	}
+
+	@Override
+	public int getElementLocation(MUIElement element) {
+		if (element == null) {
+			return NOT_IN_UI;
+		}
+
+		// If the element is shared then use its current placeholder
+		if (element.getCurSharedRef() != null) {
+			element = element.getCurSharedRef();
+		}
+
+		int location = NOT_IN_UI;
+		MUIElement curElement = element;
+		while (curElement != null) {
+			Object container = ((EObject) curElement).eContainer();
+			if (!(container instanceof MUIElement))
+				return NOT_IN_UI;
+
+			if (container instanceof MApplication) {
+				if (location != NOT_IN_UI)
+					return location;
+				return OUTSIDE_PERSPECTIVE;
+			} else if (container instanceof MPerspective) {
+				MPerspective perspective = (MPerspective) container;
+				MUIElement perspParent = perspective.getParent();
+				if (perspParent == null) {
+					location = NOT_IN_UI;
+				} else if (perspective.getParent().getSelectedElement() == perspective) {
+					location |= IN_ACTIVE_PERSPECTIVE;
+				} else {
+					location |= IN_ANY_PERSPECTIVE;
+				}
+			} else if (container instanceof MTrimBar) {
+				location = IN_TRIM;
+			} else if (container instanceof MArea) {
+				location = IN_SHARED_AREA;
+			}
+
+			curElement = (MUIElement) container;
+		}
+
+		return NOT_IN_UI;
+	}
+
+	@Override
+	public MPartDescriptor getPartDescriptor(String id) {
+		MApplication application = appContext.get(MApplication.class);
+
+		// If the id contains a ':' use the part before it as the descriptor id
+		int colonIndex = id == null ? -1 : id.indexOf(':');
+		String descId = colonIndex == -1 ? id : id.substring(0, colonIndex);
+
+		for (MPartDescriptor descriptor : application.getDescriptors()) {
+			if (descriptor.getElementId().equals(descId)) {
+				return descriptor;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void hideLocalPlaceholders(MWindow window, MPerspective perspective) {
+		List<MPlaceholder> globals = findElements(window, null, MPlaceholder.class, null,
+				OUTSIDE_PERSPECTIVE | IN_SHARED_AREA);
+
+		// Iterate across the perspective(s) removing any 'local' placeholders
+		List<MPerspective> persps = new ArrayList<MPerspective>();
+		if (perspective != null) {
+			persps.add(perspective);
+		} else {
+			persps = findElements(window, null, MPerspective.class, null);
+		}
+
+		for (MPerspective persp : persps) {
+			List<MPlaceholder> locals = findElements(persp, null, MPlaceholder.class, null,
+					IN_ANY_PERSPECTIVE);
+			for (MPlaceholder local : locals) {
+				for (MPlaceholder global : globals) {
+					if (global.getRef() == local.getRef()) {
+						local.setToBeRendered(false);
+						MElementContainer<MUIElement> localParent = local.getParent();
+						setStackVisibility(localParent);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param parent
+	 */
+	private void setStackVisibility(MElementContainer<MUIElement> parent) {
+		for (MUIElement child : parent.getChildren()) {
+			if (child.isToBeRendered() && child.isVisible()) {
+				parent.setToBeRendered(true);
+				return;
+			}
+		}
+		parent.setToBeRendered(false);
+		// continue modifying the visibility as the parent's parent may also
+		// need to be hidden from the user
+		setStackVisibility(parent.getParent());
+	}
+
+	@Override
+	public boolean isLastEditorStack(MUIElement stack) {
+		if (!(stack instanceof MPartStack)) {
+			return false;
+		}
+
+		// is it in the shared area?
+		MUIElement parent = stack.getParent();
+		while (parent != null && !(parent instanceof MArea)) {
+			parent = parent.getParent();
+		}
+		if (parent == null) {
+			return false;
+		}
+
+		// OK, it's in the area, is it the last TBR one ?
+		MArea area = (MArea) parent;
+		List<MPartStack> stacks = findElements(area, null, MPartStack.class, null);
+		int count = 0;
+		for (MPartStack aStack : stacks) {
+			if (aStack.isToBeRendered()) {
+				count++;
+			}
+		}
+		return count < 2 && stack.isToBeRendered();
+	}
+
+	@Override
+	public void hostElement(MUIElement element, MWindow hostWindow, Object uiContainer,
+			IEclipseContext hostContext) {
+		// This is subtle; unless the element is hooked into the model it won't fire events
+		hostWindow.getSharedElements().add(element);
+		element.getTags().add(HOSTED_ELEMENT);
+
+		IPresentationEngine renderer = hostWindow.getContext().get(IPresentationEngine.class);
+		renderer.createGui(element, uiContainer, hostContext);
+	}
+
+	@Override
+	public boolean isHostedElement(MUIElement element, MWindow hostWindow) {
+		MUIElement curElement = element;
+		while (curElement != null && !curElement.getTags().contains(HOSTED_ELEMENT)) {
+			if (curElement.getCurSharedRef() != null) {
+				curElement = curElement.getCurSharedRef();
+			} else {
+				curElement = curElement.getParent();
+			}
+		}
+
+		if (curElement == null) {
+			return false;
+		}
+
+		return hostWindow.getSharedElements().contains(curElement);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/OpaqueElementUtil.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/OpaqueElementUtil.java
new file mode 100644
index 0000000..e5a58d1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/OpaqueElementUtil.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+
+/**
+ * Utility class that encapsulates the representation of 'opaque' menu and tool bar elements in the
+ * model.
+ */
+public class OpaqueElementUtil {
+
+	/**
+	 * A tag value that indicates a menu, menu item, menu separator or tool item is 'opaque'
+	 */
+	private static final String OPAQUE_TAG = "Opaque"; //$NON-NLS-1$
+
+	/**
+	 * A transient value key for the 'opaque item'
+	 */
+	private static final String OPAQUE_ITEM_KEY = "OpaqueItem"; //$NON-NLS-1$
+
+	/**
+	 * Remove the 'opaque item' from the UI Element
+	 *
+	 * @param uiElement
+	 *            the UI element
+	 * @return the removed 'opaque item' or <code>null</code>
+	 */
+	public static Object clearOpaqueItem(MUIElement uiElement) {
+		return uiElement.getTransientData().remove(OPAQUE_ITEM_KEY);
+	}
+
+	/**
+	 * Create an opaque menu
+	 *
+	 * @return a new opaque menu
+	 */
+	public static MMenu createOpaqueMenu() {
+		final MMenu menu = MMenuFactory.INSTANCE.createMenu();
+		menu.getTags().add(OPAQUE_TAG);
+		return menu;
+	}
+
+	/**
+	 * Create an opaque menu item
+	 *
+	 * @return a new opaque menu item.
+	 */
+	public static MMenuItem createOpaqueMenuItem() {
+		final MMenuItem item = MMenuFactory.INSTANCE.createDirectMenuItem();
+		item.getTags().add(OPAQUE_TAG);
+		return item;
+	}
+
+	/**
+	 * Create an opaque menu separator
+	 *
+	 * @return a new opaque menu separator
+	 */
+	public static MMenuSeparator createOpaqueMenuSeparator() {
+		final MMenuSeparator separator = MMenuFactory.INSTANCE.createMenuSeparator();
+		separator.getTags().add(OPAQUE_TAG);
+		return separator;
+	}
+
+	/**
+	 * Create an opaque tool item
+	 *
+	 * @return a new opaque tool item.
+	 */
+	public static MToolItem createOpaqueToolItem() {
+		final MToolItem item = MMenuFactory.INSTANCE.createDirectToolItem();
+		item.getTags().add(OPAQUE_TAG);
+		return item;
+	}
+
+	/**
+	 * Get the 'opaque item' associated with the UI Element.
+	 *
+	 * @param uiElement
+	 *            a UI element
+	 * @return the opaque item or <code>null</code>
+	 */
+	public static Object getOpaqueItem(MUIElement uiElement) {
+		return uiElement.getTransientData().get(OPAQUE_ITEM_KEY);
+	}
+
+	/**
+	 * Tests whether a menu element is an opaque menue
+	 *
+	 * @param item
+	 * @return <code>true</code> if the element is an 'opaque' menu
+	 */
+	public static boolean isOpaqueMenu(MUIElement item) {
+		return item != null && item instanceof MMenu && item.getTags().contains(OPAQUE_TAG);
+	}
+
+	/**
+	 * Tests whether a menu element is an opaque menu item
+	 *
+	 * @param item
+	 *            a menu item.
+	 * @return <code>true</code> if the menu element is an 'opaque' menu item
+	 */
+	public static boolean isOpaqueMenuItem(MUIElement item) {
+		return item != null && item instanceof MDirectMenuItem
+				&& item.getTags().contains(OPAQUE_TAG);
+	}
+
+	/**
+	 * Tests whether a menu element is an opaque menu separator
+	 *
+	 * @param item
+	 *            a menu item.
+	 * @return <code>true</code> if the menu element is an 'opaque' separator
+	 */
+	public static boolean isOpaqueMenuSeparator(MUIElement item) {
+		return item != null && item instanceof MMenuSeparator
+				&& item.getTags().contains(OPAQUE_TAG);
+	}
+
+	/**
+	 * Tests whether a UI element is an 'opaque' tool item
+	 *
+	 * @param uiElement
+	 *            a UI element.
+	 * @return <code>true</code> if the tool item is 'opaque'
+	 */
+	public static boolean isOpaqueToolItem(MUIElement uiElement) {
+		return uiElement != null && uiElement instanceof MDirectToolItem
+				&& uiElement.getTags().contains(OPAQUE_TAG);
+	}
+
+	/**
+	 * Set the 'opaque item' associated with the UI Element.
+	 *
+	 * @param uiElement
+	 *            the UI Element.
+	 * @param opaqueItem
+	 *            the opaque item.
+	 */
+	public static void setOpaqueItem(MUIElement uiElement, Object opaqueItem) {
+		uiElement.getTransientData().put(OPAQUE_ITEM_KEY, opaqueItem);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Parameter.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Parameter.java
new file mode 100644
index 0000000..362c680
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Parameter.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import java.util.Collections;
+import java.util.Map;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.IParameterValues;
+import org.eclipse.core.commands.ITypedParameter;
+import org.eclipse.core.commands.ParameterType;
+import org.eclipse.core.commands.ParameterValuesException;
+import org.eclipse.core.commands.common.HandleObject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * <p>
+ * A parameter for a command. A parameter identifies a type of information that the command might
+ * accept. For example, a "Show View" command might accept the id of a view for display. This
+ * parameter also identifies possible values, for display in the user interface.
+ * </p>
+ * <p>
+ * Parameters are mutable, and can change as the command changes. Notifications will not be sent if
+ * the parameter itself changes. Listeners can be attached to the command.
+ * </p>
+ *
+ * @since 3.1
+ */
+public final class Parameter implements IParameter, ITypedParameter {
+	/**
+	 * The name of the configuration element attribute contain the values. This is used to retrieve
+	 * the executable extension <code>IParameterValues</code>.
+	 */
+	private static final String ATTRIBUTE_VALUES = "values"; //$NON-NLS-1$
+
+	/**
+	 * The constant integer hash code value meaning the hash code has not yet been computed.
+	 */
+	private static final int HASH_CODE_NOT_COMPUTED = -1;
+
+	/**
+	 * A factor for computing the hash code for all schemes.
+	 */
+	private static final int HASH_FACTOR = 89;
+
+	/**
+	 * The seed for the hash code for all schemes.
+	 */
+	private static final int HASH_INITIAL = HandleObject.class.getName().hashCode();
+
+	/**
+	 * The hash code for this object. This value is computed lazily, and marked as invalid when one
+	 * of the values on which it is based changes.
+	 */
+	private transient int hashCode = HASH_CODE_NOT_COMPUTED;
+
+	/**
+	 * The identifier for this object. This identifier should be unique across all objects of the
+	 * same type and should never change. This value will never be <code>null</code>.
+	 */
+	protected final String id;
+
+	/**
+	 * The non-externalized name of this parameter. The name is used as the in a name-value
+	 * parameter map. This value will never be <code>null</code>.
+	 */
+	private final String name;
+
+	/**
+	 * Whether the parameter is optional (as opposed to required).
+	 */
+	private final boolean optional;
+
+	/**
+	 * The type for this parameter. This value may be <code>null</code> if the parameter is not
+	 * typed.
+	 */
+	private final ParameterType parameterType;
+
+	/**
+	 * The string representation of this object. This string is for debugging purposes only, and is
+	 * not meant to be displayed to the user. This value is computed lazily, and is cleared if one
+	 * of its dependent values changes.
+	 */
+	protected transient String string = null;
+
+	/**
+	 * The actual <code>IParameterValues</code> implementation. This is lazily loaded from the
+	 * <code>valuesConfigurationElement</code>, to avoid unnecessary class-loading.
+	 */
+	private transient IParameterValues values = null;
+
+	private IConfigurationElement valuesConfigurationElement;
+
+	/**
+	 * Constructs a new instance of <code>Parameter</code> with all of its values pre-defined.
+	 *
+	 * @param id
+	 *            The identifier for this parameter; must not be <code>null</code>.
+	 * @param name
+	 *            The name for this parameter; must not be <code>null</code>.
+	 * @param values
+	 *            The values for this parameter; must not be <code>null</code>.
+	 * @param parameterType
+	 *            the type for this parameter; may be <code>null</code> if the parmeter doesn't
+	 *            declare type.
+	 * @param optional
+	 *            Whether this parameter is optional (as opposed to required).
+	 */
+	public Parameter(final String id, final String name, final IConfigurationElement values,
+			final ParameterType parameterType, final boolean optional) {
+		if (id == null) {
+			throw new NullPointerException("Cannot create a parameter with a null id"); //$NON-NLS-1$
+		}
+
+		if (name == null) {
+			throw new NullPointerException("The name of a parameter cannot be null."); //$NON-NLS-1$
+		}
+
+		this.valuesConfigurationElement = values;
+		this.id = id;
+		this.name = name;
+		this.parameterType = parameterType;
+		this.optional = optional;
+	}
+
+	/**
+	 * Tests whether this object is equal to another object. A parameter is only equal to another
+	 * parameter with the same properties.
+	 *
+	 * @param object
+	 *            The object with which to compare; may be <code>null</code>.
+	 * @return <code>true</code> if the objects are equal; <code>false</code> otherwise.
+	 */
+	@Override
+	public final boolean equals(final Object object) {
+		if (this == object) {
+			return true;
+		}
+
+		if (!(object instanceof Parameter)) {
+			return false;
+		}
+
+		final Parameter parameter = (Parameter) object;
+		if (!Util.equals(id, parameter.id)) {
+			return false;
+		}
+		if (!Util.equals(name, parameter.name)) {
+			return false;
+		}
+		if (!Util.equals(values, parameter.values)) {
+			return false;
+		}
+
+		return Util.equals(optional, parameter.optional);
+	}
+
+	@Override
+	public final String getId() {
+		return id;
+	}
+
+	@Override
+	public final String getName() {
+		return name;
+	}
+
+	@Override
+	public final ParameterType getParameterType() {
+		return parameterType;
+	}
+
+	@Override
+	public final IParameterValues getValues() throws ParameterValuesException {
+		if (values == null) {
+			if (valuesConfigurationElement != null) {
+				try {
+					values = (IParameterValues) valuesConfigurationElement
+							.createExecutableExtension(ATTRIBUTE_VALUES);
+				} catch (final CoreException e) {
+					throw new ParameterValuesException("Problem creating parameter values", e); //$NON-NLS-1$
+				} catch (final ClassCastException e) {
+					throw new ParameterValuesException(
+							"Parameter values were not an instance of IParameterValues", e); //$NON-NLS-1$
+				}
+			} else {
+				values = new IParameterValues() {
+					@Override
+					public Map getParameterValues() {
+						return Collections.EMPTY_MAP;
+					}
+				};
+			}
+		}
+
+		return values;
+	}
+
+	@Override
+	public final int hashCode() {
+		if (hashCode == HASH_CODE_NOT_COMPUTED) {
+			hashCode = HASH_INITIAL * HASH_FACTOR + Util.hashCode(id);
+			if (hashCode == HASH_CODE_NOT_COMPUTED) {
+				hashCode++;
+			}
+		}
+		return hashCode;
+	}
+
+	@Override
+	public final boolean isOptional() {
+		return optional;
+	}
+
+	@Override
+	public final String toString() {
+		if (string == null) {
+			final StringBuffer buffer = new StringBuffer();
+
+			buffer.append("Parameter("); //$NON-NLS-1$
+			buffer.append(id);
+			buffer.append(',');
+			buffer.append(name);
+			buffer.append(',');
+			buffer.append(values);
+			buffer.append(',');
+			buffer.append(optional);
+			buffer.append(')');
+
+			string = buffer.toString();
+		}
+
+		return string;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartActivationHistory.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartActivationHistory.java
new file mode 100644
index 0000000..423c038
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartActivationHistory.java
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MGenericStack;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+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.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.emf.ecore.EObject;
+
+class PartActivationHistory {
+
+	private PartServiceImpl partService;
+
+	private EModelService modelService;
+
+	private LinkedList<MPart> generalActivationHistory = new LinkedList<MPart>();
+
+	PartActivationHistory(PartServiceImpl partService, EModelService modelService) {
+		this.partService = partService;
+		this.modelService = modelService;
+	}
+
+	public void clear() {
+		generalActivationHistory.clear();
+	}
+
+	void activate(MPart part, boolean activateBranch) {
+		IEclipseContext context = part.getContext();
+		if (activateBranch) {
+			context.activateBranch();
+		} else {
+			IEclipseContext parent = context.getParent();
+			do {
+				context.activate();
+				context = parent;
+				parent = parent.getParent();
+			} while (parent.get(MWindow.class) != null);
+		}
+
+		prepend(part);
+	}
+
+	/**
+	 * Places the specified part at the end of the activation history if it is not already in the
+	 * list. If it is already in the activation history, then its position will not change.
+	 *
+	 * @param part
+	 *            the part to possibly add to the end of the activation history
+	 */
+	void append(MPart part) {
+		if (!generalActivationHistory.contains(part)) {
+			generalActivationHistory.addLast(part);
+		}
+	}
+
+	/**
+	 * Adds the specified part to the front of the activation history.
+	 *
+	 * @param part
+	 *            the part to insert into the front of the activation history
+	 */
+	void prepend(MPart part) {
+		generalActivationHistory.remove(part);
+		generalActivationHistory.addFirst(part);
+	}
+
+	/**
+	 * Checks to see if this element and its parents are actually being rendered.
+	 */
+	boolean isValid(MUIElement element) {
+		if (element == null || !element.isToBeRendered() || !element.isVisible()) {
+			return false;
+		}
+
+		if (element instanceof MApplication) {
+			return true;
+		}
+
+		MUIElement parent = element.getParent();
+		if (parent == null && element instanceof MWindow) {
+			// might be a detached window
+			parent = (MUIElement) ((EObject) element).eContainer();
+		}
+
+		if (parent == null) {
+			return isValid(partService.getLocalPlaceholder(element));
+		}
+
+		return isValid(parent);
+	}
+
+	/**
+	 * Checks to see if this element and its parents are actually being rendered.
+	 */
+	boolean isValid(MPerspective perspective, MUIElement element) {
+		if (element instanceof MApplication) {
+			return true;
+		} else if (element == null || !element.isToBeRendered() || !element.isVisible()) {
+			return false;
+		}
+
+		MElementContainer<?> parent = element.getParent();
+		if (parent == null) {
+			for (MPlaceholder placeholder : modelService.findElements(perspective, null,
+					MPlaceholder.class, null)) {
+				if (placeholder.getRef() == element) {
+					return isValid(perspective, placeholder);
+				}
+			}
+
+			if (element instanceof MWindow) {
+				// might be a detached window
+				return isValid(perspective, (MUIElement) ((EObject) element).eContainer());
+			}
+			return false;
+		} else if (parent instanceof MGenericStack && parent.getSelectedElement() != element) {
+			// if in a stack, then only valid if we're the selected element
+			return false;
+		}
+
+		return isValid(perspective, parent);
+	}
+
+	/**
+	 * Determines whether this element is contained within an MArea, and to return the area if it
+	 * is.
+	 */
+	private MArea isInArea(MUIElement element) {
+		MPlaceholder placeholder = element.getCurSharedRef();
+		if (placeholder == null) {
+			MUIElement parent = element.getParent();
+			if (parent == null) {
+				// may be null for detached windows
+				parent = (MUIElement) ((EObject) element).eContainer();
+			}
+			return parent instanceof MApplication ? null : parent instanceof MArea ? (MArea) parent
+					: isInArea(parent);
+		}
+
+		MUIElement parent = placeholder.getParent();
+		if (parent == null) {
+			// may be null for detached windows
+			parent = (MUIElement) ((EObject) placeholder).eContainer();
+		}
+		return parent instanceof MApplication ? null : parent instanceof MArea ? (MArea) parent
+				: isInArea(parent);
+	}
+
+	private MPart getActivationCandidate(MPart part) {
+		// get all the possible parts that we can possibly activate
+		Collection<MPart> candidates = part.getContext().get(EPartService.class).getParts();
+		return findActivationCandidate(candidates, part);
+	}
+
+	/**
+	 * Finds and returns a part that is a valid candidate to be granted activation.
+	 */
+	private MPart findActivationCandidate(Collection<MPart> candidates, MPart currentlyActivePart) {
+		candidates.remove(currentlyActivePart);
+
+		MPlaceholder activePlaceholder = partService.getLocalPlaceholder(currentlyActivePart);
+		for (MPart candidate : candidates) {
+			// make sure it's rendered and visible
+			if (isValid(candidate)) {
+				MPlaceholder placeholder = partService.getLocalPlaceholder(candidate);
+				MElementContainer<MUIElement> parent = placeholder == null ? candidate.getParent()
+						: placeholder.getParent();
+				// stacks require special considerations because we don't want to activate something
+				// that's not the selected element if possible get the selected element
+				if (parent instanceof MGenericStack) {
+					MUIElement selection = parent.getSelectedElement();
+					// if the selected element is the currently active part, the candidate is valid
+					if (selection == activePlaceholder || selection == currentlyActivePart) {
+						return candidate;
+					}
+
+					// if the selected element is the current candidate, the candidate is valid
+					if (selection == candidate || selection == placeholder) {
+						return candidate;
+					}
+				} else {
+					// not in a stack, just return the candidate then
+					return candidate;
+				}
+			}
+		}
+		return null;
+	}
+
+	MPart getActivationCandidate(Collection<MPart> validParts) {
+		// check activation history, since the history is global, we need to filter it down first
+		Collection<MPart> validCandidates = new ArrayList<MPart>();
+		for (MPart validPart : generalActivationHistory) {
+			if (validParts.contains(validPart)) {
+				validCandidates.add(validPart);
+			}
+		}
+
+		MPart candidate = findActivationCandidate(validCandidates);
+		if (candidate == null) {
+			validParts.removeAll(validCandidates);
+			return findActivationCandidate(validParts);
+		}
+		return candidate;
+	}
+
+	private MPart findActivationCandidate(Collection<MPart> candidates) {
+		for (MPart candidate : candidates) {
+			// make sure it's rendered and visible
+			if (isValid(candidate)) {
+				MPlaceholder placeholder = partService.getLocalPlaceholder(candidate);
+				MElementContainer<MUIElement> parent = placeholder == null ? candidate.getParent()
+						: placeholder.getParent();
+				// stacks require special considerations because we don't want to activate something
+				// that's not the selected element if possible get the selected element
+				if (parent instanceof MGenericStack) {
+					MUIElement selection = parent.getSelectedElement();
+					// if the selected element is the current candidate, the candidate is valid
+					if (selection == candidate || selection == placeholder) {
+						return candidate;
+					}
+				} else {
+					// not in a stack, just return the candidate then
+					return candidate;
+				}
+			}
+		}
+		return null;
+	}
+
+	MPart getNextActivationCandidate(Collection<MPart> validParts, MPart part) {
+		MArea area = isInArea(part);
+		if (area != null) {
+			// focus should stay in the area if possible
+			MPart candidate = getSiblingActivationCandidate(part);
+			if (candidate != null) {
+				return candidate;
+			}
+
+			// no sibling candidate, find another part in the area to activate
+			candidate = findActivationCandidate(
+					modelService.findElements(area, null, MPart.class, null), part);
+			if (candidate != null) {
+				return candidate;
+			}
+		}
+
+		// check activation history, since the history is global, we need to filter it down first
+		Collection<MPart> validCandidates = new ArrayList<MPart>();
+		for (MPart validPart : generalActivationHistory) {
+			if (validParts.contains(validPart)) {
+				validCandidates.add(validPart);
+			}
+		}
+
+		MPart candidate = findActivationCandidate(validCandidates, part);
+		return candidate == null ? getActivationCandidate(part) : candidate;
+	}
+
+	void forget(MWindow window, MPart part, boolean full) {
+		if (full) {
+			generalActivationHistory.remove(part);
+		} else {
+			for (MPlaceholder placeholder : modelService.findElements(window, null,
+					MPlaceholder.class, null)) {
+				// if there is at least one placeholder around, we should keep this
+				if (placeholder.getRef() == part && placeholder.isToBeRendered()) {
+					return;
+				}
+			}
+
+			generalActivationHistory.remove(part);
+		}
+	}
+
+	MPart getActivationCandidate(MPerspective perspective) {
+		for (MPart candidate : generalActivationHistory) {
+			if (partService.isInContainer(perspective, candidate)
+					&& isValid(perspective, candidate)) {
+				return candidate;
+			}
+		}
+
+		List<String> activeTag = new ArrayList<String>();
+		activeTag.add(EPartService.ACTIVE_ON_CLOSE_TAG);
+		List<MPart> activeCandidates = modelService.findElements(perspective, null, MPart.class,
+				activeTag);
+		if (activeCandidates.size() > 0) {
+			activeCandidates.get(0).getTags().remove(EPartService.ACTIVE_ON_CLOSE_TAG);
+			MPart candidate = activeCandidates.get(0);
+			if (partService.isInContainer(perspective, candidate)
+					&& isValid(perspective, candidate)) {
+				return candidate;
+			}
+		}
+
+		Collection<MPart> candidates = perspective.getContext().get(EPartService.class).getParts();
+		for (MPart candidate : candidates) {
+			if (isValid(perspective, candidate)) {
+				return candidate;
+			}
+		}
+		return null;
+	}
+
+	private MPart getSiblingActivationCandidate(MPart part) {
+		MPlaceholder placeholder = part.getCurSharedRef();
+		MUIElement candidate = getSiblingSelectionCandidate(part, placeholder == null ? part
+				: placeholder);
+		return (MPart) (candidate instanceof MPlaceholder ? ((MPlaceholder) candidate).getRef()
+				: candidate);
+	}
+
+	private MUIElement getSiblingSelectionCandidate(MPart part, MUIElement element) {
+		List<MUIElement> siblings = element.getParent().getChildren();
+		for (MPart previouslyActivatedPart : generalActivationHistory) {
+			if (previouslyActivatedPart != part && isValid(previouslyActivatedPart)) {
+				if (siblings.contains(previouslyActivatedPart)) {
+					return previouslyActivatedPart;
+				}
+
+				MPlaceholder placeholder = partService.getLocalPlaceholder(previouslyActivatedPart);
+				if (placeholder != null && placeholder.isToBeRendered()
+						&& siblings.contains(placeholder)) {
+					return placeholder;
+				}
+			}
+		}
+		return null;
+	}
+
+	MUIElement getSiblingSelectionCandidate(MPart part) {
+		MPlaceholder placeholder = part.getCurSharedRef();
+		return getSiblingSelectionCandidate(part, placeholder == null ? part : placeholder);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceCreationFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceCreationFunction.java
new file mode 100644
index 0000000..9136a1c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceCreationFunction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.IInjector;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+
+/**
+ *
+ */
+public class PartServiceCreationFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		// look for the top-most MWindow in the context chain:
+
+		// 1st: go up the tree to find topmost MWindow
+		MWindow window = null;
+		IEclipseContext current = context;
+		do {
+			MContext model = current.get(MContext.class);
+			if (model instanceof MWindow)
+				window = (MWindow) model;
+			current = current.getParent();
+		} while (current != null);
+
+		if (window == null) {
+			if (context.get(MApplication.class) != null) {
+				// called from Application scope
+				return ContextInjectionFactory.make(ApplicationPartServiceImpl.class, context);
+			}
+			return IInjector.NOT_A_VALUE;
+		}
+
+		IEclipseContext windowContext = window.getContext();
+		PartServiceImpl service = windowContext.getLocal(PartServiceImpl.class);
+		if (service == null) {
+			service = ContextInjectionFactory.make(PartServiceImpl.class, windowContext);
+			windowContext.set(PartServiceImpl.class, service);
+		}
+		return service;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java
new file mode 100644
index 0000000..a72fe32
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java
@@ -0,0 +1,1418 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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 416082
+ *     Simon Scholz <simon.scholz@vogella.com> - Bug 450411
+ *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 463962
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.InjectionException;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MGenericStack;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
+import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.services.EContextService;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.IPartListener;
+import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+public class PartServiceImpl implements EPartService {
+
+	private EventHandler selectedHandler = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			// no need to do anything if we have no listeners
+			if (!listeners.isEmpty()) {
+				Object oldSelected = event.getProperty(UIEvents.EventTags.OLD_VALUE);
+				if (oldSelected instanceof MPlaceholder) {
+					oldSelected = ((MPlaceholder) oldSelected).getRef();
+				}
+
+				MPlaceholder placeholder = null;
+				Object selected = event.getProperty(UIEvents.EventTags.NEW_VALUE);
+				if (selected instanceof MPlaceholder) {
+					placeholder = (MPlaceholder) selected;
+					selected = placeholder.getRef();
+				}
+
+				MPart oldSelectedPart = oldSelected instanceof MPart ? (MPart) oldSelected : null;
+				MPart selectedPart = selected instanceof MPart ? (MPart) selected : null;
+
+				if (oldSelectedPart != null && getParts().contains(selectedPart)) {
+					firePartHidden(oldSelectedPart);
+				}
+
+				if (selectedPart != null && selectedPart.isToBeRendered()
+						&& getParts().contains(selectedPart)) {
+					// ask the renderer to create this part
+					if (placeholder == null) {
+						if (selectedPart.getParent().getRenderer() != null) {
+							engine.createGui(selectedPart);
+							firePartVisible(selectedPart);
+							firePartBroughtToTop(selectedPart);
+						}
+					} else if (placeholder.getParent().getRenderer() != null) {
+						engine.createGui(placeholder);
+						firePartVisible(selectedPart);
+						firePartBroughtToTop(selectedPart);
+					}
+				}
+			}
+		}
+	};
+
+	private EventHandler minimizedPartHandler = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
+			if (!(element instanceof MPartStack)) {
+				return;
+			}
+
+			Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);
+			Object oldValue = event.getProperty(UIEvents.EventTags.OLD_VALUE);
+
+			boolean minimizedTagAdded = UIEvents.isADD(event)
+					&& IPresentationEngine.MINIMIZED.equals(newValue);
+			boolean minimizedTagRemoved = UIEvents.isREMOVE(event)
+					&& IPresentationEngine.MINIMIZED.equals(oldValue);
+
+			if (!(minimizedTagAdded || minimizedTagRemoved)) {
+				return;
+			}
+
+			MPart part = toPart(((MPartStack) element).getSelectedElement());
+			if (part != null && minimizedTagAdded) {
+				firePartHidden(part);
+			} else if (part != null) {
+				firePartVisible(part);
+			}
+		}
+
+		private MPart toPart(MStackElement stackElement) {
+			if (stackElement != null) {
+				return stackElement instanceof MPlaceholder ? (MPart) ((MPlaceholder) stackElement)
+						.getRef() : (MPart) stackElement;
+			}
+			return null;
+		}
+	};
+
+	private MApplication application;
+
+	/**
+	 * Might be null if this part service is created for the application
+	 */
+	private MWindow workbenchWindow;
+
+	@Inject
+	private IPresentationEngine engine;
+
+	@Inject
+	private EModelService modelService;
+
+	@Inject
+	private Logger logger;
+
+	@Inject
+	@Optional
+	private ISaveHandler saveHandler;
+
+	@Inject
+	private IEventBroker eventBroker;
+
+	// @Optional as the context service may not have been installed
+	@Inject
+	@Optional
+	private EContextService contextService;
+
+	@Inject
+	@Optional
+	private ContextManager contextManager;
+
+	private PartActivationHistory partActivationHistory;
+
+	private MPart activePart;
+
+	private ListenerList listeners = new ListenerList();
+
+	private boolean constructed = false;
+
+	@Inject
+	public PartServiceImpl(MApplication application, @Optional MWindow window) {
+		// no need to track changes:
+		this.application = application;
+		workbenchWindow = window;
+	}
+
+	private void log(String unidentifiedMessage, String identifiedMessage, String id, Exception e) {
+		if (id == null || id.length() == 0) {
+			logger.error(e, unidentifiedMessage);
+		} else {
+			logger.error(e, NLS.bind(identifiedMessage, id));
+		}
+	}
+
+	@Inject
+	void setPart(@Optional @Named(IServiceConstants.ACTIVE_PART) MPart p) {
+		if (activePart != p) {
+			if (p != null) {
+				MPerspective persp = modelService.getPerspectiveFor(p);
+				boolean inCurrentPerspective = persp == null
+						|| persp == persp.getParent().getSelectedElement();
+				if (inCurrentPerspective) {
+					activate(p, true, true);
+				}
+			} else {
+				activate(p, true, true);
+			}
+		}
+	}
+
+	@PostConstruct
+	void postConstruct() {
+		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, selectedHandler);
+		eventBroker.subscribe(UIEvents.ApplicationElement.TOPIC_TAGS, minimizedPartHandler);
+		constructed = true;
+		partActivationHistory = new PartActivationHistory(this, modelService);
+		if (activePart != null) {
+			partActivationHistory.prepend(activePart);
+		}
+	}
+
+	@PreDestroy
+	void preDestroy() {
+		constructed = false;
+		eventBroker.unsubscribe(selectedHandler);
+		eventBroker.unsubscribe(minimizedPartHandler);
+		partActivationHistory.clear();
+	}
+
+	private void firePartActivated(final MPart part) {
+		for (final Object listener : listeners.getListeners()) {
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					((IPartListener) listener).partActivated(part);
+				}
+
+				@Override
+				public void handleException(Throwable throwable) {
+					logger.error(throwable, "An exception occurred while notifying part listeners"); //$NON-NLS-1$
+				}
+			});
+		}
+	}
+
+	private void firePartDeactivated(final MPart part) {
+		for (final Object listener : listeners.getListeners()) {
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					((IPartListener) listener).partDeactivated(part);
+				}
+
+				@Override
+				public void handleException(Throwable throwable) {
+					logger.error(throwable, "An exception occurred while notifying part listeners"); //$NON-NLS-1$
+				}
+			});
+		}
+	}
+
+	private void firePartHidden(final MPart part) {
+		for (final Object listener : listeners.getListeners()) {
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					((IPartListener) listener).partHidden(part);
+				}
+
+				@Override
+				public void handleException(Throwable throwable) {
+					logger.error(throwable, "An exception occurred while notifying part listeners"); //$NON-NLS-1$
+				}
+			});
+		}
+	}
+
+	private void firePartVisible(final MPart part) {
+		for (final Object listener : listeners.getListeners()) {
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					((IPartListener) listener).partVisible(part);
+				}
+
+				@Override
+				public void handleException(Throwable throwable) {
+					logger.error(throwable, "An exception occurred while notifying part listeners"); //$NON-NLS-1$
+				}
+			});
+		}
+	}
+
+	private void firePartBroughtToTop(final MPart part) {
+		for (final Object listener : listeners.getListeners()) {
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					((IPartListener) listener).partBroughtToTop(part);
+				}
+
+				@Override
+				public void handleException(Throwable throwable) {
+					logger.error(throwable, "An exception occurred while notifying part listeners"); //$NON-NLS-1$
+				}
+			});
+		}
+	}
+
+	@Override
+	public void addPartListener(IPartListener listener) {
+		listeners.add(listener);
+	}
+
+	@Override
+	public void removePartListener(IPartListener listener) {
+		listeners.remove(listener);
+	}
+
+	private MWindow getWindow() {
+		if (workbenchWindow != null)
+			return workbenchWindow;
+		if (application.getSelectedElement() != null)
+			return application.getSelectedElement();
+		List<MWindow> windows = application.getChildren();
+		if (windows.size() != 0)
+			return windows.get(0);
+		return null;
+	}
+
+	private MContext getParentWithContext(MUIElement part) {
+		MElementContainer<MUIElement> parent = part.getParent();
+		MUIElement intermediate = parent;
+		if (intermediate == null) {
+			intermediate = part;
+		} else {
+			while (parent != null) {
+				if (parent instanceof MContext) {
+					if (((MContext) parent).getContext() != null)
+						return (MContext) parent;
+				}
+				intermediate = parent;
+				parent = parent.getParent();
+			}
+		}
+
+		MPlaceholder placeholder = modelService.findPlaceholderFor(getWindow(), intermediate);
+		parent = placeholder.getParent();
+		while (parent != null) {
+			if (parent instanceof MContext) {
+				if (((MContext) parent).getContext() != null)
+					return (MContext) parent;
+			}
+			parent = parent.getParent();
+		}
+		return null;
+	}
+
+	@Override
+	public void bringToTop(MPart part) {
+		if (isInContainer(part)) {
+			MUIElement currentElement = part;
+			MElementContainer<MUIElement> parent = part.getParent();
+			if (parent == null) {
+				currentElement = modelService.findPlaceholderFor(getWindow(), part);
+				parent = currentElement.getParent();
+			}
+
+			// If the part is in the same stack as the currently active part then activate it
+			// instead
+			MElementContainer<MUIElement> activeParent = activePart != null ? activePart
+					.getParent() : null;
+			if (activePart != null && activeParent == null) {
+				MPlaceholder activePH = modelService.findPlaceholderFor(getWindow(), activePart);
+				if (activePH != null) {
+					activeParent = activePH.getParent();
+				}
+			}
+			if (parent == activeParent && part != activePart) {
+				activate(part);
+				return;
+			}
+
+			MUIElement oldSelectedElement = parent.getSelectedElement();
+
+			delegateBringToTop(part);
+
+			// check to make sure that the currently selected element is actually valid
+			if (oldSelectedElement != currentElement
+					&& parent.getChildren().contains(oldSelectedElement)
+					&& parent instanceof MGenericStack<?>) {
+				if (oldSelectedElement instanceof MPlaceholder) {
+					oldSelectedElement = ((MPlaceholder) oldSelectedElement).getRef();
+				}
+				internalFixContext(part, oldSelectedElement);
+			}
+		}
+	}
+
+	private IEclipseContext getSubContext(MUIElement element) {
+		if (element instanceof MContext) {
+			return ((MContext) element).getContext();
+		} else if (element instanceof MElementContainer<?>) {
+			Object selectedElement = ((MElementContainer<?>) element).getSelectedElement();
+			if (selectedElement instanceof MContext) {
+				return ((MContext) selectedElement).getContext();
+			} else if (selectedElement instanceof MElementContainer<?>) {
+				return getSubContext((MUIElement) selectedElement);
+			}
+		}
+		return null;
+	}
+
+	private void internalFixContext(MPart part, MUIElement oldSelectedElement) {
+		if (oldSelectedElement == null) {
+			return;
+		}
+
+		MContext parentPart = getParentWithContext(oldSelectedElement);
+		if (parentPart == null) {
+			// technically this shouldn't happen as there should be an MWindow somewhere
+			return;
+		}
+		IEclipseContext parentContext = parentPart.getContext();
+		IEclipseContext oldContext = getSubContext(oldSelectedElement);
+		Object child = parentContext.getActiveChild();
+		if (child == null || oldContext == null || child == oldContext) {
+			if (part == null) {
+				// TBD this should not be necessary; deactivation is missing somewhere
+				IEclipseContext currentActive = parentContext.getActiveChild();
+				if (currentActive != null)
+					currentActive.deactivate();
+			} else
+				part.getContext().activate();
+		}
+	}
+
+	@Override
+	public MPart findPart(String id) {
+		List<MPart> parts = getParts(MPart.class, id);
+		return parts.size() > 0 ? parts.get(0) : null;
+	}
+
+	private <T> List<T> getParts(Class<T> cls, String id) {
+		return modelService.findElements(workbenchWindow, id, cls, null,
+				EModelService.OUTSIDE_PERSPECTIVE | EModelService.IN_ACTIVE_PERSPECTIVE
+						| EModelService.IN_SHARED_AREA);
+	}
+
+	@Override
+	public Collection<MPart> getParts() {
+		return getParts(MPart.class, null);
+	}
+
+	@Override
+	public boolean isPartVisible(MPart part) {
+		if (isInContainer(part)) {
+			MUIElement element = part;
+			MElementContainer<?> parent = part.getParent();
+			if (parent == null) {
+				// might be a shared part
+				element = part.getCurSharedRef();
+				if (element == null) {
+					return false;
+				}
+
+				parent = element.getParent();
+				if (parent == null) {
+					return false;
+				}
+			}
+
+			if (parent instanceof MPartStack) {
+				return parent.getSelectedElement() == element;
+			}
+
+			return element.isVisible();
+		}
+		return false;
+	}
+
+	private boolean isInContainer(MUIElement element) {
+		if (modelService.isHostedElement(element, getWindow()))
+			return true;
+		List<MUIElement> allPerspectiveElements = modelService.findElements(workbenchWindow, null,
+				MUIElement.class, null, EModelService.PRESENTATION);
+		return allPerspectiveElements.contains(element);
+	}
+
+	boolean isInContainer(MElementContainer<?> container, MUIElement element) {
+		for (Object object : container.getChildren()) {
+			if (object == element) {
+				return true;
+			} else if (object instanceof MElementContainer<?>) {
+				if (isInContainer((MElementContainer<?>) object, element)) {
+					return true;
+				}
+			} else if (object instanceof MPlaceholder) {
+				MUIElement ref = ((MPlaceholder) object).getRef();
+				if (ref == element) {
+					return true;
+				} else if (ref instanceof MElementContainer<?>) {
+					if (isInContainer((MElementContainer<?>) ref, element)) {
+						return true;
+					}
+				}
+			} else if (object instanceof MPerspective) {
+				MPerspective persp = (MPerspective) object;
+				for (MWindow dw : persp.getWindows()) {
+					if (isInContainer(dw, element))
+						return true;
+				}
+			} else if (object instanceof MWindow) {
+				MWindow win = (MWindow) object;
+				for (MWindow dw : win.getWindows()) {
+					if (isInContainer(dw, element))
+						return true;
+				}
+			}
+		}
+
+		if (container instanceof MWindow) {
+			MWindow win = (MWindow) container;
+			for (MWindow dw : win.getWindows()) {
+				if (isInContainer(dw, element))
+					return true;
+			}
+		}
+
+		if (container instanceof MPerspective) {
+			MPerspective persp = (MPerspective) container;
+			for (MWindow dw : persp.getWindows()) {
+				if (isInContainer(dw, element))
+					return true;
+			}
+		}
+
+		return false;
+	}
+
+	MPlaceholder getLocalPlaceholder(MUIElement part) {
+		return modelService.findPlaceholderFor(getWindow(), part);
+	}
+
+	@Override
+	public boolean isPartOrPlaceholderInPerspective(String elementId, MPerspective perspective) {
+		List<MPart> findElements = modelService.findElements(perspective, elementId, MPart.class, null);
+		if (!findElements.isEmpty()) {
+			MPart part = findElements.get(0);
+
+			// if that is a shared part, check the placeholders
+			if (workbenchWindow.getSharedElements().contains(part)) {
+				List<MPlaceholder> placeholders = modelService.findElements(perspective, elementId,
+						MPlaceholder.class, null);
+				for (MPlaceholder mPlaceholder : placeholders) {
+					if (mPlaceholder.isVisible() && mPlaceholder.isToBeRendered()) {
+						return true;
+					}
+				}
+				return false;
+			}
+			// not a shared part
+			return part.isVisible() && part.isToBeRendered();
+		}
+		return false;
+	}
+
+	@Override
+	public void switchPerspective(MPerspective perspective) {
+		Assert.isNotNull(perspective);
+		MWindow window = getWindow();
+		if (window != null && isInContainer(window, perspective)) {
+			perspective.getParent().setSelectedElement(perspective);
+			List<MPart> newPerspectiveParts = modelService.findElements(perspective, null,
+					MPart.class, null);
+			// if possible, keep the same active part across perspective switches
+			if (newPerspectiveParts.contains(activePart)
+					&& partActivationHistory.isValid(perspective, activePart)) {
+				MPart target = activePart;
+				IEclipseContext activeChild = activePart.getContext().getParent().getActiveChild();
+				if (activeChild != null) {
+					activeChild.deactivate();
+				}
+				if (target.getContext() != null && target.getContext().get(MPerspective.class) != null
+						&& target.getContext().get(MPerspective.class).getContext() == perspective.getContext()) {
+					target.getContext().activateBranch();
+				} else {
+					perspective.getContext().activate();
+				}
+
+				modelService.bringToTop(target);
+				activate(target, true, false);
+				return;
+			}
+
+			MPart newActivePart = perspective.getContext().getActiveLeaf().get(MPart.class);
+			if (newActivePart == null) {
+				// whatever part was previously active can no longer be found, find another one
+				MPart candidate = partActivationHistory.getActivationCandidate(perspective);
+				if (candidate != null) {
+					modelService.bringToTop(candidate);
+					activate(candidate, true, false);
+					return;
+				}
+			}
+
+			// there seems to be no parts in this perspective, just activate it as is then
+			if (newActivePart == null) {
+				modelService.bringToTop(perspective);
+				perspective.getContext().activate();
+			} else {
+				if ((modelService.getElementLocation(newActivePart) & EModelService.IN_SHARED_AREA) != 0) {
+					if (newActivePart.getParent().getSelectedElement() != newActivePart) {
+						newActivePart = (MPart) newActivePart.getParent().getSelectedElement();
+					}
+				}
+				activate(newActivePart, true, false);
+			}
+		}
+	}
+
+	@Override
+	public void activate(MPart part) {
+		activate(part, true);
+	}
+
+	@Override
+	public void activate(MPart part, boolean requiresFocus) {
+		activate(part, requiresFocus, true);
+	}
+
+	private void activate(MPart part, boolean requiresFocus, boolean activateBranch) {
+		if (part == null) {
+			if (constructed && activePart != null) {
+				firePartDeactivated(activePart);
+			}
+			activePart = part;
+			return;
+		}
+
+		// Delegate activations to a CompositePart's inner part (if any)
+		if (part instanceof MCompositePart) {
+			if (part.getContext() != null) {
+				IEclipseContext pContext = part.getContext();
+				if (pContext.getActiveLeaf() != null) {
+					MPart inner = pContext.getActiveLeaf().get(MPart.class);
+					if (inner != null) {
+						part = inner;
+					}
+				}
+			}
+		}
+
+		// only activate parts that is under our control
+		if (!isInContainer(part)) {
+			return;
+		}
+
+		MWindow window = getWindow();
+		IEclipseContext windowContext = window.getContext();
+		// check if the active part has changed or if we are no longer the active window
+		if (windowContext.getParent().getActiveChild() == windowContext && part == activePart) {
+			// insert it in the beginning of the activation history, it may not have been inserted
+			// pending when this service was instantiated
+			partActivationHistory.prepend(part);
+			UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part);
+			return;
+		}
+		if (contextService != null) {
+			contextService.deferUpdates(true);
+		}
+		if (contextManager != null) {
+			contextManager.deferUpdates(true);
+		}
+
+		MPart lastActivePart = activePart;
+		activePart = part;
+
+		if (constructed && lastActivePart != null && lastActivePart != activePart) {
+			firePartDeactivated(lastActivePart);
+		}
+
+		try {
+			// record any sibling into the activation history if necessary, this will allow it to be
+			// reselected again in the future as it will be an activation candidate in the future,
+			// this
+			// prevents other unrendered elements from being selected arbitrarily which would cause
+			// unwanted bundle activation
+			recordStackActivation(part);
+
+			delegateBringToTop(part);
+			window.getParent().setSelectedElement(window);
+
+			partActivationHistory.activate(part, activateBranch);
+
+			if (requiresFocus) {
+				IPresentationEngine pe = part.getContext().get(IPresentationEngine.class);
+				pe.focusGui(part);
+			}
+
+			firePartActivated(part);
+			UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part);
+		} finally {
+			if (contextService != null) {
+				contextService.deferUpdates(false);
+			}
+			if (contextManager != null) {
+				contextManager.deferUpdates(false);
+			}
+		}
+	}
+
+	private void delegateBringToTop(MPart part) {
+		modelService.bringToTop(part);
+		createElement(part);
+	}
+
+	/**
+	 * Records the specified parent part's selected element in the activation history if the parent
+	 * is a stack.
+	 *
+	 * @param part
+	 *            the part whose parent's selected element should be checked for activation history
+	 *            recording
+	 */
+	private void recordStackActivation(MPart part) {
+		MElementContainer<? extends MUIElement> parent = part.getParent();
+		if (parent instanceof MGenericStack) {
+			recordSelectedActivation(parent);
+		} else if (parent == null) {
+			MPlaceholder placeholder = part.getCurSharedRef();
+			if (placeholder != null) {
+				parent = placeholder.getParent();
+				if (parent instanceof MGenericStack) {
+					recordSelectedActivation(parent);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Records the specified parent 's selected element in the activation history.
+	 *
+	 * @param parent
+	 *            the element whose selected element should be checked for activation history
+	 *            recording
+	 */
+	private void recordSelectedActivation(MElementContainer<? extends MUIElement> parent) {
+		MUIElement selectedElement = parent.getSelectedElement();
+		if (selectedElement instanceof MPart) {
+			partActivationHistory.append((MPart) selectedElement);
+		} else if (selectedElement instanceof MPlaceholder) {
+			MUIElement ref = ((MPlaceholder) selectedElement).getRef();
+			if (ref instanceof MPart) {
+				partActivationHistory.append((MPart) ref);
+			}
+		}
+	}
+
+	@Override
+	public MPart getActivePart() {
+		return activePart;
+	}
+
+	private MPart createPart(MPartDescriptor descriptor) {
+		if (descriptor == null) {
+			return null;
+		}
+		MPart part = modelService.createModelElement(MPart.class);
+		part.setElementId(descriptor.getElementId());
+		part.getMenus().addAll(EcoreUtil.copyAll(descriptor.getMenus()));
+		if (descriptor.getToolbar() != null) {
+			part.setToolbar((MToolBar) EcoreUtil.copy((EObject) descriptor.getToolbar()));
+		}
+		part.setContributorURI(descriptor.getContributorURI());
+		part.setCloseable(descriptor.isCloseable());
+		part.setContributionURI(descriptor.getContributionURI());
+		part.setLabel(descriptor.getLabel());
+		part.setIconURI(descriptor.getIconURI());
+		part.setTooltip(descriptor.getTooltip());
+		part.getHandlers().addAll(EcoreUtil.copyAll(descriptor.getHandlers()));
+		part.getTags().addAll(descriptor.getTags());
+		part.getPersistedState().putAll(descriptor.getPersistedState());
+		part.getBindingContexts().addAll(descriptor.getBindingContexts());
+		return part;
+	}
+
+	@Override
+	public MPart createPart(String id) {
+		MPartDescriptor descriptor = modelService.getPartDescriptor(id);
+		return createPart(descriptor);
+	}
+
+	@Override
+	public MPlaceholder createSharedPart(String id) {
+		return createSharedPart(id, false);
+	}
+
+	@Override
+	public MPlaceholder createSharedPart(String id, boolean force) {
+		MWindow sharedWindow = getWindow();
+		// Do we already have the part to share?
+		MPart sharedPart = null;
+
+		// check for existing parts if necessary
+		if (!force) {
+			for (MUIElement element : sharedWindow.getSharedElements()) {
+				if (element.getElementId().equals(id)) {
+					sharedPart = (MPart) element;
+					break;
+				}
+			}
+		}
+
+		if (sharedPart == null) {
+			MPartDescriptor descriptor = modelService.getPartDescriptor(id);
+			sharedPart = createPart(descriptor);
+			if (sharedPart == null) {
+				return null;
+			}
+
+			// Replace the id to ensure that multi-instance parts work correctly
+			sharedPart.setElementId(id);
+
+			sharedWindow.getSharedElements().add(sharedPart);
+		}
+
+		return createSharedPart(sharedPart);
+	}
+
+	private MPlaceholder createSharedPart(MPart sharedPart) {
+		// Create and return a reference to the shared part
+		MPlaceholder sharedPartRef = modelService.createModelElement(MPlaceholder.class);
+		sharedPartRef.setElementId(sharedPart.getElementId());
+		sharedPartRef.setRef(sharedPart);
+		return sharedPartRef;
+	}
+
+	/**
+	 * Adds a part to the current container if it isn't already in the container. The part may still
+	 * be added to the container if the part supports having multiple copies of itself in a given
+	 * container.
+	 *
+	 * @param providedPart
+	 *            the part to add
+	 * @param localPart
+	 *            a part that shares attributes with <code>providedPart</code>, for example, it may
+	 *            have been backed by the same part descriptor, this part may already be in the
+	 *            current container
+	 * @return a part that has been added to the current container, note that this may not
+	 *         necessarily be <code>providedPart</code>
+	 * @see MPartDescriptor#isAllowMultiple()
+	 */
+	private MPart addPart(MPart providedPart, MPart localPart) {
+		MPartDescriptor descriptor = modelService.getPartDescriptor(providedPart.getElementId());
+		if (descriptor == null) {
+			// there is no part descriptor backing the provided part, just add it to the container
+			// if it's not already there
+			if (!isInContainer(providedPart)) {
+				adjustPlaceholder(providedPart);
+				addToLastContainer(null, providedPart);
+			}
+		} else {
+			if (providedPart != localPart && !descriptor.isAllowMultiple()) {
+				// multiple copies of this part are not allowed, just return the local one
+				return localPart;
+			}
+
+			// already in the container, return as is
+			if (isInContainer(providedPart)) {
+				return providedPart;
+			}
+
+			// corrects this part's placeholder if necessary
+			adjustPlaceholder(providedPart);
+
+			String category = descriptor.getCategory();
+			if (category == null) {
+				// no category, just add it to the end
+				addToLastContainer(null, providedPart);
+			} else {
+				if ("org.eclipse.e4.primaryDataStack".equals(category)) { //$NON-NLS-1$
+					MElementContainer<? extends MUIElement> container = getContainer();
+					MUIElement area = modelService.find("org.eclipse.ui.editorss", container); //$NON-NLS-1$
+
+					MPartStack activeStack = null;
+					if (area instanceof MPlaceholder
+							&& ((MPlaceholder) area).getRef() instanceof MArea) {
+						// Find the currently 'active' stack in the area
+						MArea a = (MArea) ((MPlaceholder) area).getRef();
+						MUIElement curActive = a.getSelectedElement();
+						while (curActive instanceof MElementContainer<?>) {
+							if (curActive instanceof MPartStack) {
+								activeStack = (MPartStack) curActive;
+								break;
+							}
+							MElementContainer<?> curContainer = (MElementContainer<?>) curActive;
+							curActive = curContainer.getSelectedElement();
+						}
+					}
+
+					if (activeStack != null) {
+						activeStack.getChildren().add(providedPart);
+					} else {
+						// Find the first visible stack in the area
+						List<MPartStack> sharedStacks = modelService.findElements(area, null,
+								MPartStack.class, null);
+						if (sharedStacks.size() > 0) {
+							for (MPartStack stack : sharedStacks) {
+								if (stack.isToBeRendered()) {
+									stack.getChildren().add(providedPart);
+									break;
+								}
+							}
+						} else {
+							addToLastContainer(null, providedPart);
+						}
+					}
+				} else {
+					@SuppressWarnings("rawtypes")
+					List<MElementContainer> containers = modelService.findElements(getContainer(),
+							null, MElementContainer.class, Collections.singletonList(category),
+							EModelService.PRESENTATION);
+					if (containers.isEmpty()) {
+						// couldn't find any containers with the specified tag, just add it to the
+						// end
+						addToLastContainer(category, providedPart);
+					} else {
+						// add the part to the container
+						MElementContainer<MPartSashContainerElement> container = containers.get(0);
+						MPlaceholder placeholder = providedPart.getCurSharedRef();
+						if (placeholder == null) {
+							container.getChildren().add(providedPart);
+						} else {
+							container.getChildren().add(placeholder);
+						}
+					}
+				}
+			}
+		}
+		return providedPart;
+	}
+
+	private void adjustPlaceholder(MPart part) {
+		if (isShared(part)) {
+			MPlaceholder placeholder = part.getCurSharedRef();
+			// if this part doesn't have any placeholders, we need to make one
+			if (placeholder == null
+			// alternatively, if it has one but it's not in the current container, then we
+			// need to spawn another one as we don't want to reuse the same one and end up
+			// shifting that placeholder to the current container during the add operation
+					|| (placeholder.getParent() != null && !isInContainer(placeholder))) {
+				placeholder = createSharedPart(part);
+				part.setCurSharedRef(placeholder);
+			}
+		}
+	}
+
+	private boolean isShared(MPart part) {
+		return getWindow().getSharedElements().contains(part);
+	}
+
+	private void addToLastContainer(String category, MPart part) {
+		// OK, we haven't found an explicit placeholder;
+		// If this is a multi-instance view see if there's a 'global' placeholder
+		String partId = part.getElementId();
+		int colonIndex = partId == null ? -1 : partId.indexOf(':');
+		if (colonIndex >= 0) {
+			String descId = part.getElementId().substring(0, colonIndex);
+			descId += ":*"; //$NON-NLS-1$
+			List<MPlaceholder> phList = modelService.findElements(workbenchWindow, descId,
+					MPlaceholder.class, null, EModelService.PRESENTATION);
+			if (phList.size() > 0) {
+				MUIElement phParent = phList.get(0).getParent();
+				if (phParent instanceof MPartStack) {
+					MPartStack theStack = (MPartStack) phParent;
+					int phIndex = theStack.getChildren().indexOf(phList.get(0));
+					adjustPlaceholder(part);
+					MPlaceholder placeholder = part.getCurSharedRef();
+					if (placeholder == null) {
+						theStack.getChildren().add(phIndex, part);
+					} else {
+						theStack.getChildren().add(phIndex, placeholder);
+					}
+					return;
+				}
+			}
+		}
+
+		@SuppressWarnings("unchecked")
+		MElementContainer<MUIElement> lastContainer = (MElementContainer<MUIElement>) getLastContainer();
+		MPlaceholder placeholder = part.getCurSharedRef();
+		if (placeholder == null) {
+			lastContainer.getChildren().add(part);
+		} else {
+			lastContainer.getChildren().add(placeholder);
+		}
+
+		if (category != null) {
+			lastContainer.getTags().add(category);
+		}
+	}
+
+	private MElementContainer<? extends MUIElement> getLastContainer() {
+		MElementContainer<? extends MUIElement> searchRoot = getContainer();
+		@SuppressWarnings("unchecked")
+		List<MUIElement> children = (List<MUIElement>) searchRoot.getChildren();
+		if (children.size() == 0) {
+			MPartStack stack = modelService.createModelElement(MPartStack.class);
+			children.add(stack);
+			return stack;
+		}
+
+		MElementContainer<?> lastContainer = getLastContainer(searchRoot, children);
+		if (lastContainer instanceof MPartStack) {
+			return lastContainer;
+		}
+
+		// No stacks found make one and add it
+		MPartStack stack = modelService.createModelElement(MPartStack.class);
+		stack.setElementId("CreatedByGetLastContainer"); //$NON-NLS-1$
+		if (children.get(0) instanceof MPartSashContainer) {
+			MPartSashContainer psc = (MPartSashContainer) children.get(0);
+			psc.getChildren().add(stack);
+		} else {
+			// We need a sash so 'insert' the new stack
+			modelService.insert(stack, (MPartSashContainerElement) children.get(0),
+					EModelService.RIGHT_OF, 0.5f);
+		}
+		return stack;
+	}
+
+	private MElementContainer<? extends MUIElement> getLastContainer(MElementContainer<?> container, List<?> children) {
+		if (children.isEmpty()) {
+			return null;
+		}
+
+		for (int i = children.size() - 1; i > -1; i--) {
+			Object muiElement = children.get(i);
+			if (muiElement instanceof MElementContainer<?>) {
+				MElementContainer<?> childContainer = (MElementContainer<?>) muiElement;
+				MElementContainer<?> lastContainer = getLastContainer(childContainer,
+						childContainer.getChildren());
+				if (lastContainer != null) {
+					return lastContainer;
+				}
+			}
+		}
+		return container;
+	}
+
+	/**
+	 * Returns the parent container of the specified element. If one cannot be found, a check will
+	 * be performed to see whether the element is being represented by a placeholder, if it is, the
+	 * placeholder's parent will be returned, if any.
+	 *
+	 * @param element
+	 *            the element to query
+	 * @return the element's parent container, or the parent container of the specified element's
+	 *         current placeholder, if it has one
+	 */
+	private MElementContainer<MUIElement> getParent(MUIElement element) {
+		MElementContainer<MUIElement> parent = element.getParent();
+		if (parent == null) {
+			MPlaceholder placeholder = element.getCurSharedRef();
+			if (placeholder == null) {
+				@SuppressWarnings("unchecked")
+				MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) getContainer();
+				return findContainer(container, element);
+			}
+			return placeholder.getParent();
+		}
+		return parent;
+	}
+
+	private MElementContainer<MUIElement> findContainer(MElementContainer<MUIElement> container,
+			MUIElement element) {
+		for (MUIElement child : container.getChildren()) {
+			if (child == element) {
+				return container;
+			} else if (child instanceof MPlaceholder) {
+				MPlaceholder placeholder = (MPlaceholder) child;
+				MUIElement ref = placeholder.getRef();
+				if (ref == element) {
+					return container;
+				} else if (ref instanceof MElementContainer<?>) {
+					@SuppressWarnings("unchecked")
+					MElementContainer<MUIElement> ref2 = (MElementContainer<MUIElement>) ref;
+					MElementContainer<MUIElement> match = findContainer(ref2, element);
+					if (match != null) {
+						return match;
+					}
+				}
+			} else if (child instanceof MElementContainer<?>) {
+				@SuppressWarnings("unchecked")
+				MElementContainer<MUIElement> child2 = (MElementContainer<MUIElement>) child;
+				MElementContainer<MUIElement> match = findContainer(child2, element);
+				if (match != null) {
+					return match;
+				}
+			}
+		}
+		return null;
+	}
+
+	private MUIElement getRemoveTarget(MPart part) {
+		MPlaceholder placeholder = getLocalPlaceholder(part);
+		return placeholder == null ? part : placeholder;
+	}
+
+	public MPart addPart(MPart part) {
+		Assert.isNotNull(part);
+		MPart localPart = findPart(part.getElementId());
+		return addPart(part, localPart == null ? part : localPart);
+	}
+
+	@Override
+	public MPart showPart(String id, PartState partState) {
+		Assert.isNotNull(id);
+		Assert.isNotNull(partState);
+
+		MPart part = findPart(id);
+		if (part == null) {
+			MPartDescriptor descriptor = modelService.getPartDescriptor(id);
+			part = createPart(descriptor);
+			if (part == null) {
+				return null;
+			}
+		}
+		return showPart(addPart(part), partState);
+	}
+
+	@Override
+	public MPart showPart(MPart part, PartState partState) {
+		Assert.isNotNull(part);
+		Assert.isNotNull(partState);
+
+		MPart addedPart = addPart(part);
+		MPlaceholder localPlaceholder = getLocalPlaceholder(addedPart);
+		// correct the placeholder setting if necessary
+		if (localPlaceholder != null && addedPart.getCurSharedRef() != localPlaceholder) {
+			addedPart.setCurSharedRef(localPlaceholder);
+		}
+
+		switch (partState) {
+		case ACTIVATE:
+			activate(addedPart);
+			return addedPart;
+		case VISIBLE:
+			MPart activePart = getActivePart();
+			if (activePart == null
+					|| (activePart != addedPart && getParent(activePart) == getParent(addedPart))) {
+				delegateBringToTop(addedPart);
+				activate(addedPart);
+			} else {
+				bringToTop(addedPart);
+			}
+			return addedPart;
+		case CREATE:
+			createElement(addedPart);
+			return addedPart;
+		}
+		return addedPart;
+	}
+
+	private void createElement(MUIElement element) {
+		if (modelService.isHostedElement(element, workbenchWindow)) {
+			// assume the client has full control
+			return;
+		}
+
+		MPlaceholder placeholder = element.getCurSharedRef();
+		if (placeholder != null) {
+			element.setToBeRendered(true);
+			element = placeholder;
+		}
+
+		// render this element
+		element.setToBeRendered(true);
+
+		// render all of its parents
+		MUIElement parentWindow = workbenchWindow;
+		// determine the top parent that needs to be forcibly created
+		MUIElement target = null;
+		MElementContainer<MUIElement> parent = element.getParent();
+		while (parent != null && parent != parentWindow) {
+			parent.setToBeRendered(true);
+			if (parent.getWidget() == null) {
+				target = parent;
+			}
+			parent = parent.getParent();
+		}
+		if (target != null) {
+			// force the element's parent hierarchy to be created
+			engine.createGui(target);
+		}
+		// ask the engine to create the element
+		if (element.getWidget() == null)
+			engine.createGui(element);
+
+		parent = element.getParent();
+		if (parent != null && parent.getChildren().size() == 1) {
+			// if we're the only child, set ourselves as the selected element
+			parent.setSelectedElement(element);
+		}
+	}
+
+	@Override
+	public void requestActivation() {
+		if (activePart == null) {
+			MPart candidate = partActivationHistory.getActivationCandidate(getParts());
+			if (candidate != null) {
+				activate(candidate);
+			}
+		} else if (!partActivationHistory.isValid(activePart) || !getParts().contains(activePart)) {
+			MPart candidate = partActivationHistory.getNextActivationCandidate(getParts(),
+					activePart);
+			if (candidate != null) {
+				activate(candidate);
+			}
+		}
+	}
+
+	@Override
+	public void hidePart(MPart part) {
+		hidePart(part, false);
+	}
+
+	@Override
+	public void hidePart(MPart part, boolean force) {
+		if (isInContainer(part)) {
+			MPlaceholder sharedRef = part.getCurSharedRef();
+			MUIElement toBeRemoved = getRemoveTarget(part);
+			MElementContainer<MUIElement> parent = getParent(toBeRemoved);
+			List<MUIElement> children = parent.getChildren();
+
+			// check if we're a placeholder but not actually the shared ref of the part
+			if (toBeRemoved != part && toBeRemoved instanceof MPlaceholder
+					&& sharedRef != toBeRemoved) {
+				toBeRemoved.setToBeRendered(false);
+
+				// if so, not much to do, remove ourselves if necessary but that's it
+				if (force || part.getTags().contains(REMOVE_ON_HIDE_TAG)) {
+					parent.getChildren().remove(toBeRemoved);
+				}
+				return;
+			}
+
+			boolean isActiveChild = isActiveChild(part);
+			MPart activationCandidate = null;
+			// check if we're the active child
+			if (isActiveChild) {
+				// get the activation candidate if we are
+				activationCandidate = partActivationHistory.getNextActivationCandidate(getParts(),
+						part);
+			}
+
+			MPerspective thePersp = modelService.getPerspectiveFor(toBeRemoved);
+			boolean needNewSel = thePersp == null || !thePersp.getTags().contains("PerspClosing"); //$NON-NLS-1$
+			if (needNewSel) {
+				if (parent.getSelectedElement() == toBeRemoved) {
+					// if we're the selected element and we're going to be hidden, need to select
+					// something else
+					MUIElement candidate = partActivationHistory.getSiblingSelectionCandidate(part);
+					candidate = candidate == null ? null
+							: candidate.getCurSharedRef() == null ? candidate : candidate
+									.getCurSharedRef();
+					if (candidate != null && children.contains(candidate)) {
+						parent.setSelectedElement(candidate);
+					} else {
+						for (MUIElement child : children) {
+							if (child != toBeRemoved && child.isToBeRendered()) {
+								parent.setSelectedElement(child);
+								break;
+							}
+						}
+					}
+				}
+
+				if (activationCandidate == null) {
+					// nothing else to activate and we're the active child, deactivate
+					if (isActiveChild) {
+						part.getContext().deactivate();
+					}
+				} else {
+					// activate our candidate
+					activate(activationCandidate);
+				}
+			}
+
+			if (toBeRemoved != null) {
+				toBeRemoved.setToBeRendered(false);
+			} else {
+				part.setToBeRendered(false);
+			}
+
+			if (parent.getSelectedElement() == toBeRemoved) {
+				parent.setSelectedElement(null);
+			}
+
+			if (force || part.getTags().contains(REMOVE_ON_HIDE_TAG)) {
+				children.remove(toBeRemoved);
+			}
+			// remove ourselves from the activation history also since we're being hidden
+			partActivationHistory.forget(getWindow(), part, toBeRemoved == part);
+		}
+	}
+
+	private boolean isActiveChild(MPart part) {
+		IEclipseContext context = part.getContext();
+		return context != null && context.getParent().getActiveChild() == context;
+	}
+
+	@Override
+	public Collection<MPart> getDirtyParts() {
+		List<MPart> dirtyParts = new ArrayList<MPart>();
+		for (MPart part : getParts()) {
+			if (part.isDirty()) {
+				dirtyParts.add(part);
+			}
+		}
+		return dirtyParts;
+	}
+
+	@Override
+	public boolean savePart(MPart part, boolean confirm) {
+		if (!part.isDirty()) {
+			return true;
+		}
+
+		if (saveHandler != null) {
+			return saveHandler.save(part, confirm);
+		}
+
+		Object client = part.getObject();
+		try {
+			ContextInjectionFactory.invoke(client, Persist.class, part.getContext());
+		} catch (InjectionException e) {
+			log("Failed to persist contents of part", "Failed to persist contents of part ({0})", //$NON-NLS-1$ //$NON-NLS-2$
+					part.getElementId(), e);
+			return false;
+		} catch (RuntimeException e) {
+			log("Failed to persist contents of part via DI", //$NON-NLS-1$
+					"Failed to persist contents of part ({0}) via DI", part.getElementId(), e); //$NON-NLS-1$
+			return false;
+		}
+		return true;
+	}
+
+	@Override
+	public boolean saveAll(boolean confirm) {
+		Collection<MPart> dirtyParts = getDirtyParts();
+		if (dirtyParts.isEmpty()) {
+			return true;
+		}
+		if (saveHandler != null) {
+			return saveHandler.saveParts(dirtyParts, confirm);
+		}
+
+		for (MPart dirtyPart : dirtyParts) {
+			if (!savePart(dirtyPart, false)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public Collection<MInputPart> getInputParts(String inputUri) {
+		Assert.isNotNull(inputUri, "Input uri must not be null"); //$NON-NLS-1$
+
+		Collection<MInputPart> rv = new ArrayList<MInputPart>();
+
+		for (MInputPart p : getParts(MInputPart.class, null)) {
+			if (inputUri.equals(p.getInputURI())) {
+				rv.add(p);
+			}
+		}
+
+		return rv;
+	}
+
+	/**
+	 * "Container" here is: 1) a selected MPerspective, or, if none available 2) the MWindow for
+	 * which this part service is created, or, if not available, 3) the MApplication.
+	 */
+	private MElementContainer<? extends MUIElement> getContainer() {
+		MElementContainer<? extends MUIElement> outerContainer = (workbenchWindow != null) ? workbenchWindow
+				: application;
+
+		// see if we can narrow it down to the active perspective
+		for (MElementContainer<? extends MUIElement> container = outerContainer; container != null;) {
+			if (container instanceof MPerspective) {
+				return container;
+			}
+			Object child = container.getSelectedElement();
+			if (child == null) {
+				break;
+			}
+			if (child instanceof MElementContainer<?>) {
+				container = (MElementContainer<?>) child;
+			} else {
+				break;
+			}
+		}
+		return outerContainer;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java
new file mode 100644
index 0000000..4215340
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.di.InjectionException;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.modeling.ISaveHandler;
+import org.eclipse.osgi.util.NLS;
+
+public class PartServiceSaveHandler implements ISaveHandler {
+
+	public Logger logger;
+
+	private void log(String unidentifiedMessage, String identifiedMessage, String id, Exception e) {
+		if (logger == null) {
+			return;
+		}
+		if (id == null || id.length() == 0) {
+			logger.error(e, unidentifiedMessage);
+		} else {
+			logger.error(e, NLS.bind(identifiedMessage, id));
+		}
+	}
+
+	@Override
+	public boolean save(MPart dirtyPart, boolean confirm) {
+		if (confirm) {
+			switch (promptToSave(dirtyPart)) {
+			case NO:
+				return true;
+			case CANCEL:
+				return false;
+			case YES:
+				break;
+			}
+		}
+
+		Object client = dirtyPart.getObject();
+		try {
+			ContextInjectionFactory.invoke(client, Persist.class, dirtyPart.getContext());
+		} catch (InjectionException e) {
+			log("Failed to persist contents of part", "Failed to persist contents of part ({0})", //$NON-NLS-1$ //$NON-NLS-2$
+					dirtyPart.getElementId(), e);
+			return false;
+		} catch (RuntimeException e) {
+			log("Failed to persist contents of part via DI", //$NON-NLS-1$
+					"Failed to persist contents of part ({0}) via DI", dirtyPart.getElementId(), e); //$NON-NLS-1$
+			return false;
+		}
+		return true;
+	}
+
+	@Override
+	public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) {
+		if (confirm) {
+			List<MPart> dirtyPartsList = Collections.unmodifiableList(new ArrayList<MPart>(
+					dirtyParts));
+			Save[] decisions = promptToSave(dirtyPartsList);
+			for (Save decision : decisions) {
+				if (decision == Save.CANCEL) {
+					return false;
+				}
+			}
+
+			for (int i = 0; i < decisions.length; i++) {
+				if (decisions[i] == Save.YES) {
+					if (!save(dirtyPartsList.get(i), false)) {
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+
+		for (MPart dirtyPart : dirtyParts) {
+			if (!save(dirtyPart, false)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public Save promptToSave(MPart dirtyPart) {
+		return Save.YES;
+	}
+
+	@Override
+	public Save[] promptToSave(Collection<MPart> dirtyParts) {
+		Save[] rc = new Save[dirtyParts.size()];
+		for (int i = 0; i < rc.length; i++) {
+			rc[i] = Save.YES;
+		}
+		return rc;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PlaceholderResolver.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PlaceholderResolver.java
new file mode 100644
index 0000000..83e718a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PlaceholderResolver.java
@@ -0,0 +1,86 @@
+/*******************************************************************************

+ * Copyright (c) 2011 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.internal.workbench;

+

+import java.util.List;

+import org.eclipse.core.runtime.Assert;

+import org.eclipse.e4.ui.model.application.MApplication;

+import org.eclipse.e4.ui.model.application.ui.MUIElement;

+import org.eclipse.e4.ui.model.application.ui.advanced.MArea;

+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;

+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedFactoryImpl;

+import org.eclipse.e4.ui.model.application.ui.basic.MPart;

+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;

+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;

+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl;

+import org.eclipse.e4.ui.workbench.modeling.EPartService;

+import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;

+

+/**

+ * Default implementation of a resolver that expects the id of the placeholder to match the id of a

+ * PartDescriptor. It will create an MPart from the descriptor and add it to the appropriate

+ * window'w 'sharedElementList' if necessary.

+ */

+public class PlaceholderResolver implements EPlaceholderResolver {

+

+	@Override

+	public void resolvePlaceholderRef(MPlaceholder ph, MWindow refWin) {

+		if (ph.getRef() != null)

+			return;

+

+		// Must give us the window that you are resolving for...

+		Assert.isLegal(refWin != null);

+

+		// ..and it must be a 'top level' window

+		MUIElement refParent = refWin.getParent();

+		Assert.isLegal(refParent instanceof MApplication);

+

+		// So we already have a matching shared element ?

+		List<MUIElement> sharedElements = refWin.getSharedElements();

+		for (MUIElement se : sharedElements) {

+			if (ph.getElementId().equals(se.getElementId())) {

+				ph.setRef(se);

+				return;

+			}

+		}

+

+		// Hack to make the 3.x compatibility layer work

+		if (ph.getElementId().equals("org.eclipse.ui.editorss")) { //$NON-NLS-1$

+			// This code is for the eclipse compatibility layer...

+			MArea sharedArea = AdvancedFactoryImpl.eINSTANCE.createArea();

+			// sharedArea.setLabel("Editor Area"); //$NON-NLS-1$

+

+			MPartStack editorStack = BasicFactoryImpl.eINSTANCE.createPartStack();

+			editorStack.getTags().add("org.eclipse.e4.primaryDataStack"); //$NON-NLS-1$

+			editorStack.getTags().add("EditorStack"); //$NON-NLS-1$

+			editorStack.setElementId("org.eclipse.e4.primaryDataStack"); //$NON-NLS-1$

+			sharedArea.getChildren().add(editorStack);

+			sharedArea.setElementId(ph.getElementId());

+

+			refWin.getSharedElements().add(sharedArea);

+			ph.setRef(sharedArea);

+			return;

+		}

+

+		// Assume that the placeholder is to a shared 'part'

+		EPartService ps = refWin.getContext().get(EPartService.class);

+		MPart newReferencedPart = ps.createPart(ph.getElementId());

+		if (newReferencedPart != null) {

+			refWin.getSharedElements().add(newReferencedPart);

+			ph.setRef(newReferencedPart);

+			return;

+		}

+

+		// SHould we log / show an exception here ?

+	}

+

+}

diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Policy.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Policy.java
new file mode 100644
index 0000000..09d30bf
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Policy.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+/**
+ * A common facility for parsing the
+ * <code>org.eclipse.e4.ui.workbench/.options</code> file.
+ *
+ */
+public class Policy {
+	public static final String DEBUG = "/debug"; //$NON-NLS-1$
+	public static final String DEBUG_CMDS = "/trace/commands"; //$NON-NLS-1$
+	public static final String DEBUG_MENUS = "/trace/menus"; //$NON-NLS-1$
+	public static final String DEBUG_CONTEXTS = "/trace/eclipse.context"; //$NON-NLS-1$
+	public static final String DEBUG_CONTEXTS_VERBOSE = "/trace/eclipse.context.verbose"; //$NON-NLS-1$
+	public static final String DEBUG_WORKBENCH = "/trace/workbench"; //$NON-NLS-1$
+	public static final String DEBUG_RENDERER = "/trace/renderer"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ProgressMonitorFunction.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ProgressMonitorFunction.java
new file mode 100644
index 0000000..8a39997
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ProgressMonitorFunction.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+/**
+ * This class provides a context function that returns a default progress monitor. This is generally
+ * used near the root of a context tree to provide a reasonable default monitor for cases where more
+ * specific contexts have not provided one.
+ */
+public class ProgressMonitorFunction extends ContextFunction {
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		return new NullProgressMonitor();
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ReflectionContributionFactory.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ReflectionContributionFactory.java
new file mode 100644
index 0000000..b7ebb30
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ReflectionContributionFactory.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.InjectionException;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.contributions.IContributionFactorySpi;
+import org.eclipse.emf.common.util.URI;
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.LogService;
+
+/**
+ * Create the contribution factory.
+ */
+public class ReflectionContributionFactory implements IContributionFactory {
+
+	private IExtensionRegistry registry;
+	private Map<String, Object> languages;
+
+	/**
+	 * Create a reflection factory.
+	 *
+	 * @param registry
+	 *            to read languages.
+	 */
+	public ReflectionContributionFactory(IExtensionRegistry registry) {
+		this.registry = registry;
+		processLanguages();
+	}
+
+	@Override
+	public Object create(String uriString, IEclipseContext context, IEclipseContext staticContext) {
+		return doCreate(uriString, context, staticContext);
+	}
+
+	@Override
+	public Object create(String uriString, IEclipseContext context) {
+		return doCreate(uriString, context, null);
+	}
+
+	private Object doCreate(String uriString, IEclipseContext context, IEclipseContext staticContext) {
+		if (uriString == null) {
+			return null;
+		}
+		// translate old-style platform:/plugin/ class specifiers into new-style bundleclass:// URIs
+		if (uriString.startsWith("platform:/plugin/")) { //$NON-NLS-1$
+			Activator.log(LogService.LOG_ERROR,
+					"platform-style URIs deprecated for referencing types: " + uriString); //$NON-NLS-1$
+			uriString = uriString.replace("platform:/plugin/", "bundleclass://"); //$NON-NLS-1$ //$NON-NLS-2$
+			Activator.log(LogService.LOG_ERROR, "URI rewritten as: " + uriString); //$NON-NLS-1$
+		}
+		URI uri = URI.createURI(uriString);
+		Bundle bundle = getBundle(uri);
+		Object contribution;
+		if (bundle != null) {
+			contribution = createFromBundle(bundle, context, staticContext, uri);
+		} else {
+			contribution = null;
+			Activator.log(LogService.LOG_ERROR, "Unable to retrieve the bundle from the URI: " //$NON-NLS-1$
+					+ uriString);
+		}
+		return contribution;
+	}
+
+	protected Object createFromBundle(Bundle bundle, IEclipseContext context,
+			IEclipseContext staticContext, URI uri) {
+		Object contribution;
+		if (uri.segmentCount() > 1) {
+			String prefix = uri.segment(0);
+			IContributionFactorySpi factory = (IContributionFactorySpi) languages.get(prefix);
+			if (factory == null) {
+				String message = "Unsupported contribution factory type '" + prefix + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+				Activator.log(LogService.LOG_ERROR, message);
+				return null;
+			}
+			StringBuffer resource = new StringBuffer(uri.segment(1));
+			for (int i = 2; i < uri.segmentCount(); i++) {
+				resource.append('/');
+				resource.append(uri.segment(i));
+			}
+			contribution = factory.create(bundle, resource.toString(), context);
+		} else {
+			String clazz = uri.segment(0);
+			try {
+				Class<?> targetClass = bundle.loadClass(clazz);
+				if (staticContext == null)
+					contribution = ContextInjectionFactory.make(targetClass, context);
+				else
+					contribution = ContextInjectionFactory
+							.make(targetClass, context, staticContext);
+
+				if (contribution == null) {
+					String message = "Unable to load class '" + clazz + "' from bundle '" //$NON-NLS-1$ //$NON-NLS-2$
+							+ bundle.getBundleId() + "'"; //$NON-NLS-1$
+					Activator.log(LogService.LOG_ERROR, message, new Exception());
+				}
+			} catch (ClassNotFoundException e) {
+				contribution = null;
+				String message = "Unable to load class '" + clazz + "' from bundle '" //$NON-NLS-1$ //$NON-NLS-2$
+						+ bundle.getBundleId() + "'"; //$NON-NLS-1$
+				Activator.log(LogService.LOG_ERROR, message, e);
+			} catch (InjectionException e) {
+				contribution = null;
+				String message = "Unable to create class '" + clazz + "' from bundle '" //$NON-NLS-1$ //$NON-NLS-2$
+						+ bundle.getBundleId() + "'"; //$NON-NLS-1$
+				Activator.log(LogService.LOG_ERROR, message, e);
+			}
+		}
+		return contribution;
+	}
+
+	protected void processLanguages() {
+		languages = new HashMap<String, Object>();
+		String extId = "org.eclipse.e4.languages"; //$NON-NLS-1$
+		IConfigurationElement[] languageElements = registry.getConfigurationElementsFor(extId);
+		for (int i = 0; i < languageElements.length; i++) {
+			IConfigurationElement languageElement = languageElements[i];
+			try {
+				languages.put(languageElement.getAttribute("name"), //$NON-NLS-1$
+						languageElement.createExecutableExtension("contributionFactory")); //$NON-NLS-1$
+			} catch (InvalidRegistryObjectException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (CoreException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+	}
+
+	protected Bundle getBundle(URI platformURI) {
+		if (platformURI.authority() == null) {
+			Activator.log(LogService.LOG_ERROR, "Failed to get bundle for: " + platformURI); //$NON-NLS-1$
+			return null;
+		}
+		return Activator.getDefault().getBundleForName(platformURI.authority());
+	}
+
+	@Override
+	public Bundle getBundle(String uriString) {
+		URI uri = URI.createURI(uriString);
+		return getBundle(uri);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/RenderedElementUtil.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/RenderedElementUtil.java
new file mode 100644
index 0000000..d52ad64
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/RenderedElementUtil.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.workbench;
+
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+
+/**
+ * Utility class that encapsulates the representation of 'rendered' menu and tool bar elements in
+ * the model.
+ */
+public class RenderedElementUtil {
+
+	/**
+	 * A tag value that indicates a menu, menu item or tool item is 'rendered'
+	 */
+	private static final String RENDERED_TAG = "Rendered"; //$NON-NLS-1$
+
+	/**
+	 * A transient data key for a rendered element's 'contribution manager'.
+	 */
+	private static final String CONTRIBUTION_MANAGER_KEY = "ContributionManager"; //$NON-NLS-1$
+
+	/**
+	 * Create a 'rendered' menu instance
+	 *
+	 * @return the new instance
+	 */
+	public static MMenu createRenderedMenu() {
+		final MMenu object = MMenuFactory.INSTANCE.createMenu();
+		object.getTags().add(RENDERED_TAG);
+		return object;
+
+	}
+
+	/**
+	 * Create a 'rendered' menu item instance
+	 *
+	 * @return the new instance
+	 */
+	public static MMenuItem createRenderedMenuItem() {
+		final MDirectMenuItem object = MMenuFactory.INSTANCE.createDirectMenuItem();
+		object.getTags().add(RENDERED_TAG);
+		return object;
+	}
+
+	/**
+	 * Create a 'rendered' tool bar instance
+	 *
+	 * @return the new instance
+	 */
+	public static MToolBar createRenderedToolBar() {
+		final MToolBar object = MMenuFactory.INSTANCE.createToolBar();
+		object.getTags().add(RENDERED_TAG);
+		return object;
+	}
+
+	/**
+	 * Return the contribution manager value for the 'rendered' element.
+	 *
+	 * @param element
+	 *            a rendered element.
+	 * @return the contribution manager or <code>null</code>
+	 */
+	public static Object getContributionManager(MUIElement element) {
+		return element.getTransientData().get(CONTRIBUTION_MANAGER_KEY);
+	}
+
+	/**
+	 * Test whether the UI element is an 'rendered' menu.
+	 *
+	 * @param element
+	 *            the UI element
+	 * @return <code>true</code> if the element is a 'rendered' menu
+	 */
+	public static boolean isRenderedMenu(MUIElement element) {
+		return element instanceof MMenu && element.getTags().contains(RENDERED_TAG);
+	}
+
+	/**
+	 * Test whether the UI element is a 'rendered' menu item.
+	 *
+	 * @param element
+	 *            a UI element
+	 * @return <code>true</code> if the element is a 'rendered' menu item
+	 */
+	public static boolean isRenderedMenuItem(MUIElement element) {
+		return element instanceof MDirectMenuItem && element.getTags().contains(RENDERED_TAG);
+	}
+
+	/**
+	 * Set the contribution manager value for a 'rendered' element.
+	 *
+	 * @param element
+	 *            a rendered element
+	 * @param contributionManager
+	 *            a contribution manager
+	 */
+	public static void setContributionManager(MUIElement element, Object contributionManager) {
+		element.getTransientData().put(CONTRIBUTION_MANAGER_KEY, contributionManager);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java
new file mode 100644
index 0000000..285e149
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java
@@ -0,0 +1,402 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Tristan Hume - <trishume@gmail.com> -
+ *     		Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting
+ *     		Implemented workbench auto-save to correctly restore state in case of crash.
+ *     Terry Parker <tparker@google.com> - Bug 416673
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.eclipse.core.internal.runtime.PlatformURLPluginConnection;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.commands.impl.CommandsPackageImpl;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+import org.eclipse.e4.ui.workbench.IModelResourceHandler;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.modeling.IModelReconcilingService;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.e4.ui.workbench.modeling.ModelReconciler;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.Bundle;
+import org.w3c.dom.Document;
+
+/**
+ * This class is responsible to load and save the model
+ */
+public class ResourceHandler implements IModelResourceHandler {
+
+	private ResourceSetImpl resourceSetImpl;
+	private Resource resource;
+
+	@Inject
+	private Logger logger;
+
+	@Inject
+	private IEclipseContext context;
+
+	@Inject
+	@Named(E4Workbench.INITIAL_WORKBENCH_MODEL_URI)
+	private URI applicationDefinitionInstance;
+
+	@Inject
+	@Optional
+	@Named(E4Workbench.INSTANCE_LOCATION)
+	private Location instanceLocation;
+
+	/**
+	 * Dictates whether the model should be stored using EMF or with the merging algorithm.
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=295524
+	 *
+	 */
+	final private boolean deltaRestore;
+	final private boolean saveAndRestore;
+	final private boolean clearPersistedState;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param saveAndRestore
+	 * @param clearPersistedState
+	 * @param deltaRestore
+	 */
+	@Inject
+	public ResourceHandler(@Named(IWorkbench.PERSIST_STATE) boolean saveAndRestore,
+			@Named(IWorkbench.CLEAR_PERSISTED_STATE) boolean clearPersistedState,
+			@Named(E4Workbench.DELTA_RESTORE) boolean deltaRestore) {
+		this.saveAndRestore = saveAndRestore;
+		this.clearPersistedState = clearPersistedState;
+		this.deltaRestore = deltaRestore;
+	}
+
+	@PostConstruct
+	void init() {
+		resourceSetImpl = new ResourceSetImpl();
+		resourceSetImpl.getResourceFactoryRegistry().getExtensionToFactoryMap()
+				.put(Resource.Factory.Registry.DEFAULT_EXTENSION, new E4XMIResourceFactory());
+
+		resourceSetImpl.getPackageRegistry().put(ApplicationPackageImpl.eNS_URI,
+				ApplicationPackageImpl.eINSTANCE);
+		resourceSetImpl.getPackageRegistry().put(CommandsPackageImpl.eNS_URI,
+				CommandsPackageImpl.eINSTANCE);
+		resourceSetImpl.getPackageRegistry().put(UiPackageImpl.eNS_URI, UiPackageImpl.eINSTANCE);
+		resourceSetImpl.getPackageRegistry()
+				.put(MenuPackageImpl.eNS_URI, MenuPackageImpl.eINSTANCE);
+		resourceSetImpl.getPackageRegistry().put(BasicPackageImpl.eNS_URI,
+				BasicPackageImpl.eINSTANCE);
+		resourceSetImpl.getPackageRegistry().put(AdvancedPackageImpl.eNS_URI,
+				AdvancedPackageImpl.eINSTANCE);
+		resourceSetImpl
+				.getPackageRegistry()
+				.put(org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eNS_URI,
+						org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eINSTANCE);
+
+	}
+
+	/**
+	 * @return {@code true} if the current application model has top-level windows.
+	 */
+	public boolean hasTopLevelWindows() {
+		return hasTopLevelWindows(resource);
+	}
+
+	/**
+	 * @return {@code true} if the specified application model has top-level windows.
+	 */
+	private boolean hasTopLevelWindows(Resource applicationResource) {
+		if (applicationResource == null || applicationResource.getContents() == null) {
+			// If the application resource doesn't exist or has no contents, then it has no
+			// top-level windows (and we are in an error state).
+			return false;
+		}
+		MApplication application = (MApplication) applicationResource.getContents().get(0);
+		return !application.getChildren().isEmpty();
+	}
+
+	@Override
+	public Resource loadMostRecentModel() {
+		// This is temporary code to migrate existing delta files into full models
+		if (deltaRestore && saveAndRestore && !clearPersistedState) {
+			File baseLocation = getBaseLocation();
+			File deltaFile = new File(baseLocation, "deltas.xml"); //$NON-NLS-1$
+
+			if (deltaFile.exists()) {
+				MApplication appElement = null;
+				try {
+					// create new resource in case code below fails somewhere
+					File workbenchData = getWorkbenchSaveLocation();
+					URI restoreLocationNew = URI.createFileURI(workbenchData.getAbsolutePath());
+					resource = resourceSetImpl.createResource(restoreLocationNew);
+
+					Resource oldResource = loadResource(applicationDefinitionInstance);
+					appElement = (MApplication) oldResource.getContents().get(0);
+
+					context.set(MApplication.class, appElement);
+					ModelAssembler contribProcessor = ContextInjectionFactory.make(
+							ModelAssembler.class, context);
+					contribProcessor.processModel(true);
+
+					File deltaOldFile = new File(baseLocation, "deltas_42M7migration.xml"); //$NON-NLS-1$
+					deltaFile.renameTo(deltaOldFile);
+					URI restoreLocation = URI.createFileURI(deltaOldFile.getAbsolutePath());
+
+					File file = new File(restoreLocation.toFileString());
+
+					if (file.exists()) {
+						Document document = DocumentBuilderFactory.newInstance()
+								.newDocumentBuilder().parse(file);
+						IModelReconcilingService modelReconcilingService = new ModelReconcilingService();
+						ModelReconciler modelReconciler = modelReconcilingService
+								.createModelReconciler();
+						document.normalizeDocument();
+						Collection<ModelDelta> deltas = modelReconciler.constructDeltas(oldResource
+								.getContents().get(0), document);
+						modelReconcilingService.applyDeltas(deltas);
+					}
+				} catch (Exception e) {
+					if (logger != null) {
+						logger.error(e);
+					}
+				}
+				if (appElement != null) {
+					resource.getContents().add((EObject) appElement);
+					if (!hasTopLevelWindows(resource) && logger != null) {
+						logger.error("No top-level windows seen when migrating from existing delta files"); //$NON-NLS-1$
+					}
+				}
+				return resource;
+			}
+		}
+
+		File workbenchData = null;
+		URI restoreLocation = null;
+
+		if (saveAndRestore) {
+			workbenchData = getWorkbenchSaveLocation();
+			restoreLocation = URI.createFileURI(workbenchData.getAbsolutePath());
+		}
+
+		if (clearPersistedState && workbenchData != null && workbenchData.exists()) {
+			workbenchData.delete();
+		}
+
+		// last stored time-stamp
+		long restoreLastModified = restoreLocation == null ? 0L : new File(
+				restoreLocation.toFileString()).lastModified();
+
+		// See bug 380663, bug 381219
+		// long lastApplicationModification = getLastApplicationModification();
+		// boolean restore = restoreLastModified > lastApplicationModification;
+		boolean restore = restoreLastModified > 0;
+		boolean initialModel;
+
+		resource = null;
+		if (restore && saveAndRestore) {
+			resource = loadResource(restoreLocation);
+			// If the saved model does not have any top-level windows, Eclipse will exit
+			// immediately, so throw out the persisted state and reinitialize with the defaults.
+			if (!hasTopLevelWindows(resource)) {
+				if (logger != null) {
+					logger.error(new Exception(), // log a stack trace to help debug the corruption
+							"The persisted workbench has no top-level windows, so reinitializing with defaults."); //$NON-NLS-1$
+				}
+				resource = null;
+			}
+		}
+		if (resource == null) {
+			Resource applicationResource = loadResource(applicationDefinitionInstance);
+			MApplication theApp = (MApplication) applicationResource.getContents().get(0);
+			resource = createResourceWithApp(theApp);
+			context.set(E4Workbench.NO_SAVED_MODEL_FOUND, Boolean.TRUE);
+			initialModel = true;
+		} else {
+			initialModel = false;
+		}
+
+		// Add model items described in the model extension point
+		// This has to be done before commands are put into the context
+		MApplication appElement = (MApplication) resource.getContents().get(0);
+
+		this.context.set(MApplication.class, appElement);
+		ModelAssembler contribProcessor = ContextInjectionFactory.make(ModelAssembler.class,
+				context);
+		contribProcessor.processModel(initialModel);
+
+		if (!hasTopLevelWindows(resource) && logger != null) {
+			logger.error(new Exception(), // log a stack trace to help debug the
+											// corruption
+					"Initializing from the application definition instance yields no top-level windows! " //$NON-NLS-1$
+							+ "Continuing execution, but the missing windows may cause other initialization failures."); //$NON-NLS-1$
+		}
+
+		if (!clearPersistedState) {
+			CommandLineOptionModelProcessor processor = ContextInjectionFactory.make(
+					CommandLineOptionModelProcessor.class, context);
+			processor.process();
+		}
+
+		return resource;
+	}
+
+	@Override
+	public void save() throws IOException {
+		if (saveAndRestore)
+			resource.save(null);
+	}
+
+	/**
+	 * Creates a resource with an app Model, used for saving copies of the main app model.
+	 *
+	 * @param theApp
+	 *            the application model to add to the resource
+	 * @return a resource with a proper save path with the model as contents
+	 */
+	@Override
+	public Resource createResourceWithApp(MApplication theApp) {
+		Resource res = createResource();
+		res.getContents().add((EObject) theApp);
+		return res;
+	}
+
+	private Resource createResource() {
+		if (saveAndRestore) {
+			URI saveLocation = URI.createFileURI(getWorkbenchSaveLocation().getAbsolutePath());
+			return resourceSetImpl.createResource(saveLocation);
+		}
+		return resourceSetImpl.createResource(URI.createURI("workbench.xmi")); //$NON-NLS-1$
+	}
+
+	private File getWorkbenchSaveLocation() {
+		File workbenchData = new File(getBaseLocation(), "workbench.xmi"); //$NON-NLS-1$
+		return workbenchData;
+	}
+
+	private File getBaseLocation() {
+		File baseLocation;
+		try {
+			baseLocation = new File(URIUtil.toURI(instanceLocation.getURL()));
+		} catch (URISyntaxException e) {
+			throw new RuntimeException(e);
+		}
+		baseLocation = new File(baseLocation, ".metadata"); //$NON-NLS-1$
+		baseLocation = new File(baseLocation, ".plugins"); //$NON-NLS-1$
+		baseLocation = new File(baseLocation, "org.eclipse.e4.workbench"); //$NON-NLS-1$
+		return baseLocation;
+	}
+
+	// Ensures that even models with error are loaded!
+	private Resource loadResource(URI uri) {
+		Resource resource;
+		try {
+			resource = getResource(uri);
+		} catch (Exception e) {
+			// TODO We could use diagnostics for better analyzing the error
+			logger.error(e, "Unable to load resource " + uri.toString()); //$NON-NLS-1$
+			return null;
+		}
+
+		// TODO once we switch from deltas, we only need this once on the default model?
+		String contributorURI = URIHelper.EMFtoPlatform(uri);
+		if (contributorURI != null) {
+			TreeIterator<EObject> it = EcoreUtil.getAllContents(resource.getContents());
+			while (it.hasNext()) {
+				EObject o = it.next();
+				if (o instanceof MApplicationElement) {
+					((MApplicationElement) o).setContributorURI(contributorURI);
+				}
+			}
+		}
+		return resource;
+	}
+
+	private Resource getResource(URI uri) throws Exception {
+		Resource resource;
+		if (saveAndRestore) {
+			resource = resourceSetImpl.getResource(uri, true);
+		} else {
+			// Workaround for java.lang.IllegalStateException: No instance data can be specified
+			// thrown by org.eclipse.core.internal.runtime.DataArea.assertLocationInitialized
+			// The DataArea.assertLocationInitialized is called by ResourceSetImpl.getResource(URI,
+			// boolean)
+			resource = resourceSetImpl.createResource(uri);
+			resource.load(new URL(uri.toString()).openStream(), resourceSetImpl.getLoadOptions());
+		}
+
+		return resource;
+	}
+
+	protected long getLastApplicationModification() {
+		long appLastModified = 0L;
+		ResourceSetImpl resourceSetImpl = new ResourceSetImpl();
+
+		Map<String, ?> attributes = resourceSetImpl.getURIConverter().getAttributes(
+				applicationDefinitionInstance,
+				Collections.singletonMap(URIConverter.OPTION_REQUESTED_ATTRIBUTES,
+						Collections.singleton(URIConverter.ATTRIBUTE_TIME_STAMP)));
+
+		Object timestamp = attributes.get(URIConverter.ATTRIBUTE_TIME_STAMP);
+		if (timestamp instanceof Long) {
+			appLastModified = ((Long) timestamp).longValue();
+		} else if (applicationDefinitionInstance.isPlatformPlugin()) {
+			try {
+				java.net.URL url = new java.net.URL(applicationDefinitionInstance.toString());
+				// can't just use 'url.openConnection()' as it usually returns a
+				// PlatformURLPluginConnection which doesn't expose the
+				// last-modification time. So we try to resolve the file through
+				// the bundle to obtain a BundleURLConnection instead.
+				Object[] obj = PlatformURLPluginConnection.parse(url.getFile().trim(), url);
+				Bundle b = (Bundle) obj[0];
+				// first try to resolve as an bundle file entry, then as a resource using
+				// the bundle's classpath
+				java.net.URL resolved = b.getEntry((String) obj[1]);
+				if (resolved == null) {
+					resolved = b.getResource((String) obj[1]);
+				}
+				if (resolved != null) {
+					URLConnection openConnection = resolved.openConnection();
+					appLastModified = openConnection.getLastModified();
+				}
+			} catch (Exception e) {
+				// ignore
+			}
+		}
+
+		return appLastModified;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java
new file mode 100644
index 0000000..54a3607
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionAggregator.java
@@ -0,0 +1,384 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Oliver Puetter - activePart set to NULL when all parts are closed (http://bugs.eclipse.org/423040)
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.core.internal.contexts.IContextDisposalListener;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+public class SelectionAggregator {
+
+	static final String OUT_SELECTION = "org.eclipse.ui.output.selection"; //$NON-NLS-1$
+	static final String OUT_POST_SELECTION = "org.eclipse.ui.output.postSelection"; //$NON-NLS-1$
+
+	private ListenerList genericListeners = new ListenerList();
+	private ListenerList genericPostListeners = new ListenerList();
+	private Map<String, ListenerList> targetedListeners = new HashMap<String, ListenerList>();
+	private Map<String, ListenerList> targetedPostListeners = new HashMap<String, ListenerList>();
+	private Set<IEclipseContext> tracked = new HashSet<IEclipseContext>();
+
+	private EventHandler eventHandler = new EventHandler() {
+		@Override
+		public void handleEvent(Event event) {
+			Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
+			if (element instanceof MPart) {
+				MPart part = (MPart) element;
+
+				String partId = part.getElementId();
+				if (targetedListeners.containsKey(partId)
+						|| targetedPostListeners.containsKey(partId))
+					track(part);
+			}
+		}
+	};
+
+	private MPart activePart;
+
+	private IEclipseContext context;
+
+	private EPartService partService;
+
+	private IEventBroker eventBroker;
+
+	private Logger logger;
+
+	@Inject
+	SelectionAggregator(IEclipseContext context, EPartService partService,
+			IEventBroker eventBroker, Logger logger) {
+		super();
+		this.context = context;
+		this.partService = partService;
+		this.eventBroker = eventBroker;
+		this.logger = logger;
+	}
+
+	@PreDestroy
+	void preDestroy() {
+		genericListeners.clear();
+		genericPostListeners.clear();
+		targetedListeners.clear();
+		targetedPostListeners.clear();
+
+		eventBroker.unsubscribe(eventHandler);
+	}
+
+	@PostConstruct
+	void postConstruct() {
+		eventBroker.subscribe(UIEvents.Context.TOPIC_CONTEXT, eventHandler);
+	}
+
+	@Inject
+	void setPart(@Optional @Named(IServiceConstants.ACTIVE_PART) final MPart part) {
+		if (part == null) {
+			activePart = null;
+			context.set(IServiceConstants.ACTIVE_SELECTION, null);
+		} else if (activePart != part) {
+			activePart = part;
+			IEclipseContext partContext = part.getContext();
+			if (partContext.containsKey(OUT_POST_SELECTION)) {
+				Object selection = partContext.get(OUT_POST_SELECTION);
+				context.set(IServiceConstants.ACTIVE_SELECTION, selection);
+			} else if (partContext.containsKey(OUT_SELECTION)) {
+				Object selection = partContext.get(OUT_SELECTION);
+				context.set(IServiceConstants.ACTIVE_SELECTION, selection);
+			}
+			track(part);
+		}
+	}
+
+	private void notifyListeners(final MPart part, final Object selection) {
+		for (Object listener : genericListeners.getListeners()) {
+			final ISelectionListener myListener = (ISelectionListener) listener;
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					myListener.selectionChanged(part, selection);
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					logger.error(exception);
+				}
+			});
+		}
+		notifyTargetedListeners(part, selection);
+	}
+
+	private void notifyTargetedListeners(final MPart part, final Object selection) {
+		String id = part.getElementId();
+		if (id != null) {
+			ListenerList listenerList = targetedListeners.get(id);
+			if (listenerList != null) {
+				for (Object listener : listenerList.getListeners()) {
+					final ISelectionListener myListener = (ISelectionListener) listener;
+					SafeRunner.run(new ISafeRunnable() {
+						@Override
+						public void run() throws Exception {
+							myListener.selectionChanged(part, selection);
+						}
+
+						@Override
+						public void handleException(Throwable exception) {
+							logger.error(exception);
+						}
+					});
+				}
+			}
+		}
+	}
+
+	private void notifyPostListeners(final MPart part, final Object selection) {
+		for (Object listener : genericPostListeners.getListeners()) {
+			final ISelectionListener myListener = (ISelectionListener) listener;
+			SafeRunner.run(new ISafeRunnable() {
+				@Override
+				public void run() throws Exception {
+					myListener.selectionChanged(part, selection);
+				}
+
+				@Override
+				public void handleException(Throwable exception) {
+					logger.error(exception);
+				}
+			});
+		}
+		notifyTargetedPostListeners(part, selection);
+	}
+
+	private void notifyTargetedPostListeners(final MPart part, final Object selection) {
+		String id = part.getElementId();
+		if (id != null) {
+			ListenerList listenerList = targetedPostListeners.get(id);
+			if (listenerList != null) {
+				for (Object listener : listenerList.getListeners()) {
+					final ISelectionListener myListener = (ISelectionListener) listener;
+					SafeRunner.run(new ISafeRunnable() {
+						@Override
+						public void run() throws Exception {
+							myListener.selectionChanged(part, selection);
+						}
+
+						@Override
+						public void handleException(Throwable exception) {
+							logger.error(exception);
+						}
+					});
+				}
+			}
+		}
+	}
+
+	private void track(final MPart part) {
+		final IEclipseContext myContext = this.context;
+		IEclipseContext context = part.getContext();
+		if (context != null && tracked.add(context)) {
+			if (context instanceof EclipseContext) {
+				((EclipseContext) context).notifyOnDisposal(new IContextDisposalListener() {
+					@Override
+					public void disposed(IEclipseContext context) {
+						tracked.remove(context);
+					}
+				});
+			}
+
+			context.runAndTrack(new RunAndTrack() {
+				private boolean initial = true;
+
+				@Override
+				public boolean changed(IEclipseContext context) {
+					final Object selection = context.get(OUT_SELECTION);
+					if (initial) {
+						initial = false;
+						if (selection == null) {
+							return true;
+						}
+					}
+
+					if (activePart == part) {
+						myContext.set(IServiceConstants.ACTIVE_SELECTION, selection);
+						runExternalCode(new Runnable() {
+							@Override
+							public void run() {
+								notifyListeners(part, selection);
+							}
+						});
+					} else {
+						runExternalCode(new Runnable() {
+							@Override
+							public void run() {
+								notifyTargetedListeners(part, selection);
+							}
+						});
+						// we don't need to keep tracking non-active parts unless
+						// they have targeted listeners
+						String partId = part.getElementId();
+						boolean continueTracking = targetedListeners.containsKey(partId)
+								|| targetedPostListeners.containsKey(partId);
+						if (!continueTracking) {
+							tracked.remove(part.getContext());
+						}
+						return continueTracking;
+					}
+					return true;
+				}
+			});
+			context.runAndTrack(new RunAndTrack() {
+				private boolean initial = true;
+
+				@Override
+				public boolean changed(IEclipseContext context) {
+					final Object postSelection = context.get(OUT_POST_SELECTION);
+					if (initial) {
+						initial = false;
+						if (postSelection == null) {
+							return true;
+						}
+					}
+
+					if (activePart == part) {
+						runExternalCode(new Runnable() {
+							@Override
+							public void run() {
+								notifyPostListeners(part, postSelection);
+							}
+						});
+					} else {
+						runExternalCode(new Runnable() {
+							@Override
+							public void run() {
+								notifyTargetedPostListeners(part, postSelection);
+							}
+						});
+						// we don't need to keep tracking non-active parts unless
+						// they have targeted listeners
+						String partId = part.getElementId();
+						boolean continueTracking = targetedListeners.containsKey(partId)
+								|| targetedPostListeners.containsKey(partId);
+						if (!continueTracking) {
+							tracked.remove(part.getContext());
+						}
+						return continueTracking;
+					}
+					return true;
+				}
+			});
+		}
+	}
+
+	public Object getSelection() {
+		return context.get(IServiceConstants.ACTIVE_SELECTION);
+	}
+
+	public void addSelectionListener(ISelectionListener listener) {
+		genericListeners.add(listener);
+	}
+
+	public void addPostSelectionListener(ISelectionListener listener) {
+		genericPostListeners.add(listener);
+	}
+
+	public void removeSelectionListener(ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			genericListeners.remove(listener);
+		}
+	}
+
+	public void removePostSelectionListener(ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			genericPostListeners.remove(listener);
+		}
+	}
+
+	public void addSelectionListener(String partId, ISelectionListener listener) {
+		ListenerList listeners = targetedListeners.get(partId);
+		if (listeners == null) {
+			listeners = new ListenerList();
+			targetedListeners.put(partId, listeners);
+		}
+		listeners.add(listener);
+
+		MPart part = partService.findPart(partId);
+		if (part != null)
+			track(part);
+	}
+
+	public void addPostSelectionListener(String partId, ISelectionListener listener) {
+		ListenerList listeners = targetedPostListeners.get(partId);
+		if (listeners == null) {
+			listeners = new ListenerList();
+			targetedPostListeners.put(partId, listeners);
+		}
+		listeners.add(listener);
+
+		MPart part = partService.findPart(partId);
+		if (part != null)
+			track(part);
+	}
+
+	public void removeSelectionListener(String partId, ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			ListenerList listeners = targetedListeners.get(partId);
+			if (listeners != null) {
+				listeners.remove(listener);
+			}
+		}
+	}
+
+	public void removePostSelectionListener(String partId, ISelectionListener listener) {
+		// we may have been destroyed already, see bug 310113
+		if (context != null) {
+			ListenerList listeners = targetedPostListeners.get(partId);
+			if (listeners != null) {
+				listeners.remove(listener);
+			}
+		}
+	}
+
+	public Object getSelection(String partId) {
+		MPart part = partService.findPart(partId);
+		if (part == null) {
+			return null;
+		}
+
+		IEclipseContext partContext = part.getContext();
+		if (partContext == null) {
+			return null;
+		}
+		return partContext.get(OUT_SELECTION);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java
new file mode 100644
index 0000000..92e6a9a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/SelectionServiceImpl.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import javax.inject.Inject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+
+public class SelectionServiceImpl implements ESelectionService {
+
+	private IEclipseContext context;
+
+	@Inject
+	SelectionServiceImpl(IEclipseContext context) {
+		this.context = context;
+	}
+
+	@Override
+	public void setSelection(Object selection) {
+		context.set(SelectionAggregator.OUT_SELECTION, selection);
+	}
+
+	@Override
+	public void setPostSelection(Object selection) {
+		context.set(SelectionAggregator.OUT_POST_SELECTION, selection);
+	}
+
+	@Override
+	public Object getSelection() {
+		return getServiceAggregator().getSelection();
+	}
+
+	@Override
+	public Object getSelection(String partId) {
+		return getServiceAggregator().getSelection(partId);
+	}
+
+	@Override
+	public void addSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().addSelectionListener(listener);
+	}
+
+	@Override
+	public void removeSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().removeSelectionListener(listener);
+	}
+
+	@Override
+	public void addSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().addSelectionListener(partId, listener);
+	}
+
+	@Override
+	public void removeSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().removeSelectionListener(partId, listener);
+	}
+
+	@Override
+	public void addPostSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().addPostSelectionListener(listener);
+	}
+
+	@Override
+	public void removePostSelectionListener(ISelectionListener listener) {
+		getServiceAggregator().removePostSelectionListener(listener);
+	}
+
+	@Override
+	public void addPostSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().addPostSelectionListener(partId, listener);
+	}
+
+	@Override
+	public void removePostSelectionListener(String partId, ISelectionListener listener) {
+		getServiceAggregator().removePostSelectionListener(partId, listener);
+	}
+
+	private SelectionAggregator getServiceAggregator() {
+		SelectionAggregator aggregator = context.get(SelectionAggregator.class);
+		if (aggregator != null)
+			return aggregator;
+		MApplication app = context.get(MApplication.class);
+		if (app == null)
+			return null;
+		MWindow selectedWindow = app.getSelectedElement();
+		return selectedWindow.getContext().get(SelectionAggregator.class);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java
new file mode 100644
index 0000000..daf7c93
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Manumitting Technologies Inc 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:
+ *     Brian de Alwis (MTI) - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class implements a topological sort. The implementation distinguishes between the objects to
+ * be sorted from their corresponding dependency identifier, and properly tracks where multiple
+ * objects have the same identifier. This is required for sorting Eclipse Extension Registry
+ * extensions by their plug-in dependencies, as a plug-in may contribute multiple sets of
+ * extensions.
+ *
+ * <p>
+ * The implementation creates a dependency graph where the vertices represent the object identifiers
+ * and the edges represent the required-relation between them. Subclasses must implement of
+ * {@link #getRequirements(Object)} and {@link #getDependencies(Object)}. Although these are
+ * normally symmetric operations (i.e., if <em>B</em> is a requirement of <em>A</em>, then
+ * <em>A</em> is a dependent of <em>B</em>), one may be easier to compute than the other in some
+ * contexts and so this class combines the results.
+ * </p>
+ *
+ * <p>
+ * Description of the algorithm:
+ * </p>
+ * <ol>
+ * <li>Construct the dependency graph with {@link #getRequirements(Object)} and
+ * {@link #getDependencies(Object)}. The out edges represent requirements, and in edges represent
+ * dependencies. This graph may be disconnected if there are nodes with no dependencies amongst each
+ * other.</li>
+ * <li>Sort the list of identifiers by their out-degree, and then by in-degree. Ids with out-degree
+ * 0 are roots; if there is no id with out-degree 0 then we have a cycle. We sort nodes with the
+ * same out-degree by their in-degree to privilege nodes within the cycle from those that are
+ * dependencies (e.g., consider: A &rarr; B, B &rarr; C, C &rarr; A, D &rarr; A; all have out-degree
+ * 1, but A has in-degree 2, and A must be output before D).</li>
+ * <li>While there are ids left to consider, take the id with lowest out-degree and add its objects
+ * to the list. Remove the id from all of its dependents' required lists. This removal changes the
+ * out-degree and may require that the id list be resorted since some of the dependents may now be
+ * roots. Note that should we encounter a cycle (i.e., no nodes of degree 0), we process all the
+ * bundles within the cycle, since any dependencies to any single ndoe within the cycle effectively
+ * extends to all.</li>
+ * </ol>
+ *
+ * @param <T>
+ *            the type of objects being sorted
+ * @param <ID>
+ *            the type of the object identifiers; multiple objects of T may correspond to the same
+ *            ID
+ */
+public abstract class TopologicalSort<T, ID> {
+	private final Map<ID, Collection<T>> mappedObjects = new HashMap<ID, Collection<T>>();
+	// Captures the bundles that are listed as requirements for a particular bundle.
+	private final Map<ID, Collection<ID>> requires = new HashMap<ID, Collection<ID>>();
+	// Captures the bundles that list a particular bundle as a requirement
+	private final Map<ID, Collection<ID>> depends = new HashMap<ID, Collection<ID>>();
+
+	/**
+	 * Return the identifier for the given object. The implementation properly tracks where multiple
+	 * objects have the same identifier.
+	 *
+	 * @param object
+	 *            the object
+	 * @return the identifier
+	 */
+	protected abstract ID getId(T object);
+
+	/**
+	 * Return the list of IDs required by {@code id}. Implementors may choose to return {@code null}
+	 * or an empty collection if this information is more easily computed by
+	 * {@link #getDependencies(Object)}.
+	 *
+	 * @param id
+	 *            the id
+	 * @return the IDs required by {@code id}; may be {@code null}
+	 */
+	protected abstract Collection<ID> getRequirements(ID id);
+
+	/**
+	 * Return the list of IDs depended upon by {@code id}. Implementors may choose to return
+	 * {@code null} or an empty collection if this information is more easily computed by
+	 * {@link #getRequirements(Object)}.
+	 *
+	 * @param id
+	 *            the id
+	 * @return the IDs depended upon by {@code id}; may be {@code null}
+	 */
+	protected abstract Collection<ID> getDependencies(ID id);
+
+	/**
+	 * Sort the provided extensions by the dependencies of their contributors. Note that sorting is
+	 * done in-place.
+	 *
+	 * @param objects
+	 *            the objects to be sorted
+	 * @return the objects in a topologically-sorted order
+	 */
+	public T[] sort(T[] objects) {
+		if (objects.length <= 1) {
+			return objects;
+		}
+
+		addAll(objects);
+		return process(objects);
+	}
+
+	/** Place results in results and return results */
+	private T[] process(T[] results) {
+		buildDependencyGraph();
+
+		// Sort nodes by out-degree ({@code requires}) and then by in-degree.
+		// There are two situations: we have disconnected graphs
+		// In case of a cycle, one of the nodes involved in the cycle should have
+		// higher in-degree from some other non-cyclic node
+		int resultsIndex = 0;
+		List<ID> sortedByOutdegree = new ArrayList<ID>(requires.keySet());
+		Comparator<ID> outdegreeSorter = new Comparator<ID>() {
+			@Override
+			public int compare(ID o1, ID o2) {
+				assert requires.containsKey(o1) && requires.containsKey(o2);
+				int comparison = requires.get(o1).size() - requires.get(o2).size();
+				if (comparison == 0) {
+					// Select the node whose removal would have the greatest effect
+					return depends.get(o2).size() - depends.get(o1).size();
+				}
+				return comparison;
+			}
+		};
+		Collections.sort(sortedByOutdegree, outdegreeSorter);
+
+		while (!sortedByOutdegree.isEmpty()) {
+			// don't sort unnecessarily: the current ordering is fine providing
+			// item #0 still has no dependencies
+			if (!requires.get(sortedByOutdegree.get(0)).isEmpty()) {
+				Collections.sort(sortedByOutdegree, outdegreeSorter);
+			}
+			LinkedList<ID> cycleToBeDone = new LinkedList<ID>();
+			cycleToBeDone.add(sortedByOutdegree.remove(0));
+			while (!cycleToBeDone.isEmpty()) {
+				ID bundleId = cycleToBeDone.removeFirst();
+				assert depends.containsKey(bundleId) && requires.containsKey(bundleId);
+				for (T ext : mappedObjects.get(bundleId)) {
+					results[resultsIndex++] = ext;
+				}
+				// requires.get(bundleId) is empty unless there's a cycle;
+				// we process all nodes within the cycle now
+				for (ID reqId : requires.get(bundleId)) {
+					cycleToBeDone.add(reqId);
+					sortedByOutdegree.remove(reqId);
+					depends.get(reqId).remove(bundleId);
+				}
+				requires.remove(bundleId);
+				for (ID depId : depends.get(bundleId)) {
+					requires.get(depId).remove(bundleId);
+				}
+				depends.remove(bundleId);
+			}
+		}
+		return results;
+	}
+
+	/**
+	 * @param objects
+	 */
+	private void addAll(T[] objects) {
+		// first build up the list of object ids actually being considered
+		for (T o : objects) {
+			ID id = getId(o);
+			Collection<T> exts = mappedObjects.get(id);
+			if (exts == null) {
+				mappedObjects.put(id, exts = new HashSet<T>());
+			}
+			exts.add(o);
+		}
+	}
+
+	private void buildDependencyGraph() {
+		// reset
+		requires.clear();
+		depends.clear();
+		for (ID id : mappedObjects.keySet()) {
+			requires.put(id, new HashSet<ID>());
+			depends.put(id, new HashSet<ID>());
+		}
+
+		// now populate the dependency graph
+		for (ID subjectId : mappedObjects.keySet()) {
+			assert requires.containsKey(subjectId) && depends.containsKey(subjectId);
+
+			Collection<ID> requirements = getRequirements(subjectId);
+			if (requirements != null) {
+				for (ID requiredId : requirements) {
+					assert !requiredId.equals(subjectId) : "self-cycles not supported"; //$NON-NLS-1$
+					// ignore objects not being sorted
+					if (!mappedObjects.containsKey(requiredId)) {
+						continue;
+					}
+					// So requiredId is a requirement for subjectId
+					// and subjectId is a dependent of requiredId
+					depends.get(requiredId).add(subjectId);
+					requires.get(subjectId).add(requiredId);
+				}
+			}
+
+			Collection<ID> dependencies = getDependencies(subjectId);
+			if (dependencies != null) {
+				for (ID dependentId : dependencies) {
+					assert !dependentId.equals(subjectId) : "self-cycles not supported"; //$NON-NLS-1$
+					// ignore objects not being sorted
+					if (!mappedObjects.containsKey(dependentId)) {
+						continue;
+					}
+					// So dependentId is a dependency of subjectId
+					// and subjectId is a requirement of dependentId
+					requires.get(dependentId).add(subjectId);
+					depends.get(subjectId).add(dependentId);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Trackable.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Trackable.java
new file mode 100644
index 0000000..559fb1b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Trackable.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.contexts.RunAndTrack;
+
+public abstract class Trackable extends RunAndTrack {
+	public IEclipseContext trackingContext;
+	public boolean participating = true;
+
+	public Trackable(IEclipseContext context) {
+		this.trackingContext = context;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/UIEventPublisher.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/UIEventPublisher.java
new file mode 100644
index 0000000..9d575ff
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/UIEventPublisher.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.impl.StringToObjectMapImpl;
+import org.eclipse.e4.ui.model.application.impl.StringToStringMapImpl;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
+import org.eclipse.e4.ui.workbench.UIEvents.EventTypes;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.EContentAdapter;
+
+/**
+ * Transforms E4 MPart events into 3.x legacy events.
+ */
+public class UIEventPublisher extends EContentAdapter {
+
+	private IEclipseContext context;
+
+	/**
+	 * @param e4Context
+	 */
+	public UIEventPublisher(IEclipseContext e4Context) {
+		this.context = e4Context;
+	}
+
+	@Override
+	public void notifyChanged(Notification notification) {
+		super.notifyChanged(notification);
+
+		// Ignore events that did not change the model value
+		if (notification.isTouch())
+			return;
+
+		// Format the EMF event as an E4 UIEvent
+		Map<String, Object> argMap = new HashMap<String, Object>();
+
+		String topic = formatData(notification, argMap);
+
+		if (topic != null) {
+			IEventBroker eventManager = context.get(IEventBroker.class);
+			eventManager.send(topic, argMap);
+		}
+	}
+
+	/**
+	 * Large hack here. Open to better suggestions
+	 *
+	 * When the model SET changes occur to the values of maps, the NOTIFIER is the map and not the
+	 * element containing the map. (Note that map addition and removal events DO come in with the
+	 * NOTIFIER set to the element containing the map)
+	 *
+	 * In the problematic case, the containing model element can be found in the NOTIFIER's
+	 * eContainer. However, the FEATURE (field) of the eContainer containing the map is not readily
+	 * available.
+	 *
+	 * We had considered a strategy where you recursively check all fields of the eContainer for an
+	 * object that IS the NOTIFIER, however these events happen a lot and the resulting code would
+	 * have very poor performance. Additionally, all I could get from the eContainer was an EMF
+	 * DelegatingMap, while the NOTIFIER is an instance of the contained delegated map
+	 * (StringToObjectImpl for example). It would appear some reflection tricks to read
+	 * protected/private methods would be required to get the correct objects to compare.
+	 *
+	 * At this time there are only two maps used in our model. A StringToObject map used in
+	 * MApplicationElement.transientData a StringToString map used in
+	 * MApplicationElement.persistentState.
+	 *
+	 * The large hack employed is to take this knowledge and hard hard code the topic based on the
+	 * type of the NOTIFIER.
+	 *
+	 * One problem with this approach is if a developer modifies the model to contain another field
+	 * using a map events would be generated with the wrong topic information. This will lead to
+	 * hard to identify bugs.
+	 *
+	 * To combat this I have added guard code that explicitly confirms that a StringToObject change
+	 * is being originated by transientData and a StringToString change is being originated by
+	 * persistentState. If the guard check fails an IllegalArgumentException is thrown with
+	 * instructions to modify UIEventPublisher.
+	 *
+	 * Clearly this is a sub-optimal solution and would like to hear suggestions for improvement.
+	 * Likely there is some "simple" EMF wisdom we are missing to make this work with a couple of
+	 * annotations, a white swan and a full moon.
+	 */
+	private String formatData(final Notification notification, Map<String, Object> argMap) {
+		MApplicationElement appElement = null;
+		EStructuralFeature feature = null;
+		String attributeName = null;
+		String topic = null;
+
+		Object notifier = notification.getNotifier();
+		Object oldValue = null;
+		Object newValue = null;
+		Object position = null;
+
+		if (notifier instanceof MApplicationElement) {
+			// Most EMF events will be these. Even map add and remove events
+			appElement = (MApplicationElement) notifier;
+			feature = (EStructuralFeature) notification.getFeature();
+			attributeName = feature.getName();
+			topic = getTopic(feature, getEventType(notification));
+			switch (notification.getEventType()) {
+			case Notification.MOVE:
+				// for MOVE, oldValue is actually the source position
+				oldValue = notification.getOldValue();
+				newValue = notification.getNewValue();
+				position = notification.getPosition();
+				break;
+			case Notification.ADD_MANY:
+				newValue = notification.getNewValue();
+				position = notification.getPosition();
+				break;
+			case Notification.REMOVE_MANY:
+				oldValue = notification.getOldValue();
+				position = notification.getNewValue();
+				break;
+			case Notification.ADD:
+			case Notification.REMOVE:
+				oldValue = notification.getOldValue();
+				newValue = notification.getNewValue();
+				position = notification.getPosition();
+				break;
+			case Notification.SET:
+			case Notification.UNSET:
+				oldValue = notification.getOldValue();
+				newValue = notification.getNewValue();
+				break;
+			default:
+				Activator.log(IStatus.ERROR, getClass().getName()
+						+ ": unhandled EMF Notification code: " //$NON-NLS-1$
+						+ notification.getEventType());
+			}
+		} else if (notifier instanceof StringToObjectMapImpl) {
+			// These are SET events on StringToObjectMap only
+			// StringToObjectMap is ONLY used by MApplicationData.transientData
+			appElement = (MApplicationElement) ((StringToObjectMapImpl) notifier).eContainer();
+
+			// Guard code to detect if some other model field is using a StringToObjectMap
+			final String key = ((StringToObjectMapImpl) notifier).getKey();
+			Object storedNewValue = appElement.getTransientData().get(key);
+			Object notificationNewValue = notification.getNewValue();
+
+			// Identity check by design. If these are not the same object then the event came from
+			// a different model object than we expected. Warn the developer
+			if (notificationNewValue != storedNewValue) {
+				throw new IllegalArgumentException(
+						"A StringToObjectMap that was NOT MApplicationElement.transientData changed.  You must modify UIEventPublisher appropriately"); //$NON-NLS-1$
+			}
+
+			attributeName = UIEvents.ApplicationElement.TRANSIENTDATA;
+			topic = getTopic(attributeName, getEventType(notification));
+
+			// We need to send MapEntries for the old and new values.
+			oldValue = createMapEntry(key, notification.getOldValue());
+			newValue = createMapEntry(key, notification.getNewValue());
+		} else if (notifier instanceof StringToStringMapImpl) {
+			// These are SET events on StringToStringMap only
+			// StringToStringMap is ONLY used by MApplicationData.persistedState
+			appElement = (MApplicationElement) ((StringToStringMapImpl) notifier).eContainer();
+
+			// Guard code to detect if some other model field is using a StringToStringMap
+			final String key = ((StringToStringMapImpl) notifier).getKey();
+			Object storedNewValue = appElement.getPersistedState().get(key);
+			Object notificationNewValue = notification.getNewValue();
+
+			// Identity check by design. If these are not the same object then the event came from
+			// a different model object than we expected. Warn the developer
+			if (notificationNewValue != storedNewValue) {
+				throw new IllegalArgumentException(
+						"A StringToStringMap that was NOT MApplicationElement.persistedState changed.  You must modify UIEventPublisher appropriately"); //$NON-NLS-1$
+			}
+
+			attributeName = UIEvents.ApplicationElement.PERSISTEDSTATE;
+			topic = getTopic(attributeName, getEventType(notification));
+			oldValue = createMapEntry(key, notification.getOldValue());
+			newValue = createMapEntry(key, notification.getNewValue());
+		} else {
+			// Unhandled notification type. Ignore event
+			return null;
+		}
+
+		argMap.put(EventTags.TYPE, getEventType(notification));
+		argMap.put(EventTags.ELEMENT, appElement);
+		argMap.put(EventTags.ATTNAME, attributeName);
+
+		// no need to include UNSET
+		if (notification.getEventType() == Notification.SET
+				|| notification.getEventType() == Notification.MOVE
+				|| notification.getEventType() == Notification.ADD
+				|| notification.getEventType() == Notification.ADD_MANY
+				|| notification.getEventType() == Notification.REMOVE
+				|| notification.getEventType() == Notification.REMOVE_MANY) {
+			if (newValue != null) {
+				argMap.put(EventTags.NEW_VALUE, newValue);
+			}
+			if (oldValue != null) {
+				argMap.put(EventTags.OLD_VALUE, oldValue);
+			}
+			if (position != null) {
+				argMap.put(EventTags.POSITION, position);
+			}
+		}
+
+		if (appElement instanceof MUIElement) {
+			argMap.put(EventTags.WIDGET, ((MUIElement) appElement).getWidget());
+		}
+
+		return topic;
+	}
+
+	private String getEventType(Notification notification) {
+		switch (notification.getEventType()) {
+		case Notification.ADD:
+			return EventTypes.ADD;
+
+		case Notification.ADD_MANY:
+			return EventTypes.ADD_MANY;
+
+		case Notification.REMOVE:
+			return EventTypes.REMOVE;
+
+		case Notification.REMOVE_MANY:
+			return EventTypes.REMOVE_MANY;
+
+		case Notification.MOVE:
+			return EventTypes.MOVE;
+
+			// case Notification.UNSET: doesn't appear to be generated
+		case Notification.SET:
+			return EventTypes.SET;
+		}
+
+		return "UNKNOWN"; //$NON-NLS-1$
+	}
+
+	private Map.Entry<String, Object> createMapEntry(final String key, final Object value) {
+		return new Map.Entry<String, Object>() {
+			@Override
+			public String getKey() {
+				return key;
+			}
+
+			@Override
+			public Object getValue() {
+				return value;
+			}
+
+			@Override
+			public Object setValue(Object value) {
+				throw new UnsupportedOperationException();
+			}
+		};
+	}
+
+	private String getTopic(EStructuralFeature eFeature, String type) {
+		EClass eContainingClass = eFeature.getEContainingClass();
+		return UIEvents.UIModelTopicBase + UIEvents.TOPIC_SEP
+				+ eContainingClass.getEPackage().getName() + UIEvents.TOPIC_SEP
+				+ eContainingClass.getName() + UIEvents.TOPIC_SEP + eFeature.getName()
+				+ UIEvents.TOPIC_SEP + type;
+	}
+
+	private String getTopic(String attributeName, String type) {
+		String topicBase = "org/eclipse/e4/ui/model/application/ApplicationElement/"; //$NON-NLS-1$
+		return topicBase + attributeName + UIEvents.TOPIC_SEP + type;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java
new file mode 100644
index 0000000..e19ed5b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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
+ *     René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ *     Lars Vogel <Lars.Vogel@vogela.com> - Bug 449859
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import org.eclipse.core.runtime.IContributor;
+import org.eclipse.core.runtime.spi.RegistryContributor;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.service.log.LogService;
+
+/**
+ * Collection of URI-related utilities
+ */
+public class URIHelper {
+
+	/**
+	 * The schema identifier used for Eclipse platform references
+	 */
+	final private static String PLATFORM_SCHEMA = "platform:/"; //$NON-NLS-1$
+
+	/**
+	 * The schema identifier used for Eclipse bundlesclass reference
+	 */
+	final private static String BUNDLECLASS_SCHEMA = "bundleclass://"; //$NON-NLS-1$
+
+	/**
+	 * The schema identifier used for EMF platform references
+	 */
+	final private static String PLATFORM_SCHEMA_EMF = "platform"; //$NON-NLS-1$
+
+	/**
+	 * The segment used to specify location in a plugin
+	 */
+	final private static String PLUGIN_SEGMENT = "plugin/"; //$NON-NLS-1$
+
+	/**
+	 * The segment used to specify location in a fragment
+	 */
+	final private static String FRAGMENT_SEGMENT = "fragment/"; //$NON-NLS-1$
+
+	static public String constructPlatformURI(Bundle bundle) {
+		BundleRevision bundleRevision = bundle.adapt(BundleRevision.class);
+		if (bundleRevision == null)
+			return null;
+
+		StringBuffer tmp = new StringBuffer();
+		tmp.append(PLATFORM_SCHEMA);
+		if ((bundleRevision.getTypes() & BundleRevision.TYPE_FRAGMENT) == BundleRevision.TYPE_FRAGMENT)
+			tmp.append(FRAGMENT_SEGMENT);
+		else
+			tmp.append(PLUGIN_SEGMENT);
+		tmp.append(bundle.getSymbolicName());
+		return tmp.toString();
+	}
+
+	static public String constructPlatformURI(IContributor contributor) {
+		// registry contributors are singletons
+		String bundleName;
+		if (contributor instanceof RegistryContributor)
+			bundleName = ((RegistryContributor) contributor).getActualName();
+		else
+			// should not happen for the standard registry, but try to make a best guess
+			bundleName = contributor.getName();
+		Bundle bundle = Activator.getDefault().getBundleForName(bundleName);
+		return constructPlatformURI(bundle);
+	}
+
+	static public Bundle getBundle(String contributorURI) {
+		URI uri;
+		try {
+			uri = new URI(contributorURI);
+		} catch (URISyntaxException e) {
+			Activator.log(LogService.LOG_ERROR, "Invalid contributor URI: " + contributorURI); //$NON-NLS-1$
+			return null;
+		}
+		if (!PLATFORM_SCHEMA.equals(uri.getScheme()))
+			return null; // not implemented
+		return Activator.getDefault().getBundleForName(uri.getPath());
+	}
+
+	static public String EMFtoPlatform(org.eclipse.emf.common.util.URI uri) {
+		if (!PLATFORM_SCHEMA_EMF.equals(uri.scheme()))
+			return null;
+		// remove all segments but first two - only need bundle/fragment name
+		int segments = uri.segmentCount();
+		// segments: { "plugin", "org.eclipse.platform", "myDir", "model.e4xmi" }
+		if (segments > 2)
+			uri = uri.trimSegments(segments - 2);
+		return uri.toString();
+	}
+
+	/**
+	 * Helper method which checks if given String represents a Platform URI.
+	 *
+	 * @param uri
+	 *            a possible Platform URI
+	 * @return true if the given string is not {@code null} and starts with
+	 *         {@value #PLATFORM_SCHEMA}; false otherwise
+	 */
+	public static boolean isPlatformURI(String uri) {
+		return uri != null && uri.startsWith(PLATFORM_SCHEMA);
+	}
+
+	/**
+	 * Helper method which checks if given String represents a Bundleclass URI.
+	 *
+	 * @param uri
+	 *            a possible Bundleclass URI
+	 * @return true if the given string is not {@code null} and starts with
+	 *         {@value #BUNDLECLASS_SCHEMA}; false otherwise
+	 */
+	public static boolean isBundleClassUri(String uri) {
+		if (uri != null && uri.startsWith(BUNDLECLASS_SCHEMA)) {
+			String[] split = uri.substring(BUNDLECLASS_SCHEMA.length()).split("/"); //$NON-NLS-1$
+			// segments: { "bundle-symbolic-name", "fully qualified classname"}
+			if (split.length == 2) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Util.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Util.java
new file mode 100644
index 0000000..606eae1
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Util.java
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 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.internal.workbench;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * <p>
+ * A static class providing utility methods to all of JFace.
+ * </p>
+ *
+ * @since 3.1
+ */
+public final class Util {
+
+	/**
+	 * An unmodifiable, empty, sorted set. This value is guaranteed to never change and never be
+	 * <code>null</code>.
+	 */
+	public static final SortedSet<?> EMPTY_SORTED_SET = Collections.unmodifiableSortedSet(new TreeSet<>());
+
+	/**
+	 * A common zero-length string. It avoids needing write <code>NON-NLS</code> next to code
+	 * fragments. It's also a bit clearer to read.
+	 */
+	public static final String ZERO_LENGTH_STRING = ""; //$NON-NLS-1$
+
+	/**
+	 * Verifies that the given object is an instance of the given class.
+	 *
+	 * @param object
+	 *            The object to check; may be <code>null</code>.
+	 * @param c
+	 *            The class which the object should be; must not be <code>null</code>.
+	 */
+	public static final void assertInstance(final Object object, final Class<?> c) {
+		assertInstance(object, c, false);
+	}
+
+	/**
+	 * Verifies the given object is an instance of the given class. It is possible to specify
+	 * whether the object is permitted to be <code>null</code>.
+	 *
+	 * @param object
+	 *            The object to check; may be <code>null</code>.
+	 * @param c
+	 *            The class which the object should be; must not be <code>null</code>.
+	 * @param allowNull
+	 *            Whether the object is allowed to be <code>null</code>.
+	 */
+	private static final void assertInstance(final Object object, final Class<?> c,
+			final boolean allowNull) {
+		if (object == null && allowNull) {
+			return;
+		}
+
+		if (object == null || c == null) {
+			throw new NullPointerException();
+		} else if (!c.isInstance(object)) {
+			throw new IllegalArgumentException();
+		}
+	}
+
+	/**
+	 * Compares two boolean values. <code>false</code> is considered to be "less than"
+	 * <code>true</code>.
+	 *
+	 * @param left
+	 *            The left value to compare
+	 * @param right
+	 *            The right value to compare
+	 * @return <code>-1</code> if the left is <code>false</code> and the right is <code>true</code>.
+	 *         <code>1</code> if the opposite is true. If they are equal, then it returns
+	 *         <code>0</code>.
+	 */
+	public static final int compare(final boolean left, final boolean right) {
+		return left == false ? (right == true ? -1 : 0) : 1;
+	}
+
+	/**
+	 * Compares two integer values.
+	 *
+	 * @param left
+	 *            The left value to compare
+	 * @param right
+	 *            The right value to compare
+	 * @return <code>left - right</code>
+	 */
+	public static final int compare(final int left, final int right) {
+		return left - right;
+	}
+
+	/**
+	 * Compares to comparable objects -- defending against <code>null</code>.
+	 *
+	 * @param left
+	 *            The left object to compare; may be <code>null</code>.
+	 * @param right
+	 *            The right object to compare; may be <code>null</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to be the least
+	 *         possible value.
+	 */
+	public static final <T extends Comparable<T>> int compare(final T left, final T right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			return left.compareTo(right);
+		}
+	}
+
+	/**
+	 * Compares two arrays of comparable objects -- accounting for <code>null</code>.
+	 *
+	 * @param left
+	 *            The left array to be compared; may be <code>null</code>.
+	 * @param right
+	 *            The right array to be compared; may be <code>null</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to be the least
+	 *         possible value. A shorter array is considered less than a longer array.
+	 */
+	public static final <T extends Comparable<T>> int compare(final T[] left, final T[] right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			int l = left.length;
+			int r = right.length;
+
+			if (l != r) {
+				return l - r;
+			}
+
+			for (int i = 0; i < l; i++) {
+				int compareTo = compare(left[i], right[i]);
+
+				if (compareTo != 0) {
+					return compareTo;
+				}
+			}
+
+			return 0;
+		}
+	}
+
+	/**
+	 * Compares two lists -- account for <code>null</code>. The lists must contain comparable
+	 * objects.
+	 *
+	 * @param left
+	 *            The left list to compare; may be <code>null</code>. This list must only contain
+	 *            instances of <code>Comparable</code>.
+	 * @param right
+	 *            The right list to compare; may be <code>null</code>. This list must only contain
+	 *            instances of <code>Comparable</code>.
+	 * @return The result of the comparison. <code>null</code> is considered to be the least
+	 *         possible value. A shorter list is considered less than a longer list.
+	 */
+	public static final <T extends Comparable<T>> int compare(final List<T> left, final List<T> right) {
+		if (left == null && right == null) {
+			return 0;
+		} else if (left == null) {
+			return -1;
+		} else if (right == null) {
+			return 1;
+		} else {
+			int l = left.size();
+			int r = right.size();
+
+			if (l != r) {
+				return l - r;
+			}
+
+			for (int i = 0; i < l; i++) {
+				int compareTo = compare(left.get(i), right.get(i));
+
+				if (compareTo != 0) {
+					return compareTo;
+				}
+			}
+
+			return 0;
+		}
+	}
+
+	/**
+	 * Tests whether the first array ends with the second array.
+	 *
+	 * @param left
+	 *            The array to check (larger); may be <code>null</code>.
+	 * @param right
+	 *            The array that should be a subsequence (smaller); may be <code>null</code>.
+	 * @param equals
+	 *            Whether the two array are allowed to be equal.
+	 * @return <code>true</code> if the second array is a subsequence of the array list, and they
+	 *         share end elements.
+	 */
+	public static final boolean endsWith(final Object[] left, final Object[] right,
+			final boolean equals) {
+		if (left == null || right == null) {
+			return false;
+		}
+
+		int l = left.length;
+		int r = right.length;
+
+		if (r > l || !equals && r == l) {
+			return false;
+		}
+
+		for (int i = 0; i < r; i++) {
+			if (!equals(left[l - i - 1], right[r - i - 1])) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Checks whether the two objects are <code>null</code> -- allowing for <code>null</code>.
+	 *
+	 * @param left
+	 *            The left object to compare; may be <code>null</code>.
+	 * @param right
+	 *            The right object to compare; may be <code>null</code>.
+	 * @return <code>true</code> if the two objects are equivalent; <code>false</code> otherwise.
+	 */
+	public static final boolean equals(final Object left, final Object right) {
+		return left == null ? right == null : ((right != null) && left.equals(right));
+	}
+
+	/**
+	 * Tests whether two arrays of objects are equal to each other. The arrays must not be
+	 * <code>null</code>, but their elements may be <code>null</code>.
+	 *
+	 * @param leftArray
+	 *            The left array to compare; may be <code>null</code>, and may be empty and may
+	 *            contain <code>null</code> elements.
+	 * @param rightArray
+	 *            The right array to compare; may be <code>null</code>, and may be empty and may
+	 *            contain <code>null</code> elements.
+	 * @return <code>true</code> if the arrays are equal length and the elements at the same
+	 *         position are equal; <code>false</code> otherwise.
+	 */
+	public static final boolean equals(final Object[] leftArray, final Object[] rightArray) {
+		if (leftArray == rightArray) {
+			return true;
+		}
+
+		if (leftArray == null) {
+			return (rightArray == null);
+		} else if (rightArray == null) {
+			return false;
+		}
+
+		if (leftArray.length != rightArray.length) {
+			return false;
+		}
+
+		for (int i = 0; i < leftArray.length; i++) {
+			final Object left = leftArray[i];
+			final Object right = rightArray[i];
+			final boolean equal = (left == null) ? (right == null) : (left.equals(right));
+			if (!equal) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Provides a hash code based on the given integer value.
+	 *
+	 * @param i
+	 *            The integer value
+	 * @return <code>i</code>
+	 */
+	public static final int hashCode(final int i) {
+		return i;
+	}
+
+	/**
+	 * Provides a hash code for the object -- defending against <code>null</code>.
+	 *
+	 * @param object
+	 *            The object for which a hash code is required.
+	 * @return <code>object.hashCode</code> or <code>0</code> if <code>object</code> if
+	 *         <code>null</code>.
+	 */
+	public static final int hashCode(final Object object) {
+		return object != null ? object.hashCode() : 0;
+	}
+
+	/**
+	 * Computes the hash code for an array of objects, but with defense against <code>null</code>.
+	 *
+	 * @param objects
+	 *            The array of objects for which a hash code is needed; may be <code>null</code>.
+	 * @return The hash code for <code>objects</code>; or <code>0</code> if <code>objects</code> is
+	 *         <code>null</code>.
+	 */
+	public static final int hashCode(final Object[] objects) {
+		if (objects == null) {
+			return 0;
+		}
+
+		int hashCode = 89;
+		for (int i = 0; i < objects.length; i++) {
+			final Object object = objects[i];
+			if (object != null) {
+				hashCode = hashCode * 31 + object.hashCode();
+			}
+		}
+
+		return hashCode;
+	}
+
+	/**
+	 * Checks whether the second array is a subsequence of the first array, and that they share
+	 * common starting elements.
+	 *
+	 * @param left
+	 *            The first array to compare (large); may be <code>null</code>.
+	 * @param right
+	 *            The second array to compare (small); may be <code>null</code>.
+	 * @param equals
+	 *            Whether it is allowed for the two arrays to be equivalent.
+	 * @return <code>true</code> if the first arrays starts with the second list; <code>false</code>
+	 *         otherwise.
+	 */
+	public static final boolean startsWith(final Object[] left, final Object[] right,
+			final boolean equals) {
+		if (left == null || right == null) {
+			return false;
+		}
+
+		int l = left.length;
+		int r = right.length;
+
+		if (r > l || !equals && r == l) {
+			return false;
+		}
+
+		for (int i = 0; i < r; i++) {
+			if (!equals(left[i], right[i])) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Converts an array into a string representation that is suitable for debugging.
+	 *
+	 * @param array
+	 *            The array to convert; may be <code>null</code>.
+	 * @return The string representation of the array; never <code>null</code>.
+	 */
+	public static final String toString(final Object[] array) {
+		if (array == null) {
+			return "null"; //$NON-NLS-1$
+		}
+
+		final StringBuffer buffer = new StringBuffer();
+		buffer.append('[');
+
+		final int length = array.length;
+		for (int i = 0; i < length; i++) {
+			if (i != 0) {
+				buffer.append(',');
+			}
+			final Object object = array[i];
+			final String element = String.valueOf(object);
+			buffer.append(element);
+		}
+		buffer.append(']');
+
+		return buffer.toString();
+	}
+
+	/**
+	 * Provides a translation of a particular key from the resource bundle.
+	 *
+	 * @param resourceBundle
+	 *            The key to look up in the resource bundle; should not be <code>null</code>.
+	 * @param key
+	 *            The key to look up in the resource bundle; should not be <code>null</code>.
+	 * @param defaultString
+	 *            The value to return if the resource cannot be found; may be <code>null</code>.
+	 * @return The value of the translated resource at <code>key</code>. If the key cannot be found,
+	 *         then it is simply the <code>defaultString</code>.
+	 */
+	public static final String translateString(final ResourceBundle resourceBundle,
+			final String key, final String defaultString) {
+		if (resourceBundle != null && key != null) {
+			try {
+				final String translatedString = resourceBundle.getString(key);
+
+				if (translatedString != null) {
+					return translatedString;
+				}
+			} catch (MissingResourceException eMissingResource) {
+				// Such is life. We'll return the key
+			}
+		}
+
+		return defaultString;
+	}
+
+	/**
+	 * Foundation replacement for <code>String#replaceAll(String,
+	 * String)</code>, but <strong>without support for regular expressions</strong>.
+	 *
+	 * @param src
+	 *            the original string
+	 * @param find
+	 *            the string to find
+	 * @param replacement
+	 *            the replacement string
+	 * @return the new string, with all occurrences of <code>find</code> replaced by
+	 *         <code>replacement</code> (not using regular expressions)
+	 * @since 3.4
+	 */
+	public static final String replaceAll(String src, String find, String replacement) {
+		final int len = src.length();
+		final int findLen = find.length();
+
+		int idx = src.indexOf(find);
+		if (idx < 0) {
+			return src;
+		}
+
+		StringBuffer buf = new StringBuffer();
+		int beginIndex = 0;
+		while (idx != -1 && idx < len) {
+			buf.append(src.substring(beginIndex, idx));
+			buf.append(replacement);
+
+			beginIndex = idx + findLen;
+			if (beginIndex < len) {
+				idx = src.indexOf(find, beginIndex);
+			} else {
+				idx = -1;
+			}
+		}
+		if (beginIndex < len) {
+			buf.append(src.substring(beginIndex, (idx == -1 ? len : idx)));
+		}
+		return buf.toString();
+	}
+
+	/**
+	 * This class should never be constructed.
+	 */
+	private Util() {
+		// Not allowed.
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/WorkbenchLogger.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/WorkbenchLogger.java
new file mode 100644
index 0000000..c5e76a6
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/WorkbenchLogger.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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.internal.workbench;
+
+import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.service.debug.DebugOptions;
+import org.eclipse.osgi.service.debug.DebugTrace;
+
+/**
+ * The workbench implementation of the logger service.
+ */
+public final class WorkbenchLogger extends Logger {
+	protected DebugTrace trace;
+	protected FrameworkLog log;
+	private String bundleName;
+
+	/**
+	 * Creates a new workbench logger
+	 */
+	@Inject
+	public WorkbenchLogger(@Optional @Named("logger.bundlename") String bundleName) {
+		super();
+		this.bundleName = bundleName == null ? Activator.PI_WORKBENCH : bundleName;
+	}
+
+	@Override
+	public void debug(Throwable t) {
+		debug(t, null);
+	}
+
+	@Override
+	public void debug(Throwable t, String message) {
+		trace(t, message);
+	}
+
+	@Override
+	public void error(Throwable t, String message) {
+		log(new Status(IStatus.ERROR, bundleName, message, t));
+	}
+
+	/**
+	 * Copied from PlatformLogWriter in core runtime.
+	 */
+	private static FrameworkLogEntry getLog(IStatus status) {
+		Throwable t = status.getException();
+		ArrayList<FrameworkLogEntry> childlist = new ArrayList<>();
+
+		int stackCode = t instanceof CoreException ? 1 : 0;
+		// ensure a substatus inside a CoreException is properly logged
+		if (stackCode == 1) {
+			IStatus coreStatus = ((CoreException) t).getStatus();
+			if (coreStatus != null) {
+				childlist.add(getLog(coreStatus));
+			}
+		}
+
+		if (status.isMultiStatus()) {
+			IStatus[] children = status.getChildren();
+			for (int i = 0; i < children.length; i++) {
+				childlist.add(getLog(children[i]));
+			}
+		}
+
+		FrameworkLogEntry[] children = childlist.size() == 0 ? null
+				: childlist.toArray(new FrameworkLogEntry[childlist.size()]);
+
+		return new FrameworkLogEntry(status.getPlugin(), status.getSeverity(), status.getCode(),
+				status.getMessage(), stackCode, t, children);
+	}
+
+	@Override
+	public void info(Throwable t, String message) {
+		log(new Status(IStatus.INFO, bundleName, message, t));
+	}
+
+	@Override
+	public boolean isDebugEnabled() {
+		return false;
+	}
+
+	@Override
+	public boolean isErrorEnabled() {
+		return true;
+	}
+
+	@Override
+	public boolean isInfoEnabled() {
+		return true;
+	}
+
+	@Override
+	public boolean isTraceEnabled() {
+		return false;
+	}
+
+	@Override
+	public boolean isWarnEnabled() {
+		return true;
+	}
+
+	private void log(IStatus status) {
+		if (log != null) {
+			log.log(getLog(status));
+		} else {
+			System.out.println(status.getMessage());
+			if (status.getException() != null)
+				status.getException().printStackTrace();
+		}
+	}
+
+	/**
+	 * Sets the debug options service for this logger.
+	 *
+	 * @param options
+	 *            The debug options to be used by this logger
+	 */
+	@Inject
+	public void setDebugOptions(DebugOptions options) {
+		if (options != null) {
+			this.trace = options.newDebugTrace(bundleName, WorkbenchLogger.class);
+		}
+	}
+
+	/**
+	 * @param log
+	 */
+	@Inject
+	public void setFrameworkLog(FrameworkLog log) {
+		this.log = log;
+	}
+
+	@Override
+	public void trace(Throwable t, String message) {
+		if (trace != null) {
+			trace.trace(null, message, t);
+		} else {
+			System.out.println(message);
+			if (t != null)
+				t.printStackTrace();
+		}
+	}
+
+	@Override
+	public void warn(Throwable t, String message) {
+		log(new Status(IStatus.WARNING, bundleName, message, t));
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/XMLModelReconciler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/XMLModelReconciler.java
new file mode 100644
index 0000000..bcf2888
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/XMLModelReconciler.java
@@ -0,0 +1,1996 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.MContribution;
+import org.eclipse.e4.ui.model.application.commands.MBindingTable;
+import org.eclipse.e4.ui.model.application.commands.MBindingTableContainer;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MCommandParameter;
+import org.eclipse.e4.ui.model.application.commands.MHandler;
+import org.eclipse.e4.ui.model.application.commands.MHandlerContainer;
+import org.eclipse.e4.ui.model.application.commands.MKeyBinding;
+import org.eclipse.e4.ui.model.application.commands.MParameter;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptorContainer;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.ItemType;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContributions;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContributions;
+import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MTrimContributions;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+import org.eclipse.e4.ui.workbench.modeling.IDelta;
+import org.eclipse.e4.ui.workbench.modeling.ModelDelta;
+import org.eclipse.e4.ui.workbench.modeling.ModelReconciler;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.change.ChangeDescription;
+import org.eclipse.emf.ecore.change.FeatureChange;
+import org.eclipse.emf.ecore.change.util.ChangeRecorder;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class XMLModelReconciler extends ModelReconciler {
+
+	private static final String XMIID_ATTNAME = "xmiId"; //$NON-NLS-1$
+
+	private static final String REFERENCE_ELEMENT_NAME = "reference"; //$NON-NLS-1$
+	private static final String ORIGINALREFERENCE_ELEMENT_NAME = "originalReference"; //$NON-NLS-1$
+
+	private static final String NAMESPACE_ATTNAME = "e4namespace"; //$NON-NLS-1$
+	private static final String OLD_CONTRIBUTION_URI_PREFIX = "platform:/plugin/"; //$NON-NLS-1$
+	private static final String NEW_CONTRIBUTION_URI_PREFIX = "bundleclass://"; //$NON-NLS-1$
+
+	/**
+	 * The name of the root element that describes the model deltas in XML form (value is
+	 * <code>changes</code>).
+	 */
+	private static final String CHANGES_ELEMENT_NAME = "changes"; //$NON-NLS-1$
+
+	/**
+	 * The name of the attribute that describes the version of the model deltas (value is
+	 * <code>version</code>).
+	 */
+	private static final String VERSION_ATTNAME = "version"; //$NON-NLS-1$
+
+	/**
+	 * The version of the model deltas.
+	 *
+	 * <ul>
+	 * <li>1.1 - introduced direct references to binding contexts instead of using string ids (see
+	 * bug 320171 and bug 338444)</li>
+	 * <li>1.0 (no change) - the model was updated with MArea, code was inserted to handle this case
+	 * so the version number was not actually increased (see bug 328388)</li>
+	 * <li>1.0 - first version of the model that went out for 4.0</li>
+	 * </ul>
+	 */
+	// a new string is constructed because we do not know want the value to be inlined
+	private static final String VERSION_NUMBER = new String("1.1"); //$NON-NLS-1$
+
+	/**
+	 * An attribute for describing the type of the object in question (value is <code>type</code>).
+	 */
+	private static final String TYPE_ATTNAME = "type"; //$NON-NLS-1$
+
+	private static final String UNSET_ATTNAME = "unset"; //$NON-NLS-1$
+	private static final String UNSET_ATTVALUE_TRUE = "true"; //$NON-NLS-1$
+
+	private static final String ENTRY_ATTVALUE_KEY = "key"; //$NON-NLS-1$
+	private static final String ENTRY_ATTVALUE_VALUE = "value"; //$NON-NLS-1$
+
+	private ChangeRecorder changeRecorder;
+
+	private ChangeDescription changeDescription;
+
+	private EObject rootObject;
+
+	/**
+	 * A map of all the objects that were originally defined in the model.
+	 */
+	private WeakHashMap<EObject, EObject> originalObjects = new WeakHashMap<EObject, EObject>();
+
+	/**
+	 * Records all of the objects in the original model so that we can determine whether an element
+	 * was originally a part of the defined model or not.
+	 */
+	private void record() {
+		originalObjects.clear();
+		originalObjects.put(rootObject, null);
+		Iterator<EObject> it = rootObject.eAllContents();
+		while (it.hasNext()) {
+			EObject object = it.next();
+			originalObjects.put(object, null);
+		}
+	}
+
+	@Override
+	public void recordChanges(Object object) {
+		Assert.isNotNull(object);
+		rootObject = (EObject) object;
+		changeRecorder = new ChangeRecorder(rootObject) {
+			@Override
+			protected boolean shouldRecord(EStructuralFeature feature, EObject eObject) {
+				return !feature.isTransient() && super.shouldRecord(feature, eObject);
+			}
+
+			@Override
+			protected boolean shouldRecord(EStructuralFeature feature, EReference containment,
+					Notification notification, EObject eObject) {
+				return !feature.isTransient()
+						&& super.shouldRecord(feature, containment, notification, eObject);
+			}
+		};
+		changeDescription = null;
+		record();
+	}
+
+	static List<Object> getReferences(Object object) {
+		Iterator<EObject> it = ((EObject) object).eAllContents();
+		List<Object> references = new LinkedList<Object>();
+		while (it.hasNext()) {
+			Object reference = it.next();
+			references.add(reference);
+		}
+		return references;
+	}
+
+	@Override
+	public Collection<ModelDelta> constructDeltas(Object object, Object serializedState) {
+		rootObject = (EObject) object;
+		List<Object> references = getReferences(rootObject);
+
+		Document document = (Document) serializedState;
+
+		Collection<ModelDelta> deltas = new LinkedList<ModelDelta>();
+
+		Element rootElement = document.getDocumentElement();
+		String version = rootElement.getAttribute(VERSION_ATTNAME);
+		try {
+			if (version == null || version.length() == 0
+					|| Double.parseDouble(version) < Double.parseDouble(VERSION_NUMBER)) {
+				return deltas;
+			}
+		} catch (NumberFormatException e) {
+			// some corrupt versioning, ignore this deltas file
+			return deltas;
+		}
+
+		NodeList rootNodeList = (NodeList) rootElement;
+		for (int i = 0; i < rootNodeList.getLength(); i++) {
+			Node node = rootNodeList.item(i);
+			if (node instanceof Element) {
+				Element element = (Element) node;
+				constructDeltas(deltas, references, rootObject, element,
+						element.getAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME));
+			}
+		}
+
+		return deltas;
+	}
+
+	private static EStructuralFeature getStructuralFeature(EObject object, String featureName) {
+		for (EStructuralFeature sf : object.eClass().getEAllStructuralFeatures()) {
+			if (sf.getName().equals(featureName)) {
+				return sf;
+			}
+		}
+		return null;
+	}
+
+	private Object getValue(EStructuralFeature feature, String featureValue) {
+		Class<?> instanceClass = feature.getEType().getInstanceClass();
+		if (instanceClass == String.class) {
+			return featureValue;
+		} else if (instanceClass == int.class) {
+			return Integer.valueOf(featureValue);
+		} else if (instanceClass == boolean.class) {
+			return Boolean.valueOf(featureValue);
+		} else if (feature == UiPackageImpl.eINSTANCE.getGenericTrimContainer_Side()) {
+			return SideValue.getByName(featureValue);
+		} else if (feature == MenuPackageImpl.eINSTANCE.getItem_Type()) {
+			return ItemType.getByName(featureValue);
+		}
+		return null;
+	}
+
+	static Object findReference(List<Object> references, String id) {
+		for (Object reference : references) {
+			if (reference instanceof MApplicationElement && getLocalId(reference).equals(id)) {
+				return reference;
+			}
+		}
+
+		return null;
+	}
+
+	private boolean constructDeltas(Collection<ModelDelta> deltas, List<Object> references,
+			EObject object, Element element, String id) {
+		if (object instanceof MApplicationElement || object instanceof MKeyBinding) {
+			if (getLocalId(object).equals(id)) {
+				constructDeltas(deltas, references, object, element);
+				return true;
+			}
+		}
+
+		if (object instanceof MElementContainer<?>) {
+			for (Object child : ((MElementContainer<?>) object).getChildren()) {
+				if (constructDeltas(deltas, references, (EObject) child, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MPerspective) {
+			for (MWindow window : ((MPerspective) object).getWindows()) {
+				if (constructDeltas(deltas, references, (EObject) window, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MBindingTableContainer) {
+			for (MBindingTable bindingTable : ((MBindingTableContainer) object).getBindingTables()) {
+				if (constructDeltas(deltas, references, (EObject) bindingTable, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MBindingTable) {
+			for (MKeyBinding keyBinding : ((MBindingTable) object).getBindings()) {
+				if (constructDeltas(deltas, references, (EObject) keyBinding, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MHandlerContainer) {
+			for (MHandler handler : ((MHandlerContainer) object).getHandlers()) {
+				if (constructDeltas(deltas, references, (EObject) handler, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MApplication) {
+			for (MCommand command : ((MApplication) object).getCommands()) {
+				if (constructDeltas(deltas, references, (EObject) command, element, id)) {
+					return true;
+				}
+			}
+
+			for (MAddon addon : ((MApplication) object).getAddons()) {
+				if (constructDeltas(deltas, references, (EObject) addon, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MPartDescriptorContainer) {
+			for (MPartDescriptor descriptor : ((MPartDescriptorContainer) object).getDescriptors()) {
+				if (constructDeltas(deltas, references, (EObject) descriptor, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MPart) {
+			MPart part = (MPart) object;
+
+			for (MMenu menu : part.getMenus()) {
+				if (constructDeltas(deltas, references, (EObject) menu, element, id)) {
+					return true;
+				}
+			}
+
+			MToolBar toolBar = part.getToolbar();
+			if (toolBar != null) {
+				if (constructDeltas(deltas, references, (EObject) toolBar, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MMenuContributions) {
+			for (MMenuContribution contribution : ((MMenuContributions) object)
+					.getMenuContributions()) {
+				if (constructDeltas(deltas, references, (EObject) contribution, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MToolBarContributions) {
+			for (MToolBarContribution contribution : ((MToolBarContributions) object)
+					.getToolBarContributions()) {
+				if (constructDeltas(deltas, references, (EObject) contribution, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MTrimContributions) {
+			for (MTrimContribution contribution : ((MTrimContributions) object)
+					.getTrimContributions()) {
+				if (constructDeltas(deltas, references, (EObject) contribution, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		if (object instanceof MWindow) {
+			MWindow window = (MWindow) object;
+			if (constructDeltas(deltas, references, (EObject) window.getMainMenu(), element, id)) {
+				return true;
+			}
+
+			if (object instanceof MTrimmedWindow) {
+				MTrimmedWindow trimmedWindow = (MTrimmedWindow) object;
+				for (MTrimBar trimBar : trimmedWindow.getTrimBars()) {
+					if (constructDeltas(deltas, references, (EObject) trimBar, element, id)) {
+						return true;
+					}
+				}
+			}
+		}
+
+		if (object instanceof MHandledItem) {
+			for (MParameter parameter : ((MHandledItem) object).getParameters()) {
+				if (constructDeltas(deltas, references, (EObject) parameter, element, id)) {
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	private void constructDeltas(Collection<ModelDelta> deltas, List<Object> references,
+			EObject object, Element element) {
+		String elementName = element.getNodeName();
+		if (elementName.equals(CONTEXT_PROPERTIES_ATTNAME)) {
+			constructEntryDelta(deltas, UiPackageImpl.eINSTANCE.getContext_Properties(), object,
+					element);
+		} else if (elementName.equals(APPLICATIONELEMENT_PERSISTEDSTATE_ATTNAME)) {
+			constructEntryDelta(deltas,
+					ApplicationPackageImpl.eINSTANCE.getApplicationElement_PersistedState(),
+					object, element);
+		} else {
+			constructObjectDeltas(deltas, references, object, element);
+		}
+	}
+
+	private void constructEntryDelta(Collection<ModelDelta> deltas, EStructuralFeature feature,
+			EObject object, Element element) {
+		if (element.getAttribute(UNSET_ATTNAME).equals(UNSET_ATTVALUE_TRUE)) {
+			EMFDeltaEntrySet delta = new EMFDeltaEntrySet(object, feature,
+					element.getAttribute(ENTRY_ATTVALUE_KEY), null);
+			deltas.add(delta);
+		} else {
+			EMFDeltaEntrySet delta = new EMFDeltaEntrySet(object, feature,
+					element.getAttribute(ENTRY_ATTVALUE_KEY),
+					element.getAttribute(ENTRY_ATTVALUE_VALUE));
+			deltas.add(delta);
+		}
+	}
+
+	private void constructObjectDeltas(Collection<ModelDelta> deltas, List<Object> references,
+			EObject object, Element element) {
+		NodeList nodeList = (NodeList) element;
+		for (int i = 0; i < nodeList.getLength(); i++) {
+			Node node = nodeList.item(i);
+			if (!(node instanceof Element)) {
+				continue;
+			}
+
+			Element innerElement = (Element) node;
+			String featureName = innerElement.getNodeName();
+			EStructuralFeature feature = getStructuralFeature(object, featureName);
+			if (feature != null) {
+				if (isChainedReference(featureName)) {
+					ModelDelta delta = createMultiReferenceDelta(deltas, references, object,
+							feature, innerElement);
+					deltas.add(delta);
+				} else if (isUnset(innerElement)) {
+					ModelDelta delta = new EMFModelDeltaUnset(object, feature);
+					deltas.add(delta);
+				} else if (isDirectReference(featureName)) {
+					ModelDelta delta = createDirectReferenceDelta(deltas, references, object,
+							feature, innerElement);
+					deltas.add(delta);
+				} else if (isIndirectReference(featureName)) {
+					ModelDelta delta = createIndirectReferenceDelta(references, object, feature,
+							innerElement);
+					deltas.add(delta);
+				} else if (isUnorderedChainedAttribute(featureName)) {
+					ModelDelta delta = createUnorderedChainedAttributeDelta(object, feature,
+							innerElement, featureName);
+					deltas.add(delta);
+				} else if (isStringToStringMap(featureName)) {
+					ModelDelta delta = createMapDelta(object, innerElement, feature);
+					deltas.add(delta);
+				} else {
+					ModelDelta delta = createAttributeDelta(object, feature, innerElement,
+							featureName);
+					deltas.add(delta);
+				}
+			}
+		}
+	}
+
+	private ModelDelta createDirectReferenceDelta(Collection<ModelDelta> deltas,
+			List<Object> references, EObject eObject, EStructuralFeature feature, Element node) {
+		NodeList referencedIds = (NodeList) node;
+		Element reference = getFirstElement(referencedIds);
+		String referenceId = reference.getAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME);
+
+		Object match = findReference(references, referenceId);
+		if (match == null) {
+			// couldn't find a reference, must be a new object
+			match = createObject(deltas, reference, references);
+		}
+
+		return new EMFModelDeltaSet(eObject, feature, match);
+	}
+
+	private static Element getFirstElement(NodeList list) {
+		for (int i = 0; i < list.getLength(); i++) {
+			Node item = list.item(i);
+			if (item instanceof Element) {
+				return (Element) item;
+			}
+		}
+		return null;
+	}
+
+	private ModelDelta createIndirectReferenceDelta(List<Object> references, EObject eObject,
+			EStructuralFeature feature, Element node) {
+		NodeList referencedIds = (NodeList) node;
+
+		Element reference = getFirstElement(referencedIds);
+		String referenceId = reference.getAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME);
+
+		Object match = findReference(references, referenceId);
+		if (match == null) {
+			return createDelayedDelta(eObject, feature, reference);
+		}
+
+		return new EMFModelDeltaSet(eObject, feature, match);
+	}
+
+	private ModelDelta createMapDelta(EObject object, Element innerElement,
+			EStructuralFeature feature) {
+		Map<String, String> deltaMap = new HashMap<String, String>();
+		NodeList attributes = (NodeList) innerElement;
+		for (int j = 0; j < attributes.getLength(); j++) {
+			Node entry = attributes.item(j);
+			if (entry instanceof Element) {
+				Element keyValue = (Element) entry;
+				String key = keyValue.getAttribute(ENTRY_ATTVALUE_KEY);
+				String value = keyValue.getAttribute(ENTRY_ATTVALUE_VALUE);
+				deltaMap.put(key, value);
+			}
+		}
+		return new EMFDeltaMapSet(object, feature, deltaMap);
+	}
+
+	private ModelDelta createDelayedDelta(EObject object, EStructuralFeature feature,
+			Element element) {
+		String referenceId = element.getAttribute(XMIID_ATTNAME);
+		return new EMFModelDeltaDelayedSet(object, feature, rootObject, referenceId);
+	}
+
+	public static List<?> threeWayMerge(List<?> originalReferences, List<?> userReferences,
+			List<?> currentReferences) {
+		int userSize = userReferences.size();
+		int originalSize = originalReferences.size();
+
+		if (userSize == 0) {
+			// the user removed all the original parts
+			List<Object> collectedReferences = new ArrayList<Object>(currentReferences);
+			collectedReferences.removeAll(originalReferences);
+			return collectedReferences;
+		} else if (originalSize == 0) {
+			List<Object> collectedReferences = new ArrayList<Object>(userReferences);
+			collectedReferences.addAll(currentReferences);
+			return collectedReferences;
+		} else if (currentReferences.isEmpty()) {
+			// currently not referencing anything, so just return what the user had exactly
+			return userReferences;
+		} else if (currentReferences.size() == originalSize
+				&& currentReferences.containsAll(originalReferences)) {
+			// since both versions contain the same thing, just use whatever the user had
+			return userReferences;
+		}
+
+		if (originalReferences.containsAll(userReferences)
+				&& !userReferences.containsAll(originalReferences)) {
+			List<Object> collectedReferences2 = new ArrayList<Object>(originalReferences);
+			collectedReferences2.removeAll(userReferences);
+
+			List<Object> collectedReferences = new ArrayList<Object>(currentReferences);
+			collectedReferences.removeAll(collectedReferences2);
+
+			return collectedReferences;
+		}
+
+		List<Position> positions = new ArrayList<Position>();
+
+		for (int i = 0; i < userReferences.size(); i++) {
+			Object user = userReferences.get(i);
+
+			Position p = getPosition(originalReferences, userReferences, currentReferences, user, i);
+			if (p != null) {
+				positions.add(p);
+			}
+		}
+
+		List<Object> collectedRefs = new ArrayList<Object>(currentReferences);
+
+		for (Position position : positions) {
+			Object after = position.getAfter();
+			if (after != null) {
+				int index = currentReferences.indexOf(after);
+				collectedRefs.add(index + 1, position.getObject());
+			}
+
+			Object before = position.getBefore();
+			if (before != null) {
+				int index = currentReferences.indexOf(before);
+				collectedRefs.add(index, position.getObject());
+			}
+		}
+
+		return collectedRefs;
+	}
+
+	private static Position getPosition(List<?> originalReferences, List<?> userReferences,
+			List<?> currentReferences, Object object, int originalIndex) {
+		int index = originalReferences.indexOf(object);
+		if (index == -1) {
+			Object after = null;
+			for (int i = originalIndex - 1; i > -1; i--) {
+				Object afterCandidate = userReferences.get(i);
+				int afterIndex = currentReferences.indexOf(afterCandidate);
+				if (afterIndex != -1) {
+					after = afterCandidate;
+					break;
+				}
+			}
+
+			Object before = null;
+			for (int i = originalIndex + 1; i < userReferences.size(); i++) {
+				Object beforeCandidate = userReferences.get(i);
+				int beforeIndex = currentReferences.indexOf(beforeCandidate);
+				if (beforeIndex != -1) {
+					before = beforeCandidate;
+					break;
+				}
+			}
+
+			return new Position(object, after, before);
+		}
+		return null;
+	}
+
+	static class Position {
+
+		private final Object object;
+		private final Object after;
+		private final Object before;
+
+		Position(Object object, Object after, Object before) {
+			this.object = object;
+			this.after = after;
+			this.before = before;
+		}
+
+		public Object getObject() {
+			return object;
+		}
+
+		public Object getBefore() {
+			return before;
+		}
+
+		public Object getAfter() {
+			return after;
+		}
+
+	}
+
+	private ModelDelta createMultiReferenceDelta(Collection<ModelDelta> deltas,
+			List<Object> references, EObject eObject, EStructuralFeature feature, Element node) {
+		NodeList referencedIds = (NodeList) node;
+		List<Object> originalReferences = new ArrayList<Object>();
+		List<Object> userReferences = new ArrayList<Object>();
+		List<?> currentReferences = (List<?>) eObject.eGet(feature);
+
+		for (int i = 0; i < referencedIds.getLength(); i++) {
+			Node item = referencedIds.item(i);
+			if (item instanceof Element) {
+				Element reference = (Element) item;
+				if (isUnset(reference)) {
+					userReferences.add(createObject(deltas, reference, references));
+				} else {
+					String referenceId = reference
+							.getAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME);
+					Object match = findReference(references, referenceId);
+					if (match != null) {
+						// determine if this was a reference set by the user or a reference that was
+						// originally defined by the application
+						if (reference.getNodeName().equals(REFERENCE_ELEMENT_NAME)) {
+							userReferences.add(match);
+						} else {
+							originalReferences.add(match);
+						}
+					}
+				}
+			}
+		}
+
+		return new EMFModelDeltaThreeWayDelayedSet(eObject, feature, originalReferences,
+				userReferences, currentReferences);
+	}
+
+	private static EObject createObject(String namespace, String type) {
+		EFactory factory = EPackage.Registry.INSTANCE.getEFactory(namespace);
+		for (EClassifier classifier : factory.getEPackage().getEClassifiers()) {
+			if (classifier instanceof EClass) {
+				EClass cls = (EClass) classifier;
+				if (cls.getInstanceClassName().equals(type)) {
+					return factory.create(cls);
+				}
+			}
+		}
+		return null;
+	}
+
+	private Object getReference(Collection<ModelDelta> deltas, Element element,
+			List<Object> references) {
+		String id = element.getAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME);
+		if (!id.equals("")) { //$NON-NLS-1$
+			return findReference(references, id);
+		}
+		return createObject(deltas, element, references);
+	}
+
+	private Object createObject(Collection<ModelDelta> deltas, Element element,
+			List<Object> references) {
+		String typeName = element.getAttribute(TYPE_ATTNAME);
+		String namespace = element.getAttribute(NAMESPACE_ATTNAME);
+
+		EObject object = createObject(namespace, typeName);
+		CompositeDelta compositeDelta = new CompositeDelta(object);
+
+		E4XMIResource resource = (E4XMIResource) rootObject.eResource();
+		resource.setInternalId(object, element.getAttribute(XMIID_ATTNAME));
+
+		NodeList elementAttributes = (NodeList) element;
+		for (int i = 0; i < elementAttributes.getLength(); i++) {
+			Node node = elementAttributes.item(i);
+			if (node instanceof Element) {
+				Element item = (Element) node;
+				if (!isUnset(item)) {
+					String attributeName = item.getNodeName();
+					EStructuralFeature attributeFeature = getStructuralFeature(object,
+							attributeName);
+					if (attributeFeature != null) {
+						if (isDirectReference(attributeName)) {
+							String id = item.getAttribute(attributeName);
+							Object objectReference = findReference(references, id);
+							if (objectReference == null) {
+								objectReference = createObject(deltas,
+										getFirstElement((NodeList) item), references);
+							}
+
+							IDelta delta = new EMFModelDeltaSet(object, attributeFeature,
+									objectReference);
+							compositeDelta.add(delta);
+						} else if (isIndirectReference(attributeName)) {
+							String id = item.getAttribute(attributeName);
+							Object objectReference = findReference(references, id);
+							if (objectReference == null) {
+								NodeList list = (NodeList) item;
+								Element refElement = getFirstElement(list);
+								if (refElement != null) {
+									ModelDelta delta = createDelayedDelta(object, attributeFeature,
+											refElement);
+									deltas.add(delta);
+								}
+							} else {
+								IDelta delta = new EMFModelDeltaSet(object, attributeFeature,
+										objectReference);
+								compositeDelta.add(delta);
+							}
+						} else if (isChainedReference(attributeName)) {
+							List<Object> objectReferences = new ArrayList<Object>();
+							NodeList objectReferenceNodes = (NodeList) item;
+
+							for (int j = 0; j < objectReferenceNodes.getLength(); j++) {
+								Node refNode = objectReferenceNodes.item(j);
+								if (refNode instanceof Element) {
+									Object objectReference = getReference(deltas,
+											(Element) refNode, references);
+									if (objectReference != null) {
+										objectReferences.add(objectReference);
+									}
+								}
+							}
+
+							IDelta delta = new EMFModelDeltaSet(object, attributeFeature,
+									objectReferences);
+							compositeDelta.add(delta);
+						} else if (isUnorderedChainedAttribute(attributeName)) {
+							ModelDelta delta = createUnorderedChainedAttributeDelta(object,
+									attributeFeature, item, attributeName);
+							deltas.add(delta);
+						} else if (isStringToStringMap(attributeName)) {
+							EStructuralFeature feature = getStructuralFeature(object, attributeName);
+							@SuppressWarnings("unchecked")
+							EMap<String, String> map = (EMap<String, String>) object.eGet(feature);
+
+							NodeList attributes = (NodeList) item;
+							for (int j = 0; j < attributes.getLength(); j++) {
+								Node entry = attributes.item(j);
+								if (entry instanceof Element) {
+									Element keyValue = (Element) entry;
+									map.put(keyValue.getAttribute(ENTRY_ATTVALUE_KEY),
+											keyValue.getAttribute(ENTRY_ATTVALUE_VALUE));
+								}
+							}
+						} else {
+							Object value = getValue(attributeFeature,
+									item.getAttribute(attributeName));
+							if (CONTRIBUTION_URI_ATTNAME.equals(attributeFeature.getName()))
+								value = ((String) value).replaceFirst(OLD_CONTRIBUTION_URI_PREFIX,
+										NEW_CONTRIBUTION_URI_PREFIX);
+							object.eSet(attributeFeature, value);
+						}
+					}
+				}
+			}
+		}
+
+		return compositeDelta;
+	}
+
+	private ModelDelta createUnorderedChainedAttributeDelta(EObject object,
+			EStructuralFeature feature, Element node, String featureName) {
+		Set<Object> values = new HashSet<Object>();
+		NodeList attributes = (NodeList) node;
+		for (int j = 0; j < attributes.getLength(); j++) {
+			Node item = attributes.item(j);
+			if (item instanceof Element) {
+				Element attribute = (Element) item;
+				Object value = getValue(feature, attribute.getAttribute(featureName));
+				values.add(value);
+			}
+		}
+
+		List<?> currentValues = (List<?>) object.eGet(feature);
+		values.addAll(currentValues);
+
+		return new EMFModelDeltaSet(object, feature, new ArrayList<Object>(values));
+	}
+
+	private ModelDelta createAttributeDelta(EObject eObject, EStructuralFeature feature,
+			Element node, String featureName) {
+		Object value = getValue(feature, node.getAttribute(featureName));
+		return new EMFModelDeltaSet(eObject, feature, value);
+	}
+
+	private Document createDocument() {
+		try {
+			return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private ChangeDescription calculateDeltas() {
+		if (changeDescription == null) {
+			changeDescription = changeRecorder.endRecording();
+		}
+		return changeDescription;
+	}
+
+	@Override
+	public Object serialize() {
+		calculateDeltas();
+
+		// begin construction of the XML document
+		Document document = createDocument();
+		Element root = document.createElement(CHANGES_ELEMENT_NAME);
+		root.setAttribute(VERSION_ATTNAME, VERSION_NUMBER);
+		document.appendChild(root);
+
+		EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription.getObjectChanges();
+		for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+			EObject object = entry.getKey();
+			// persist every change
+			Element persistedElement = persist(document, entry, object);
+			if (persistedElement != null) {
+				// append the change to the document
+				root.appendChild(persistedElement);
+			}
+		}
+
+		return document;
+	}
+
+	/**
+	 * Returns an XML representation of the changes that have occurred in the specified object. Or
+	 * <code>null</code> if changes pertaining to this object should not be persisted
+	 *
+	 * @param document
+	 *            the root XML document
+	 * @param entry
+	 *            a list of changes that have occurred to the object
+	 * @param object
+	 *            the object to persist
+	 * @return an XML representation of the changes of the object, or <code>null</code> if its
+	 *         changes should be ignored
+	 */
+	private Element persist(Document document, Entry<EObject, EList<FeatureChange>> entry,
+			EObject object) {
+		if (object instanceof Entry<?, ?>) {
+			return persistEntry(document, object);
+		}
+		return persistObject(document, entry, object);
+	}
+
+	private Element persistObject(Document document, Entry<EObject, EList<FeatureChange>> entry,
+			EObject object) {
+		if (getOriginalId(object) == null) {
+			return null;
+		}
+
+		Element modelChange = null;
+
+		List<FeatureChange> featureChanges = entry.getValue();
+		for (FeatureChange featureChange : featureChanges) {
+			// we only want to persist deltas of non-transient features
+			if (!featureChange.getFeature().isTransient()) {
+				String featureName = featureChange.getFeatureName();
+				// check if we're interested in this particular feature
+				if (shouldPersist(featureName)) {
+					if (modelChange == null) {
+						// create an element to record this object's changes
+						modelChange = createElement(document, object);
+					}
+
+					// create a delta for this particular change
+					Element deltaElement = createDeltaElement(document, object, featureChange,
+							featureName);
+					modelChange.appendChild(deltaElement);
+				}
+			}
+		}
+
+		return modelChange;
+	}
+
+	private String getEntryElementName(EObject object, Entry<?, ?> entry) {
+		if (object instanceof MContext) {
+			for (Entry<String, String> property : ((MContext) object).getProperties().entrySet()) {
+				if (property == entry) {
+					return CONTEXT_PROPERTIES_ATTNAME;
+				}
+			}
+		}
+
+		if (object instanceof MContribution) {
+			for (Entry<String, String> state : ((MContribution) object).getPersistedState()
+					.entrySet()) {
+				if (state == entry) {
+					return APPLICATIONELEMENT_PERSISTEDSTATE_ATTNAME;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	private Element persistEntry(Document document, EObject object) {
+		EObject container = object.eContainer();
+		if (getOriginalId(container) == null) {
+			return null;
+		}
+
+		Entry<?, ?> entry = (Entry<?, ?>) object;
+		String elementName = getEntryElementName(container, entry);
+		if (elementName == null) {
+			return null;
+		}
+
+		Element element = createElement(document, elementName, container);
+		element.setAttribute(ENTRY_ATTVALUE_KEY, (String) entry.getKey());
+
+		String value = (String) entry.getValue();
+		if (value == null) {
+			element.setAttribute(UNSET_ATTNAME, UNSET_ATTVALUE_TRUE);
+		} else {
+			element.setAttribute(ENTRY_ATTVALUE_VALUE, (String) entry.getValue());
+		}
+
+		return element;
+	}
+
+	private Element createElement(Document document, EObject object) {
+		Class<?> rootInterface = object.getClass().getInterfaces()[0];
+		// this technically doesn't have to be tagged with this name, it's not parsed, but makes the
+		// XML more readable
+		return createElement(document, rootInterface.getCanonicalName(), object);
+	}
+
+	private Element createElement(Document document, String elementName, EObject object) {
+		Element modelChange = document.createElement(elementName);
+		modelChange.setAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME, getOriginalId(object));
+		return modelChange;
+	}
+
+	/**
+	 * Retrieves the id of the object by querying for it from the resource.
+	 *
+	 * @param object
+	 *            the object to retrieve the id for
+	 * @param container
+	 *            the parent container of the object
+	 * @return the object's id as recorded by the containing resource
+	 */
+	private static String getResourceId(EObject object, EObject container) {
+		Resource resource = object.eResource();
+		if (resource instanceof XMLResource) {
+			return ((XMLResource) resource).getID(object);
+		}
+
+		resource = container.eResource();
+		if (resource instanceof XMLResource) {
+			return ((XMLResource) resource).getID(object);
+		}
+
+		throw new IllegalStateException(object + " could not be identified"); //$NON-NLS-1$
+	}
+
+	private String findResourceId(EObject object, EObject container) {
+		Resource resource = object.eResource();
+		if (resource instanceof XMLResource) {
+			return ((XMLResource) resource).getID(object);
+		}
+
+		resource = container.eResource();
+		if (resource instanceof XMLResource) {
+			return ((XMLResource) resource).getID(object);
+		}
+
+		if (originalObjects.containsKey(object)) {
+			resource = rootObject.eResource();
+			if (resource instanceof XMLResource) {
+				return ((XMLResource) resource).getID(object);
+			}
+		}
+
+		throw new IllegalStateException(object + " could not be identified"); //$NON-NLS-1$
+	}
+
+	private static String getLocalId(Object object) {
+		EObject reference = (EObject) object;
+		return getResourceId(reference, reference.eContainer());
+	}
+
+	/**
+	 * Retrieves the original containing parent object of the specified reference. If
+	 * <code>null</code> is returned, the object was not initially known by the change recorder.
+	 *
+	 * @param reference
+	 *            the object to find its original container for
+	 * @return the original parent container of the object, or <code>null</code> if it did not
+	 *         initially exist
+	 */
+	private EObject getOriginalContainer(EObject reference) {
+		if (changeDescription == null) {
+			// no changes have been recorded, just ask the container through EMF directly
+			return reference.eContainer();
+		} else if (!originalObjects.containsKey(reference)) {
+			return null;
+		}
+
+		if (reference instanceof MCommandParameter) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean parametersChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MCommand) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(COMMAND_PARAMETERS_ATTNAME)) {
+							List<?> parameters = (List<?>) change.getValue();
+							for (Object parameter : parameters) {
+								if (parameter == reference) {
+									return key;
+								}
+							}
+
+							parametersChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return parametersChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MParameter) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean parametersChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MHandledItem) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(HANDLEDITEM_PARAMETERS_ATTNAME)) {
+							List<?> parameters = (List<?>) change.getValue();
+							for (Object parameter : parameters) {
+								if (parameter == reference) {
+									return key;
+								}
+							}
+
+							parametersChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return parametersChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MCommand) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean commandsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(APPLICATION_COMMANDS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							commandsChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			if (!commandsChanged) {
+				return reference.eContainer();
+			}
+		}
+
+		if (reference instanceof MMenuContribution) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean menuContributionsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(
+								MENUCONTRIBUTIONS_MENUCONTRIBUTIONS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							menuContributionsChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return menuContributionsChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MToolBarContribution) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean toolBarContributionsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(
+								TOOLBARCONTRIBUTIONS_TOOLBARCONTRIBUTIONS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							toolBarContributionsChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return toolBarContributionsChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MTrimContribution) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean toolBarContributionsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(
+								TRIMCONTRIBUTIONS_TRIMCONTRIBUTIONS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							toolBarContributionsChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return toolBarContributionsChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MBindingTable) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean bindingTablesChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(BINDINGCONTAINER_BINDINGTABLES_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							bindingTablesChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			if (!bindingTablesChanged) {
+				return reference.eContainer();
+			}
+		}
+
+		if (reference instanceof MHandler) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean handlersChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MHandlerContainer) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(HANDLERCONTAINER_HANDLERS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							handlersChanged = true;
+							break;
+						}
+					}
+				}
+			}
+
+			if (!handlersChanged) {
+				return reference.eContainer();
+			}
+		}
+
+		if (reference instanceof MKeyBinding) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+
+			boolean bindingsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MBindingTable) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(BINDINGTABLE_BINDINGS_ATTNAME)) {
+							List<?> commands = (List<?>) change.getValue();
+							for (Object command : commands) {
+								if (command == reference) {
+									return key;
+								}
+							}
+
+							bindingsChanged = true;
+							break;
+						}
+					}
+				}
+			}
+
+			if (!bindingsChanged) {
+				return reference.eContainer();
+			}
+		}
+
+		if (reference instanceof MPartDescriptor) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+			boolean descriptorsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == rootObject) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(
+								PARTDESCRIPTORCONTAINER_DESCRIPTORS_ATTNAME)) {
+							List<?> descriptors = (List<?>) change.getValue();
+							for (Object descriptor : descriptors) {
+								if (descriptor == reference) {
+									return key;
+								}
+							}
+							descriptorsChanged = true;
+							break;
+						}
+					}
+					break;
+				}
+			}
+
+			return descriptorsChanged ? null : reference.eContainer();
+		}
+
+		if (reference instanceof MTrimBar) {
+			EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription
+					.getObjectChanges();
+			boolean trimBarsChanged = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MTrimmedWindow) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(TRIMMEDWINDOW_TRIMBARS_ATTNAME)) {
+							List<?> trimBars = (List<?>) change.getValue();
+							for (Object trimBar : trimBars) {
+								if (trimBar == reference) {
+									return key;
+								}
+							}
+							trimBarsChanged = true;
+							break;
+						}
+					}
+
+					if (trimBarsChanged) {
+						break;
+					}
+				}
+			}
+
+			if (trimBarsChanged) {
+				return null;
+			}
+
+			for (EObject rootChild : rootObject.eContents()) {
+				if (rootChild instanceof MTrimmedWindow) {
+					if (((MTrimmedWindow) rootChild).getTrimBars().contains(reference)) {
+						return rootChild;
+					}
+				}
+			}
+
+			return null;
+		}
+
+		EMap<EObject, EList<FeatureChange>> objectChanges = changeDescription.getObjectChanges();
+		if (reference instanceof MUIElement) {
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == reference) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(UIELEMENT_PARENT_ATTNAME)) {
+							return (EObject) change.getValue();
+						}
+					}
+					break;
+				}
+			}
+
+			if (reference instanceof MMenu) {
+				boolean appendedMenu = false;
+
+				for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+					EObject key = entry.getKey();
+					if (key instanceof MPart) {
+						for (FeatureChange change : entry.getValue()) {
+							if (change.getFeatureName().equals(PART_MENUS_ATTNAME)) {
+								List<?> originalMenus = (List<?>) change.getValue();
+								if (originalMenus.contains(reference)) {
+									return key;
+								}
+
+								if (((MPart) key).getMenus().contains(reference)) {
+									appendedMenu = true;
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				boolean menuSet = false;
+				boolean menuChanged = false;
+
+				for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+					EObject key = entry.getKey();
+					if (key instanceof MWindow) {
+						for (FeatureChange change : entry.getValue()) {
+							if (change.getFeatureName().equals(WINDOW_MAINMENU_ATTNAME)) {
+								Object oldMenu = change.getValue();
+								if (oldMenu == reference) {
+									return key;
+								} else if (oldMenu == null
+										&& ((MWindow) key).getMainMenu() == reference) {
+									menuSet = true;
+								}
+								menuChanged = true;
+								break;
+							}
+						}
+					}
+				}
+
+				if (menuChanged && menuSet) {
+					return null;
+				} else if (appendedMenu && !menuSet && !menuChanged) {
+					return null;
+				}
+
+				EObject container = reference.eContainer();
+				if (!(container instanceof MMenu)) {
+					return container;
+				}
+			}
+
+			if (reference instanceof MToolBar) {
+				for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+					EObject key = entry.getKey();
+					if (key instanceof MPart) {
+						for (FeatureChange change : entry.getValue()) {
+							if (change.getFeatureName().equals(PART_TOOLBAR_ATTNAME)) {
+								if (change.getValue() == reference) {
+									return key;
+								}
+							}
+						}
+					}
+				}
+			}
+
+			boolean newElement = false;
+
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key == reference.eContainer()) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(ELEMENTCONTAINER_CHILDREN_ATTNAME)) {
+							EList<?> value = (EList<?>) change.getValue();
+							if (value.contains(reference)) {
+								return key;
+							}
+							newElement = true;
+							break;
+						} else if (change.getFeatureName().equals(PART_TOOLBAR_ATTNAME)) {
+							if (reference.equals(change.getValue())) {
+								return key;
+							}
+							newElement = true;
+							break;
+						} else if (change.getFeatureName().equals(WINDOW_SHAREDELEMENTS_ATTNAME)) {
+							EList<?> value = (EList<?>) change.getValue();
+							if (value.contains(reference)) {
+								return key;
+							}
+							newElement = true;
+							break;
+						} else if (change.getFeatureName().equals(PERSPECTIVE_WINDOWS_ATTNAME)) {
+							EList<?> value = (EList<?>) change.getValue();
+							if (value.contains(reference)) {
+								return key;
+							}
+							newElement = true;
+							break;
+						}
+					}
+					break;
+				}
+
+				for (FeatureChange change : entry.getValue()) {
+					if (change.getFeatureName().equals(WINDOW_SHAREDELEMENTS_ATTNAME)) {
+						EList<?> value = (EList<?>) change.getValue();
+						if (value.contains(reference)) {
+							return key;
+						}
+					}
+				}
+			}
+
+			if (reference instanceof MWindow) {
+				for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+					EObject key = entry.getKey();
+					if (key instanceof MPerspective) {
+						for (FeatureChange change : entry.getValue()) {
+							if (change.getFeatureName().equals(PERSPECTIVE_WINDOWS_ATTNAME)) {
+								EList<?> value = (EList<?>) change.getValue();
+								if (value.contains(reference)) {
+									return key;
+								}
+								break;
+							}
+						}
+					}
+				}
+			}
+
+			if (!newElement) {
+				return reference instanceof MApplication ? changeDescription : reference
+						.eContainer();
+			}
+		}
+
+		if (reference instanceof MAddon) {
+			for (Entry<EObject, EList<FeatureChange>> entry : objectChanges.entrySet()) {
+				EObject key = entry.getKey();
+				if (key instanceof MApplication) {
+					for (FeatureChange change : entry.getValue()) {
+						if (change.getFeatureName().equals(APPLICATION_ADDONS_ATTNAME)) {
+							EList<?> value = (EList<?>) change.getValue();
+							return value.contains(reference) ? key : null;
+						}
+					}
+				}
+			}
+
+			return reference.eContainer();
+		}
+
+		return null;
+	}
+
+	/**
+	 * Computes and returns the original id of the specified object. The meaning of the term
+	 * "original" is defined as the state of the object prior to having its state monitored via
+	 * {@link #recordChanges(Object)}. The identifier for the object will be queried from the
+	 * resource. If the object did not exist was not known when changes began recording,
+	 * <code>null</code> will be returned.
+	 *
+	 * @param object
+	 *            the object to query an id for
+	 * @return an id suitable for looking up the object, or <code>null</code> if the object did not
+	 *         exist or was not known within the scope of the originally monitored object
+	 */
+	private String getOriginalId(Object object) {
+		EObject reference = (EObject) object;
+		EObject originalContainer = getOriginalContainer(reference);
+
+		// did not exist in the model originally
+		if (originalContainer == null) {
+			return null;
+		}
+
+		if (originalContainer != changeDescription) {
+			EObject container = originalContainer;
+			while (container != rootObject) {
+				container = getOriginalContainer(container);
+				if (container == null) {
+					return null;
+				}
+			}
+		}
+
+		return findResourceId(reference, originalContainer);
+	}
+
+	/**
+	 * Creates an XML element that will capture the delta that occurred in the object.
+	 *
+	 * @param document
+	 *            the root XML document
+	 * @param object
+	 *            the object that has changed
+	 * @param featureChange
+	 *            the captured information about the change
+	 * @param featureName
+	 *            the name of the feature that has changed
+	 * @return the XML element about the change
+	 */
+	private Element createDeltaElement(Document document, EObject object,
+			FeatureChange featureChange, String featureName) {
+		EStructuralFeature feature = featureChange.getFeature();
+		if (object.eIsSet(feature)) {
+			return createSetDeltaElement(document, object, featureChange, featureName, feature);
+		}
+
+		return createUnsetDeltaElement(document, featureChange, featureName);
+	}
+
+	private Element createSetDeltaElement(Document document, EObject object,
+			FeatureChange featureChange, String featureName, EStructuralFeature feature) {
+		Element featureElement = document.createElement(featureName);
+		Object value = object.eGet(feature);
+		if (isSingleReference(featureName)) {
+			// record what we're currently referencing, we create an element instead of simply
+			// recording the id because we need to describe the entire object if the object is new,
+			// simply recording an id would be insufficient for recording the attributes of the new
+			// object
+			Element referenceElement = createReferenceElement(document, (EObject) value,
+					featureName);
+			featureElement.appendChild(referenceElement);
+		} else if (isChainedReference(featureName)) {
+			// record what we're currently referencing
+			appendReferenceElements(document, featureElement, (List<?>) value);
+			// record what was originally referenced
+			appendOriginalReferenceElements(document, featureElement,
+					(List<?>) featureChange.getValue());
+		} else if (isUnorderedChainedAttribute(featureName)) {
+			appendUnorderedChainedAttributeElements(document, (List<?>) value, featureName,
+					featureElement);
+		} else if (isStringToStringMap(featureName)) {
+			appendStringToStringMapElements(document, featureElement, object, feature, featureName);
+		} else {
+			featureElement.setAttribute(featureName, String.valueOf(value));
+		}
+		return featureElement;
+	}
+
+	private Element createUnsetDeltaElement(Document document, FeatureChange featureChange,
+			String featureName) {
+		Element featureElement = document.createElement(featureName);
+		if (isChainedReference(featureName)) {
+			appendOriginalReferenceElements(document, featureElement,
+					(List<?>) featureChange.getValue());
+		} else {
+			featureElement.setAttribute(UNSET_ATTNAME, UNSET_ATTVALUE_TRUE);
+		}
+		return featureElement;
+	}
+
+	/**
+	 * Creates an element to describe that the specified object was a reference that was originally
+	 * there when the application started prior to the applying of any deltas. It should be noted
+	 * that an object that was originally referenced will not necessarily be dereferenced after any
+	 * deltas have been applied.
+	 *
+	 * @param document
+	 *            the root XML document
+	 * @param reference
+	 *            the referenced object
+	 * @return an XML element to record that the specified object was originally referenced by
+	 *         another object when the application started
+	 */
+	private Element createOriginalReferenceElement(Document document, Object reference) {
+		Element referenceElement = document.createElement(ORIGINALREFERENCE_ELEMENT_NAME);
+		referenceElement.setAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME,
+				getOriginalId(reference));
+		return referenceElement;
+	}
+
+	private void appendOriginalReferenceElements(Document document, Element element,
+			List<?> references) {
+		for (Object reference : references) {
+			Element referenceElement = createOriginalReferenceElement(document, reference);
+			element.appendChild(referenceElement);
+		}
+	}
+
+	/**
+	 * Creates a new element that defines a reference to another object.
+	 *
+	 * @param document
+	 *            the root XML document
+	 * @param eObject
+	 *            the object to reference
+	 * @param featureName
+	 *            the name of the feature describing the reference relationship, if
+	 *            <code>null</code>, it is assumed to be a direct reference
+	 * @return an XML element that describes the reference to the provided object
+	 * @see #isDirectReference(String)
+	 * @see #isIndirectReference(String)
+	 */
+	private Element createReferenceElement(Document document, EObject eObject, String featureName) {
+		String id = getOriginalId(eObject);
+
+		if (id == null) {
+			if (featureName == null || isDirectReference(featureName)) {
+				// didn't exist originally, we need a completely new reference that describes the
+				// object and its attributes
+				return createNewReferenceElement(document, eObject);
+			}
+			return createUniqueReferenceElement(document, eObject);
+		}
+
+		Element referenceElement = document.createElement(REFERENCE_ELEMENT_NAME);
+		referenceElement.setAttribute(APPLICATIONELEMENT_ELEMENTID_ATTNAME, id);
+		return referenceElement;
+	}
+
+	private void appendReferenceElements(Document document, Element element, List<?> references) {
+		for (Object reference : references) {
+			Element ef = createReferenceElement(document, (EObject) reference, null);
+			element.appendChild(ef);
+		}
+	}
+
+	private Element createNewReferenceElement(Document document, EObject eObject) {
+		Element referenceElement = createUniqueReferenceElement(document, eObject);
+
+		// object did not exist, mark it as such so it can be created during the
+		// when the deltas are applied
+		referenceElement.setAttribute(UNSET_ATTNAME, UNSET_ATTVALUE_TRUE);
+		// note what we need to create by storing the type
+		referenceElement.setAttribute(TYPE_ATTNAME,
+				eObject.getClass().getInterfaces()[0].getCanonicalName());
+
+		for (EStructuralFeature collectedFeature : collectFeatures(eObject)) {
+			String featureName = collectedFeature.getName();
+			// ignore transient features and features that we are not interested in
+			if (!collectedFeature.isTransient() && shouldPersist(featureName)) {
+				Element referenceAttributeElement = createAttributeElement(document, eObject,
+						collectedFeature, featureName);
+				referenceElement.appendChild(referenceAttributeElement);
+			}
+		}
+
+		return referenceElement;
+	}
+
+	private Element createUniqueReferenceElement(Document document, EObject eObject) {
+		EClass cls = eObject.eClass();
+		EPackage pkg = (EPackage) cls.eContainer();
+
+		Element referenceElement = document.createElement(REFERENCE_ELEMENT_NAME);
+
+		E4XMIResource resource = (E4XMIResource) rootObject.eResource();
+		String internalId = resource.getInternalId(eObject);
+		referenceElement.setAttribute(XMIID_ATTNAME, internalId);
+		referenceElement.setAttribute(NAMESPACE_ATTNAME, pkg.getNsURI());
+
+		return referenceElement;
+	}
+
+	/**
+	 * Creates an element that describes the state of the feature in the specified object.
+	 *
+	 * @param document
+	 *            the root XML element document
+	 * @param object
+	 *            the object to describe
+	 * @param feature
+	 *            the feature of interest
+	 * @param featureName
+	 *            the name of the feature
+	 * @return an XML element that describes the feature's value in the provided object
+	 */
+	private Element createAttributeElement(Document document, EObject object,
+			EStructuralFeature feature, String featureName) {
+		Element referenceAttributeElement = document.createElement(featureName);
+		if (object.eIsSet(feature)) {
+			if (isSingleReference(featureName)) {
+				Object value = object.eGet(feature);
+				String id = getOriginalId(value);
+				if (id == null) {
+					Element referenceElement = createReferenceElement(document, (EObject) value,
+							featureName);
+					referenceAttributeElement.appendChild(referenceElement);
+				} else {
+					referenceAttributeElement.setAttribute(featureName, id);
+				}
+			} else if (isChainedReference(featureName)) {
+				List<?> references = (List<?>) object.eGet(feature);
+				appendReferenceElements(document, referenceAttributeElement, references);
+			} else if (isUnorderedChainedAttribute(featureName)) {
+				appendUnorderedChainedAttributeElements(document, (List<?>) object.eGet(feature),
+						featureName, referenceAttributeElement);
+			} else if (isStringToStringMap(featureName)) {
+				appendStringToStringMapElements(document, referenceAttributeElement, object,
+						feature, featureName);
+			} else {
+				referenceAttributeElement.setAttribute(featureName,
+						String.valueOf(object.eGet(feature)));
+			}
+		} else {
+			referenceAttributeElement.setAttribute(UNSET_ATTNAME, UNSET_ATTVALUE_TRUE);
+		}
+		return referenceAttributeElement;
+	}
+
+	private void appendUnorderedChainedAttributeElements(Document document, List<?> attributes,
+			String featureName, Element referenceAttributeElement) {
+		// iterate over all the attributes
+		for (Object attribute : attributes) {
+			// create a new element for each attribute
+			Element attributeElement = document.createElement(featureName);
+			// set the attribute's value into the element
+			attributeElement.setAttribute(featureName, String.valueOf(attribute));
+			// append the element to the parent
+			referenceAttributeElement.appendChild(attributeElement);
+		}
+	}
+
+	private void appendStringToStringMapElements(Document document, Element parentElement,
+			EObject object, EStructuralFeature feature, String featureName) {
+		EMap<?, ?> map = (EMap<?, ?>) object.eGet(feature);
+		// iterate over the map
+		for (Entry<?, ?> entry : map.entrySet()) {
+			// create a new element for each entry in the map
+			Element entryElement = document.createElement(featureName);
+			// set the string keys and values into the element
+			entryElement.setAttribute(ENTRY_ATTVALUE_KEY, (String) entry.getKey());
+			entryElement.setAttribute(ENTRY_ATTVALUE_VALUE, (String) entry.getValue());
+			// append the element to the parent
+			parentElement.appendChild(entryElement);
+		}
+	}
+
+	private static boolean isStringToStringMap(String featureName) {
+		return featureName.equals(APPLICATIONELEMENT_PERSISTEDSTATE_ATTNAME)
+				|| featureName.equals(CONTEXT_PROPERTIES_ATTNAME);
+	}
+
+	/**
+	 * Determines whether this feature is a direct reference to a particular object. That is, the
+	 * reference is a 1-1 relationship and the referenced object is not referred by other objects
+	 * and is a hard containment feature.
+	 * <p>
+	 * An example of a direct reference would be a window's main menu. The menu is "owned" by the
+	 * window and cannot be one of the menus in a part.
+	 * </p>
+	 *
+	 * @param featureName
+	 *            the name of the interested feature
+	 * @return <code>true</code> if this particular feature directly references and "owns" the
+	 *         target object, <code>false</code> otherwise
+	 * @see #isIndirectReference(String)
+	 */
+	private static boolean isDirectReference(String featureName) {
+		// a Window has a single reference to a menu
+		return featureName.equals(WINDOW_MAINMENU_ATTNAME) ||
+		// a Part has a single reference to a tool bar
+				featureName.equals(PART_TOOLBAR_ATTNAME) ||
+				// a UIElement has a single reference to a visibleWhen
+				featureName.equals(UIELEMENT_VISIBLEWHEN_ATTNAME);
+	}
+
+	/**
+	 * Determines whether this feature is an indirect reference to a particular object. That is, the
+	 * reference refers to an object and this reference does not necessarily describe containment.
+	 * <p>
+	 * An example of an indirect reference would be a handler's command. The handler points to a
+	 * command but the command is actually "owned" by an application in its list of commands. In
+	 * this case, there is no containment involved between the handler and the command.
+	 * </p>
+	 * <p>
+	 * Another example of an indirect reference would be a element container's active child. In this
+	 * case, the element container's contains the active child in its list of children and both this
+	 * listing and the active child reference is a containment feature.
+	 * </p>
+	 *
+	 * @param featureName
+	 *            the name of the interested feature
+	 * @return <code>true</code> if this particular feature directly references and "owns" the
+	 *         target object, <code>false</code> otherwise
+	 * @see #isDirectReference(String)
+	 */
+	private static boolean isIndirectReference(String featureName) {
+		// an ElementContainer has a single reference to its active child
+		return featureName.equals(ELEMENTCONTAINER_SELECTEDELEMENT_ATTNAME) ||
+		// a Handler has a single reference to a command
+				featureName.equals(HANDLER_COMMAND_ATTNAME) ||
+				// a KeyBinding has a single reference to a command
+				featureName.equals(KEYBINDING_COMMAND_ATTNAME) ||
+				// a Placeholder has a single reference to a ui element
+				featureName.equals(PLACEHOLDER_REF_NAME) ||
+				// a BindingTable has a single reference to a bindingContext
+				featureName.equals(BINDINGTABLE_BINDINGCONTEXT_ATTNAME);
+	}
+
+	/**
+	 * Returns whether the feature is a reference to another object.
+	 *
+	 * @param featureName
+	 *            the name of the feature
+	 * @return <code>true</code> if this particular feature is a reference to another object,
+	 *         <code>false</code> otherwise
+	 */
+	private static boolean isSingleReference(String featureName) {
+		return isDirectReference(featureName) || isIndirectReference(featureName);
+	}
+
+	/**
+	 * Returns whether the feature is a list of object references.
+	 *
+	 * @param featureName
+	 *            the name of the feature
+	 * @return <code>true</code> if this particular feature is referring to a list of object
+	 *         references, <code>false</code> otherwise
+	 */
+	private static boolean isChainedReference(String featureName) {
+		// an ElementContainer has multiple children
+		return featureName.equals(ELEMENTCONTAINER_CHILDREN_ATTNAME) ||
+		// a BindingContainer has multiple bindings
+				featureName.equals(BINDINGTABLE_BINDINGS_ATTNAME) ||
+				// a Part has multiple menus
+				featureName.equals(PART_MENUS_ATTNAME) ||
+				// an Application has multiple commands
+				featureName.equals(APPLICATION_COMMANDS_ATTNAME) ||
+				// a SnippetContainer has multiple snippets
+				featureName.equals(SNIPPETCONTAINER_SNIPPETS_ATTNAME) ||
+				// a HandlerContainer has multiple handlers
+				featureName.equals(HANDLERCONTAINER_HANDLERS_ATTNAME) ||
+				// a BindingContainer has multiple binding tables
+				featureName.equals(BINDINGCONTAINER_BINDINGTABLES_ATTNAME) ||
+				// a TrimmedWindow has multiple trim bars
+				featureName.equals(TRIMMEDWINDOW_TRIMBARS_ATTNAME) ||
+				// a Window has multiple shared elements
+				featureName.equals(WINDOW_SHAREDELEMENTS_ATTNAME) ||
+				// a MenuContributions has multiple menu contributions
+				featureName.equals(MENUCONTRIBUTIONS_MENUCONTRIBUTIONS_ATTNAME) ||
+				// a Command has multiple (command) parameters
+				featureName.equals(COMMAND_PARAMETERS_ATTNAME) ||
+				// a HandledItem has multiple parameters
+				featureName.equals(HANDLEDITEM_PARAMETERS_ATTNAME) ||
+				// a ToolBarContributions has multiple tool bar contributions
+				featureName.equals(TOOLBARCONTRIBUTIONS_TOOLBARCONTRIBUTIONS_ATTNAME) ||
+				// a TrimContributions has multiple trim contributions
+				featureName.equals(TRIMCONTRIBUTIONS_TRIMCONTRIBUTIONS_ATTNAME) ||
+				// a Perspective has multiple windows
+				featureName.equals(PERSPECTIVE_WINDOWS_ATTNAME) ||
+				// a Binding has multiple binding contexts
+				featureName.equals(BINDINGS_BINDINGCONTEXTS_ATTNAME) ||
+				// a BindingContainer has multiple root contexts
+				featureName.equals(BINDINGCONTAINER_ROOTCONTEXT_ATTNAME);
+	}
+
+	private static boolean isUnorderedChainedAttribute(String featureName) {
+		return featureName.equals(APPLICATIONELEMENT_TAGS_ATTNAME);
+	}
+
+	/**
+	 * Returns whether this feature should be persisted.
+	 *
+	 * @param featureName
+	 *            the name of the feature
+	 * @return <code>true</code> if this particular feature should be persisted, <code>false</code>
+	 *         otherwise
+	 */
+	private static boolean shouldPersist(String featureName) {
+		// parent changes are captured by children changes already
+		return !featureName.equals(UIELEMENT_PARENT_ATTNAME)
+				&& !featureName.equals(PARTDESCRIPTORCONTAINER_DESCRIPTORS_ATTNAME);
+	}
+
+	private static Collection<EStructuralFeature> collectFeatures(
+			Collection<EStructuralFeature> features, EClass eClass) {
+		features.addAll(eClass.getEStructuralFeatures());
+		for (EClass superType : eClass.getESuperTypes()) {
+			collectFeatures(features, superType);
+		}
+		return features;
+	}
+
+	private static Collection<EStructuralFeature> collectFeatures(EObject object) {
+		return collectFeatures(new HashSet<EStructuralFeature>(), object.eClass());
+	}
+
+	private static boolean isUnset(Element element) {
+		return UNSET_ATTVALUE_TRUE.equals(element.getAttribute(UNSET_ATTNAME));
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/ContextProcessingAddon.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/ContextProcessingAddon.java
new file mode 100644
index 0000000..62965a3
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/ContextProcessingAddon.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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 395161
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.addons;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.Activator;
+import org.eclipse.e4.ui.internal.workbench.Policy;
+import org.eclipse.e4.ui.model.LocalizationHelper;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.commands.MBindingContext;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Process contexts in the model, feeding them into the command service.
+ */
+public class ContextProcessingAddon {
+
+	@Inject
+	private MApplication application;
+
+	@Inject
+	private IEventBroker broker;
+
+	@Inject
+	private ContextManager contextManager;
+
+	@Inject
+	Logger logger;
+
+	private EventHandler additionHandler;
+
+	@PostConstruct
+	public void init() {
+		defineContexts();
+		registerModelListeners();
+	}
+
+	private void defineContexts() {
+		Activator.trace(Policy.DEBUG_CMDS, "Initialize contexts and parents from model", null); //$NON-NLS-1$
+		for (MBindingContext root : application.getRootContext()) {
+			defineContexts(null, root);
+		}
+	}
+
+	private void defineContexts(MBindingContext parent, MBindingContext current) {
+		if (current.getName() == null || current.getElementId() == null) {
+			logger.error("Binding context name or id is null for: " + current); //$NON-NLS-1$
+			return;
+		}
+		Context context = contextManager.getContext(current.getElementId());
+		if (!context.isDefined()) {
+			String localizedName = LocalizationHelper.getLocalized(current.getName(), current,
+					application.getContext());
+			String localizedDescriptor = LocalizationHelper.getLocalized(current.getDescription(),
+					current, application.getContext());
+			context.define(localizedName, localizedDescriptor,
+					parent == null ? null : parent.getElementId());
+		}
+		for (MBindingContext child : current.getChildren()) {
+			defineContexts(current, child);
+		}
+	}
+
+	private void undefineContext(MBindingContext current) {
+		Context context = contextManager.getContext(current.getElementId());
+		context.undefine();
+	}
+
+	@PreDestroy
+	public void dispose() {
+		unregsiterModelListeners();
+	}
+
+	private void registerModelListeners() {
+		additionHandler = new EventHandler() {
+			@Override
+			public void handleEvent(Event event) {
+				Object elementObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+				if (elementObj instanceof MBindingContext) {
+					if (UIEvents.isADD(event)) {
+						for (Object newObj : UIEvents.asIterable(event,
+								UIEvents.EventTags.NEW_VALUE)) {
+							if (newObj instanceof MBindingContext) {
+								MBindingContext newCtx = (MBindingContext) newObj;
+								defineContexts((MBindingContext) elementObj, newCtx);
+							}
+						}
+					} else if (UIEvents.isREMOVE(event)) {
+						for (Object oldObj : UIEvents.asIterable(event,
+								UIEvents.EventTags.OLD_VALUE)) {
+							if (oldObj instanceof MBindingContext) {
+								MBindingContext oldCtx = (MBindingContext) oldObj;
+								undefineContext(oldCtx);
+							}
+						}
+					}
+				}
+			}
+		};
+		broker.subscribe(UIEvents.BindingContext.TOPIC_CHILDREN, additionHandler);
+	}
+
+	private void unregsiterModelListeners() {
+		broker.unsubscribe(additionHandler);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/HandlerProcessingAddon.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/HandlerProcessingAddon.java
new file mode 100644
index 0000000..bac38a9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/addons/HandlerProcessingAddon.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 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
+ *     Sopot Cela - initial API, implementation and fixes
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench.addons;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.extensions.EventTopic;
+import org.eclipse.e4.core.services.contributions.IContributionFactory;
+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.commands.MHandlerContainer;
+import org.eclipse.e4.ui.model.application.ui.MContext;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.osgi.service.event.Event;
+
+/**
+ * Process the additions and removals of handlers on the model
+ */
+public class HandlerProcessingAddon {
+
+	/**
+	 * Do initial check of handlers and their context upon creation
+	 * 
+	 * @param application
+	 * @param modelService
+	 */
+	@PostConstruct
+	public void postConstruct(MApplication application, EModelService modelService) {
+		List<MHandlerContainer> findElements = modelService.findElements(application, null,
+				MHandlerContainer.class, null);
+		for (MHandlerContainer mHandlerContainer : findElements) {
+			if (mHandlerContainer instanceof MContext) {
+				MContext mContext = (MContext) mHandlerContainer;
+				IEclipseContext context = mContext.getContext();
+				if (context != null) {
+					for (MHandler mHandler : mHandlerContainer.getHandlers()) {
+						processActiveHandler(mHandler, context);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Responds to the coming and goings of handlers in the application model by activating and
+	 * deactivating them accordingly.
+	 * 
+	 * @param event
+	 *            The event thrown in the event bus
+	 */
+	@Inject
+	public void handleHandlerEvent(
+			@Optional @EventTopic(UIEvents.HandlerContainer.TOPIC_HANDLERS) Event event) {
+		if (event == null)
+			return;
+		if ((event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MHandlerContainer)
+				&& (event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MContext)) {
+			MHandlerContainer handlerContainer = (MHandlerContainer) event
+					.getProperty(UIEvents.EventTags.ELEMENT);
+			if (UIEvents.EventTypes.ADD.equals(event.getProperty(UIEvents.EventTags.TYPE))) {
+				if (event.getProperty(UIEvents.EventTags.NEW_VALUE) instanceof MHandler) {
+					MHandler handler = (MHandler) event.getProperty(UIEvents.EventTags.NEW_VALUE);
+					MContext mContext = (MContext) handlerContainer;
+					IEclipseContext context = mContext.getContext();
+					if (context != null) {
+						processActiveHandler(handler, context);
+					}
+				}
+			} else if (UIEvents.EventTypes.REMOVE
+					.equals(event.getProperty(UIEvents.EventTags.TYPE))) {
+				if (event.getProperty(UIEvents.EventTags.OLD_VALUE) instanceof MHandler) {
+					MHandler handler = (MHandler) event.getProperty(UIEvents.EventTags.OLD_VALUE);
+					MContext mContext = (MContext) handlerContainer;
+					IEclipseContext context = mContext.getContext();
+					if (context != null) {
+						MCommand command = handler.getCommand();
+						if (command != null) {
+							String commandId = command.getElementId();
+							EHandlerService handlerService = (EHandlerService) context
+									.get(EHandlerService.class.getName());
+							handlerService.deactivateHandler(commandId, handler.getObject());
+						}
+					}
+				}
+
+			}
+
+		}
+
+	}
+
+	/**
+	 * Responds to the setting of contexts of handlers in the application model and reacts
+	 * accordingly.
+	 *
+	 * @param event
+	 *            The event which signals the setting of the context.
+	 */
+
+	@Inject
+	public void handleContextEvent(@Optional @EventTopic(UIEvents.Context.TOPIC_CONTEXT) Event event) {
+		if (event == null)
+			return;
+		Object origin = event.getProperty(UIEvents.EventTags.ELEMENT);
+		Object context = event.getProperty(UIEvents.EventTags.NEW_VALUE);
+		if ((origin instanceof MHandlerContainer)
+				&& (UIEvents.EventTypes.SET.equals(event.getProperty(UIEvents.EventTags.TYPE)) && context instanceof IEclipseContext)) {
+			MHandlerContainer handlerContainer = (MHandlerContainer) origin;
+			IEclipseContext castedContext = (IEclipseContext) context;
+			for (MHandler mHandler : handlerContainer.getHandlers()) {
+				processActiveHandler(mHandler, castedContext);
+			}
+
+		}
+	}
+
+	/**
+	 * @param handler
+	 * @param context
+	 */
+	private void processActiveHandler(MHandler handler, IEclipseContext context) {
+		MCommand command = handler.getCommand();
+		if (command != null) {
+			String commandId = command.getElementId();
+			if (handler.getObject() == null) {
+				IContributionFactory contributionFactory = (IContributionFactory) context
+						.get(IContributionFactory.class.getName());
+				handler.setObject(contributionFactory.create(handler.getContributionURI(), context));
+			}
+			EHandlerService handlerService = (EHandlerService) context.get(EHandlerService.class
+					.getName());
+			handlerService.activateHandler(commandId, handler.getObject());
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/ExitHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/ExitHandler.java
new file mode 100644
index 0000000..8759d95
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/ExitHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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.internal.workbench.handlers;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+
+public class ExitHandler {
+	@Execute
+	public void execute(IWorkbench workbench) {
+		workbench.close();
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveAllHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveAllHandler.java
new file mode 100644
index 0000000..0e2ac3e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveAllHandler.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 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 416099
+ ******************************************************************************/
+package org.eclipse.e4.ui.internal.workbench.handlers;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+
+public class SaveAllHandler {
+
+	@CanExecute
+	boolean canExecute(@Optional EPartService partService) {
+		if (partService != null) {
+			return !partService.getDirtyParts().isEmpty();
+		}
+		return false;
+	}
+
+	@Execute
+	void execute(EPartService partService) {
+		partService.saveAll(false);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveHandler.java
new file mode 100644
index 0000000..3952a81
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/SaveHandler.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench.handlers;
+
+import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+
+public class SaveHandler {
+
+	@CanExecute
+	boolean canExecute(@Named(IServiceConstants.ACTIVE_PART) MDirtyable dirtyable) {
+		return dirtyable == null ? false : dirtyable.isDirty();
+	}
+
+	@Execute
+	void execute(EPartService partService, @Named(IServiceConstants.ACTIVE_PART) MPart part) {
+		partService.savePart(part, false);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/UnimplementedHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/UnimplementedHandler.java
new file mode 100644
index 0000000..20c2e9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/handlers/UnimplementedHandler.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.internal.workbench.handlers;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+
+public class UnimplementedHandler {
+	@Execute
+	public void execute(IWorkbench workbench) {
+		System.err.println("This command handler is not implemented."); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IExceptionHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IExceptionHandler.java
new file mode 100644
index 0000000..debdb5f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IExceptionHandler.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench;
+
+/**
+ * This handler allows clients to be notified when an exception occurs
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 1.0
+ */
+public interface IExceptionHandler {
+
+	/**
+	 * Call-back to handle the given {@link Throwable}
+	 *
+	 * @param e
+	 *            the {@link Throwable}
+	 */
+	public void handleException(Throwable e);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java
new file mode 100644
index 0000000..e864250
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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
+ *     Tristan Hume - <trishume@gmail.com> -
+ *     		Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting
+ *     		Implemented workbench auto-save to correctly restore state in case of crash.
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench;
+
+import java.io.IOException;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.emf.ecore.resource.Resource;
+
+/**
+ * This handler allows clients load, create and save model resources
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 1.0
+ */
+public interface IModelResourceHandler {
+
+	/**
+	 * Loads an returns the most recent model that was persisted
+	 *
+	 * @return the most recent model state
+	 */
+	public Resource loadMostRecentModel();
+
+	/**
+	 * Creates a resource with an app Model, used for saving copies of the main app model.
+	 *
+	 * @param theApp
+	 *            the application model to add to the resource
+	 * @return a resource with a proper save path with the model as contents
+	 */
+	public Resource createResourceWithApp(MApplication theApp);
+
+	/**
+	 * Saves the model
+	 *
+	 * @throws IOException
+	 *             if storing fails
+	 *
+	 */
+	public void save() throws IOException;
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IPresentationEngine.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IPresentationEngine.java
new file mode 100644
index 0000000..d17dea2
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IPresentationEngine.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2014 BestSolution.at 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:
+ *     Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
+ *     IBM - ongoing development
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.workbench;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+
+/**
+ * The presentation engine is used to translate the generic workbench model into widgets.
+ * Implementations of this service are responsible for creating or destroying widgets corresponding
+ * to model elements, as well as for running any event loop required for handling user events on
+ * those widgets.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 1.0
+ */
+public interface IPresentationEngine {
+	/**
+	 * The ID to access the service in the {@link IEclipseContext}
+	 */
+	public static final String SERVICE_NAME = IPresentationEngine.class.getName();
+
+	/**
+	 * When applied as a tag to an MUILabel inhibits the display of the label text
+	 */
+	public static final String NO_TITLE = "NoTitle"; //$NON-NLS-1$
+
+	/**
+	 * When applied as a tag to an MPlaceholder inhibits the display of the close affordance. This
+	 * allows a part to be closeable in one perspective but not in a different one.
+	 *
+	 * <b>NOTE:</b> If you are not using perspectives then use the MPart's 'isCloseable' attribute
+	 * to control the affordance.
+	 */
+	public static final String NO_CLOSE = "NoClose"; //$NON-NLS-1$
+
+	/**
+	 * Declare the stack as containing a singe 'standalone' view. These stacks will not allow either
+	 * dragging the view out of the stack nor dragging other views in.
+	 *
+	 * @since 1.1
+	 */
+	public static final String STANDALONE = "Standalone"; //$NON-NLS-1$
+
+	/**
+	 * Don't remove the element from the display even if it has no displayable children
+	 */
+	public static final String NO_AUTO_COLLAPSE = "NoAutoCollapse"; //$NON-NLS-1$
+
+	/**
+	 * When applied as a tag to an MUIElement inhibits moving the element (ie. through DnD...
+	 */
+	public static final String NO_MOVE = "NoMove"; //$NON-NLS-1$
+
+	/**
+	 * This tag can be used by the renderer implementation to decide that the user interface element
+	 * has been hidden.
+	 *
+	 * @since 1.1
+	 */
+	public static final String HIDDEN_EXPLICITLY = "HIDDEN_EXPLICITLY"; //$NON-NLS-1$
+
+	/**
+	 * This key is used to store information in the 'persistentData' map which will be used to
+	 * override the initial style of an element at rendering time. For example the SWT renderer will
+	 * expect to see an integer (as a string) which defines the initial SWT style bits.
+	 *
+	 * @since 1.1
+	 */
+	public static String STYLE_OVERRIDE_KEY = "styleOverride"; //$NON-NLS-1$
+
+	/**
+	 * When applied to an MWindow causes the renderer to minimize the resulting control.
+	 *
+	 * @since 1.1
+	 */
+	public static String WINDOW_MINIMIZED_TAG = "shellMinimized"; //$NON-NLS-1$
+
+	/**
+	 * When applied to an MWindow causes the renderer to maximize the resulting control.
+	 *
+	 * @since 1.1
+	 */
+	public static String WINDOW_MAXIMIZED_TAG = "shellMaximized"; //$NON-NLS-1$
+
+	/**
+	 * When applied to an MWindow causes the renderer to render the resulting control as a top level
+	 * window
+	 *
+	 * @since 1.3
+	 */
+	public static String WINDOW_TOP_LEVEL = "shellTopLevel"; //$NON-NLS-1$
+
+	/**
+	 * When added to an element's 'tags' this should cause the presentation to move that element to
+	 * the trim. In the default implementation you can only apply this tag to an MPartStack or the
+	 * MPlaceholder of the MArea.
+	 */
+	public static String MINIMIZED = "Minimized"; //$NON-NLS-1$
+
+	/**
+	 * When added to an element's 'tags' this should cause the presentation to minimize all other
+	 * presentation elements. In the default implementation you can only apply this tag to an
+	 * MPartStack or the MPlaceholder of the MArea.
+	 */
+	public static String MAXIMIZED = "Maximized"; //$NON-NLS-1$
+
+	/**
+	 * This tag should be applied to any element that had its MINIMIZED tag set due to a different
+	 * element going maximized. This allows the restore operation to only restore elements that the
+	 * user did not explicitly minimize.
+	 */
+	public static String MINIMIZED_BY_ZOOM = "MinimizedByZoom"; //$NON-NLS-1$
+
+	/**
+	 * This tag can be applied to an element as a hint to the renderers that the element would
+	 * prefer to be horizontal. For an MPart this could be used both as a hint to how to show the
+	 * view when it's in the trim but could also be used when picking a stack to add a newly opening
+	 * part to. It could also be used for example to control where the tabs appear on an MPartStack.
+	 */
+	public static String ORIENTATION_HORIZONTAL = "Horizontal"; //$NON-NLS-1$
+
+	/**
+	 * This tag can be applied to an element as a hint to the renderers that the element would
+	 * prefer to be vertical. For an MPart this could be used both as a hint to how to show the view
+	 * when it's in the trim but could also be used when picking a stack to add a newly opening part
+	 * to. It could also be used for example to control where the tabs appear on an MPartStack.
+	 */
+	public static String ORIENTATION_VERTICAL = "Vertical"; //$NON-NLS-1$
+
+	/**
+	 * This tag can be applied to an element (usually an MPart) to indicate that the element should
+	 * be split with the result being side by side.
+	 *
+	 * @since 1.1
+	 */
+	public static String SPLIT_HORIZONTAL = "Split Horizontal"; //$NON-NLS-1$
+
+	/**
+	 * This tag can be applied to an element (usually an MPart) to indicate that the element should
+	 * be split with the result being one above the other.
+	 *
+	 * @since 1.1
+	 */
+	public static String SPLIT_VERTICAL = "Split Vertical"; //$NON-NLS-1$
+
+	/**
+	 * This key should be used to add an optional String to an element that is a URI to the elements
+	 * disabled icon. This is used, for example, by Toolbar Items which, in Eclipse SDK, provide a
+	 * unique icon for disabled tool items that look better than the OS default graying on the
+	 * default icon.
+	 *
+	 * There is a strong argument to be made that this disabledIconURI actually be part of the model
+	 */
+	public static final String DISABLED_ICON_IMAGE_KEY = "e4_disabled_icon_image_key"; //$NON-NLS-1$
+
+	/**
+	 * This key should be used to add an optional org.eclipse.swt.graphics.Image to an elements
+	 * TRANSIENTDATA. If present, the image will be used to override that elements iconURI. An
+	 * example is drawing the error icon on a minimized problems view stack.
+	 *
+	 * NOTE: This image must be checked to ensure that it hasn't been disposed on retrieval.
+	 */
+	public static final String OVERRIDE_ICON_IMAGE_KEY = "e4_override_icon_image_key"; //$NON-NLS-1$
+
+	/**
+	 * This key should be used to add an optional String to an elements TRANSIENTDATA. If present,
+	 * the string will be used to override the elements TitleToolTip. An example is setting the
+	 * ToolTip of a minimized problems view stack to the number of errors and warnings in the view.
+	 */
+	public static final String OVERRIDE_TITLE_TOOL_TIP_KEY = "e4_override_title_tool_tip_key"; //$NON-NLS-1$
+
+	/**
+	 * This is a Tag that when applied to an MUILabel element will cause whatever Image is to be
+	 * shown to be adorned with the 'pinned' affordance.
+	 *
+	 * @since 1.1
+	 */
+	public static final String ADORNMENT_PIN = "Pin Adornment"; //$NON-NLS-1$
+
+	/**
+	 * This is a <b>Boolean</b> preference used to control animations in the application
+	 */
+	public static final String ANIMATIONS_ENABLED = "Animations Enabled"; //$NON-NLS-1$
+
+	/**
+	 * This is a persistedState 'key' whose value is expected to be the URI of a subclass of
+	 * ABstractPartRenderer that is to be used to render the element
+	 */
+	public static final String CUSTOM_RENDERER_KEY = "Custom Renderer"; //$NON-NLS-1$
+
+	/**
+	 * This is the tag name that enables the DND support for the element. The element's tags list
+	 * has to be updated with the tag in order to enable the DND processing.
+	 *
+	 * @since 1.1
+	 */
+	public static final String DRAGGABLE = "Draggable"; //$NON-NLS-1$
+
+	/**
+	 * This is the tag name that indicates that the model element is active.
+	 *
+	 * @since 1.3
+	 */
+	public static final String ACTIVE = "active"; //$NON-NLS-1$
+
+	/**
+	 * Creates and returns the UI element for the given model element.
+	 *
+	 * @param element
+	 *            the model element
+	 * @param parentWidget
+	 *            the parent
+	 * @param parentContext
+	 *            the context within which this element is being rendered
+	 *
+	 * @return the created UI element
+	 */
+	public Object createGui(MUIElement element, Object parentWidget, IEclipseContext parentContext);
+
+	/**
+	 * Creates and returns the UI element corresponding to the given model element. The resulting UI
+	 * element sits at the top of a widget hierarchy
+	 *
+	 * @param element
+	 *            the model element
+	 * @return the create UI element
+	 */
+	public Object createGui(MUIElement element);
+
+	/**
+	 * Remove the UI element created for this model element.
+	 *
+	 * @param element
+	 *            the model element whose UI element should removed
+	 */
+	public void removeGui(MUIElement element);
+
+	/**
+	 * Attempts to set the UI focus onto the given element. By default we delegate this to the
+	 * elements implementation's @Focus method (if any). If no such method exists we delegate the
+	 * the renderer's 'forceFocus' method.
+	 *
+	 * @param element
+	 */
+	public void focusGui(MUIElement element);
+
+	/**
+	 * Run the UI. This method is responsible for creating the initial UI and (if necessary)
+	 * spinning the event loop for the life of the application.
+	 *
+	 * @param uiRoot
+	 * @param appContext
+	 *
+	 * @return The application's return value
+	 */
+	public Object run(MApplicationElement uiRoot, IEclipseContext appContext);
+
+	/**
+	 * Shuts down the presentation engine
+	 */
+	public void stop();
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IResourceUtilities.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IResourceUtilities.java
new file mode 100644
index 0000000..ee2adba
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IResourceUtilities.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench;
+
+import org.eclipse.emf.common.util.URI;
+
+/**
+ * This interface describes a utility that is used to load ImageDesc's from {@link URI}s
+ *
+ * @param <ImageDesc>
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 1.0
+ */
+public interface IResourceUtilities<ImageDesc> {
+
+	/**
+	 * Loads an ImageDesc from the given {@link URI}.
+	 *
+	 * @param iconPath
+	 * @return the ImageDesc from the given URI or <code>null</code>
+	 */
+	public ImageDesc imageDescriptorFromURI(URI iconPath);
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IWorkbench.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IWorkbench.java
new file mode 100644
index 0000000..fbf0226
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IWorkbench.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2013 BestSolution.at 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:
+ *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench;
+
+import java.net.URI;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+
+/**
+ * A running instance of the workbench.
+ *
+ * This instance is published through:
+ * <ul>
+ * <li>the {@link IEclipseContext} of the application</li>
+ * <li>the OSGi-Service-Registry</lI>
+ * </ul>
+ * <b>It is possible that there are multiple active {@link IWorkbench} instances in one
+ * OSGi-Instance</b>
+ *
+ * @since 1.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IWorkbench {
+	/**
+	 * The argument for whether the persisted state should be cleared on startup <br>
+	 * <br>
+	 * Value is: <code>clearPersistedState</code>
+	 */
+	public static final String CLEAR_PERSISTED_STATE = "clearPersistedState"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the resources referenced from the
+	 * application CSS file <br>
+	 * <br>
+	 * Value is: <code>applicationCSSResources</code>
+	 *
+	 * @since 0.12.0
+	 */
+	public static final String CSS_RESOURCE_URI_ARG = "applicationCSSResources"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the application CSS file <br>
+	 * <br>
+	 * Value is: <code>applicationCSS</code>
+	 *
+	 * @since 0.12.0
+	 */
+	public static final String CSS_URI_ARG = "applicationCSS"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the life-cycle manager <br>
+	 * <br>
+	 * Value is: <code>lifeCycleURI</code>
+	 *
+	 * @since 0.12.0
+	 */
+	public static final String LIFE_CYCLE_URI_ARG = "lifeCycleURI"; //$NON-NLS-1$
+	/**
+	 * The argument for the resource handler to use <br>
+	 * <br>
+	 * Value is: <code>modelResourceHandler</code>
+	 */
+	public static final String MODEL_RESOURCE_HANDLER = "modelResourceHandler"; //$NON-NLS-1$
+	/**
+	 * The argument for whether the workbench should save and restore its state <br>
+	 * <<br>
+	 * Value is: <code>persistState</code>
+	 */
+	public static final String PERSIST_STATE = "persistState"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the application presentation <br>
+	 * <br>
+	 * Value is: <code>presentationURI</code>
+	 *
+	 * @since 0.12.0
+	 */
+	public static final String PRESENTATION_URI_ARG = "presentationURI"; //$NON-NLS-1$
+	/**
+	 * The argument for the {@link URI} of the applicaton.xmi file <br>
+	 * <br>
+	 * Value is: <code>applicationXMI</code>
+	 *
+	 * @since 0.12.0
+	 */
+	public static final String XMI_URI_ARG = "applicationXMI"; //$NON-NLS-1$
+
+	/**
+	 * Close the workbench instance
+	 *
+	 * @return <code>true</code> if the shutdown succeeds
+	 */
+	public boolean close();
+
+	/**
+	 * @return the application model driving the workbench
+	 */
+	public MApplication getApplication();
+
+	/**
+	 * @return unique id of the instance
+	 */
+	public String getId();
+
+	/**
+	 * restart the workbench
+	 *
+	 * @return <code>false</code> if the restart is aborted
+	 */
+	public boolean restart();
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/Selector.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/Selector.java
new file mode 100644
index 0000000..d78e53d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/Selector.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2014 BestSolution.at 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:
+ *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench;
+
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+
+/**
+ * Selector to find element
+ *
+ * @since 1.1
+ */
+public interface Selector {
+	/**
+	 * Call for each element to find matching elements
+	 *
+	 * @param element
+	 *            the element
+	 * @return <code>true</code> if matches else <code>false</code>
+	 */
+	public boolean select(MApplicationElement element);
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java
new file mode 100644
index 0000000..1fcedb5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/UIEvents.java
@@ -0,0 +1,1402 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.internal.ModelUtils;
+import org.osgi.service.event.Event;
+
+/**
+ * E4 UI events and event topic definitions.
+ *
+ * This file contains generated and hand crafted event topic constants. There are also hand crafted
+ * utility methods for constructing topic strings and publishing events.
+ *
+ * When the UI model changes org.eclipse.e4.ui.internal.workbench.swt.GenTopic should be run as an
+ * Eclipse application and the console results should be pasted into this file replacing the code
+ * below the "Place Generated Code Here" comment
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @since 1.0
+ */
+public class UIEvents {
+
+	/**
+	 * Topic separator character
+	 */
+	public static final String TOPIC_SEP = "/"; //$NON-NLS-1$
+
+	/**
+	 * Wild card character for matching all sub topics
+	 */
+	public static final String ALL_SUB_TOPICS = "*"; //$NON-NLS-1$
+
+	/**
+	 * Base name of all E4 UI events
+	 */
+	public static final String UITopicBase = "org/eclipse/e4/ui"; //$NON-NLS-1$
+
+	/**
+	 * Name element for all E4 UI model events (these are generated by GenTopic)
+	 */
+	public static final String UIModelTopicBase = UITopicBase + "/model"; //$NON-NLS-1$
+
+	/**
+	 * Name element for E4 Renderer events
+	 *
+	 * @since 1.1
+	 */
+	public static final String UIRendererTopicBase = UITopicBase + "/renderer"; //$NON-NLS-1$
+
+	/**
+	 * Event sent when a enabled update is requested for tool-items.
+	 * <p>
+	 * As a value you may pass in to the {@link IEventBroker#DATA}:
+	 * <ul>
+	 * <li>the special value {@link #ALL_ELEMENT_ID} to request changes of all
+	 * applicable elements (the default)</li>
+	 * <li>the {@link MApplicationElement#getElementId()} of the element to
+	 * check</li>
+	 * <li>instance of {@link Selector}</li>
+	 * </ul>
+	 * </p>
+	 *
+	 * @since 1.1
+	 */
+	public static final String REQUEST_ENABLEMENT_UPDATE_TOPIC = UIRendererTopicBase
+			+ "/requestEnablementUpdate"; //$NON-NLS-1$
+
+	/**
+	 * Special id passed to force all elements to be checked
+	 *
+	 * @since 1.1
+	 */
+	public static final String ALL_ELEMENT_ID = "ALL"; //$NON-NLS-1$
+
+	/**
+	 * E4 UI Event Types. Add appropriate utility is<Test> method below if new types added
+	 */
+	public static interface EventTypes {
+		/**
+		 * Creation event
+		 */
+		public static final String CREATE = "CREATE"; //$NON-NLS-1$
+		/**
+		 * Set event
+		 */
+		public static final String SET = "SET"; //$NON-NLS-1$
+		/**
+		 * Add event: value added is {@link EventTags#NEW_VALUE}.
+		 *
+		 * @see UIEvents#isADD(Event)
+		 */
+		public static final String ADD = "ADD"; //$NON-NLS-1$
+		/**
+		 * Add many items: values added are {@link EventTags#NEW_VALUE}
+		 *
+		 * @see UIEvents#isADD(Event)
+		 */
+		public static final String ADD_MANY = "ADD_MANY";//$NON-NLS-1$
+		/**
+		 * Remove event: value removed is {@link EventTags#OLD_VALUE}
+		 *
+		 * @see UIEvents#isREMOVE(Event)
+		 */
+		public static final String REMOVE = "REMOVE"; //$NON-NLS-1$
+		/**
+		 * Remove many event: the values removed are the {@link EventTags#OLD_VALUE} (a collection).
+		 * The former positions of the removed values are provided as an integer array in
+		 * {@link EventTags#POSITION}.
+		 *
+		 * @see UIEvents#isREMOVE(Event)
+		 */
+		public static final String REMOVE_MANY = "REMOVE_MANY"; //$NON-NLS-1$
+		/**
+		 * Value moved: the value moved is the {@link EventTags#NEW_VALUE}, the old position is
+		 * {@link EventTags#OLD_VALUE}, and the new position in {@link EventTags#POSITION}.
+		 */
+		public static final String MOVE = "MOVE"; //$NON-NLS-1$
+	}
+
+	/**
+	 * @param event
+	 *            An OSGI event representing a UIEvent
+	 * @return true if it is an add event (i.e., {@link EventTypes#ADD} or
+	 *         {@link EventTypes#ADD_MANY}), or false otherwise.
+	 * @see UIEvents.EventTags#NEW_VALUE
+	 * @see #asIterable(Event, String)
+	 */
+	public static boolean isADD(Event event) {
+		Object type = event.getProperty(UIEvents.EventTags.TYPE);
+		return UIEvents.EventTypes.ADD.equals(type) || UIEvents.EventTypes.ADD_MANY.equals(type);
+	}
+
+	/**
+	 * @param event
+	 *            An OSGI event representing a UIEvent
+	 * @return true if it is a remove event (i.e., {@link EventTypes#REMOVE} or
+	 *         {@link EventTypes#REMOVE_MANY}), or false otherwise.
+	 * @see UIEvents.EventTags#OLD_VALUE
+	 * @see #asIterable(Event, String)
+	 */
+	public static boolean isREMOVE(Event event) {
+		Object type = event.getProperty(UIEvents.EventTags.TYPE);
+		return UIEvents.EventTypes.REMOVE.equals(type)
+				|| UIEvents.EventTypes.REMOVE_MANY.equals(type);
+	}
+
+	/**
+	 * @param event
+	 *            An OSGI event representing a UIEvent
+	 * @return true if it is a set event, false otherwise.
+	 */
+	public static boolean isSET(Event event) {
+		return UIEvents.EventTypes.SET.equals(event.getProperty(UIEvents.EventTags.TYPE));
+	}
+
+	/**
+	 * @param event
+	 *            An OSGI event representing a UIEvent
+	 * @return true if it is a create event, false otherwise.
+	 */
+	public static boolean isCREATE(Event event) {
+		return UIEvents.EventTypes.CREATE.equals(event.getProperty(UIEvents.EventTags.TYPE));
+	}
+
+	/**
+	 * Return true if the specified property contains {@code o}. Intended as a helper function for
+	 * {@link EventTypes#ADD}, {@link EventTypes#ADD_MANY}, {@link EventTypes#REMOVE}, and
+	 * {@link EventTypes#REMOVE_MANY}. If the property is not a container (e.g., a collection or
+	 * array), then return true then if {@code container} is equal to {@code o}.
+	 *
+	 * @param event
+	 *            the event
+	 * @param propertyName
+	 *            the property name
+	 * @param o
+	 *            the object to check for containment
+	 * @return true if the property value contains {@code o} or is equal to {@code o}
+	 */
+	public static boolean contains(Event event, String propertyName, Object o) {
+		Object container = event.getProperty(propertyName);
+		if (container == null) {
+			return false;
+		} else if (container instanceof Collection<?> && ((Collection<?>) container).contains(o)) {
+			return true;
+		} else if (container instanceof Object[]) {
+			for (Object element : (Object[]) container) {
+				if (o.equals(element)) {
+					return true;
+				}
+			}
+		}
+		return o.equals(container);
+	}
+
+	/**
+	 * Return the provided event property as an iterable. If already a collection, return the
+	 * collection.
+	 *
+	 * @param event
+	 *            the event object
+	 * @param propertyName
+	 *            the name of the property
+	 * @return an iterable collection over the property elements
+	 */
+	public static Iterable<?> asIterable(Event event, String propertyName) {
+		Object o = event.getProperty(propertyName);
+		return o instanceof Collection<?> ? (Collection<?>) o : Collections.singleton(o);
+	}
+
+	/**
+	 * E4 UI Event argument attribute keys. These are used as keys for the event arguments map. Each
+	 * event may have none, some, or all arguments set.
+	 */
+	public static interface EventTags {
+		/**
+		 * The element that caused the event to be published
+		 */
+		public static final String ELEMENT = "ChangedElement"; //$NON-NLS-1$
+		/**
+		 * The widget that generated the event
+		 */
+		public static final String WIDGET = "Widget"; //$NON-NLS-1$
+		/**
+		 * The event type @see UIEvents.EventTypes
+		 */
+		public static final String TYPE = "EventType"; //$NON-NLS-1$
+		/**
+		 * The attribute name
+		 */
+		public static final String ATTNAME = "AttName"; //$NON-NLS-1$
+		/**
+		 * The old value
+		 */
+		public static final String OLD_VALUE = "OldValue"; //$NON-NLS-1$
+		/**
+		 * The new value
+		 */
+		public static final String NEW_VALUE = "NewValue"; //$NON-NLS-1$
+		/**
+		 * The position (if applicable) of the change within the list.
+		 */
+		public static final String POSITION = "Position"; //$NON-NLS-1$
+	}
+
+	/**
+	 * E4 UI life cycle events. These events are explicitly published by specific operations. They
+	 * are not directly generated by UI model changes.
+	 */
+	public static interface UILifeCycle {
+		/**
+		 * Base name for all UI life cycle events
+		 */
+		public static final String TOPIC = UITopicBase + "/LifeCycle"; //$NON-NLS-1$
+
+		/**
+		 * Sent when a UIElement is brought to top
+		 */
+		public static final String BRINGTOTOP = TOPIC + TOPIC_SEP + "bringToTop"; //$NON-NLS-1$
+
+		/**
+		 * Sent when an MPart is activated
+		 */
+		public static final String ACTIVATE = TOPIC + TOPIC_SEP + "activate"; //$NON-NLS-1$
+
+		/**
+		 * Sent when a perspective is saved
+		 */
+		public static final String PERSPECTIVE_SAVED = TOPIC + TOPIC_SEP + "perpSaved"; //$NON-NLS-1$
+
+		/**
+		 * Sent when a perspective is opened
+		 */
+		public static final String PERSPECTIVE_OPENED = TOPIC + TOPIC_SEP + "perspOpened"; //$NON-NLS-1$
+
+		/**
+		 * Sent when a perspective is reset
+		 *
+		 * @since 1.2
+		 */
+		public static final String PERSPECTIVE_RESET = TOPIC + TOPIC_SEP + "perspReset"; //$NON-NLS-1$
+
+		/**
+		 * Sent when application startup is complete
+		 */
+		public static final String APP_STARTUP_COMPLETE = TOPIC + TOPIC_SEP + "appStartupComplete"; //$NON-NLS-1$
+		/**
+		 * Sent when application shutdown is starting
+		 *
+		 * @since 1.1
+		 */
+		public static final String APP_SHUTDOWN_STARTED = TOPIC + TOPIC_SEP + "appShutdownStarted"; //$NON-NLS-1$
+
+		/**
+		 * Sent when the theme is changed
+		 *
+		 * @since 1.1
+		 */
+		public static final String THEME_CHANGED = TOPIC + TOPIC_SEP + "themeChanged"; //$NON-NLS-1$
+
+		/**
+		 * Sent when the theme definition is changed
+		 *
+		 * @since 1.1
+		 */
+		public static final String THEME_DEFINITION_CHANGED = TOPIC + TOPIC_SEP
+				+ "themeDefinitionChanged"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Publish the topic to the changedElements global event bus. The changedElement is added the
+	 * the EventTags.ELEMENT tag.
+	 *
+	 * @param topic
+	 *            to broadcast
+	 * @param changedElement
+	 *            the element that changed
+	 * @return true if the event is published correctly, false otherwise
+	 */
+	public static boolean publishEvent(String topic, MUIElement changedElement) {
+		if (topic == null || topic.length() == 0 || changedElement == null)
+			return false;
+
+		Map<String, Object> argMap = new HashMap<String, Object>(1);
+		argMap.put(EventTags.ELEMENT, changedElement);
+		return publishEvent(topic, argMap);
+	}
+
+	/**
+	 * Publish the topic with the provided arguments to the global event bus. argMap MUST contain an
+	 * EventTags.ELEMENT argument that is an MUIElement. the contained MUIElement will be used to
+	 * determine the event bus to publish to.
+	 *
+	 * @param topic
+	 *            to broadcast
+	 * @param argMap
+	 *            arguments map with a minimum of a changedElement
+	 * @return true if the event is published correctly, false otherwise
+	 */
+	public static boolean publishEvent(String topic, Map<String, Object> argMap) {
+		if (topic == null || topic.length() == 0 || argMap == null)
+			return false;
+
+		Object uiElement = argMap.get(EventTags.ELEMENT);
+		if (uiElement == null || !(uiElement instanceof MUIElement))
+			return false;
+
+		IEclipseContext context = uiElement instanceof MApplication ? ((MApplication) uiElement)
+				.getContext() : ModelUtils.getContainingContext((MUIElement) uiElement);
+		if (context == null)
+			return false;
+
+		IEventBroker eventBroker = context.get(IEventBroker.class);
+		if (eventBroker == null)
+			return false;
+
+		return eventBroker.send(topic, argMap);
+	}
+
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	/**
+	 * @deprecated Subscribe to an all attribute events on a topic using the TOPIC_ALL constant directly
+	 */
+	public static String buildTopic(String topic) {
+		return topic + TOPIC_SEP + ALL_SUB_TOPICS;
+	}
+
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	/**
+	 * @deprecated Subscribe to an attribute event by using the TOPIC_<attribute> constant directly
+	 */
+	public static String buildTopic(String topic, String attrName) {
+		return topic + TOPIC_SEP + attrName + TOPIC_SEP + ALL_SUB_TOPICS;
+	}
+
+	@SuppressWarnings("javadoc")
+	@Deprecated
+	/**
+	 * @deprecated Subscribing to a particular event type on a topic attribute is not longer supported
+	 */
+	public static String buildTopic(String topic, String attrName, String eventType) {
+		return topic + TOPIC_SEP + attrName + TOPIC_SEP + eventType;
+	}
+
+	/*************************************************************************************
+	 * GENERATED CODE!!
+	 *
+	 * NOTE: *All* non-generated code must be above this comment.
+	 *
+	 * Replace the generated code below this comment with the output of GenTopic.
+	 *
+	 *************************************************************************************/
+
+	@SuppressWarnings("javadoc")
+	public static interface BindingContext {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/BindingContext"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/BindingContext/*"; //$NON-NLS-1$
+		public static final String TOPIC_CHILDREN = "org/eclipse/e4/ui/model/commands/BindingContext/children/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTION = "org/eclipse/e4/ui/model/commands/BindingContext/description/*"; //$NON-NLS-1$
+		public static final String TOPIC_NAME = "org/eclipse/e4/ui/model/commands/BindingContext/name/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CHILDREN = "children"; //$NON-NLS-1$
+		public static final String DESCRIPTION = "description"; //$NON-NLS-1$
+		public static final String NAME = "name"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface BindingTable {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/BindingTable"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/BindingTable/*"; //$NON-NLS-1$
+		public static final String TOPIC_BINDINGCONTEXT = "org/eclipse/e4/ui/model/commands/BindingTable/bindingContext/*"; //$NON-NLS-1$
+		public static final String TOPIC_BINDINGS = "org/eclipse/e4/ui/model/commands/BindingTable/bindings/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String BINDINGCONTEXT = "bindingContext"; //$NON-NLS-1$
+		public static final String BINDINGS = "bindings"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface BindingTableContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/BindingTableContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/BindingTableContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_BINDINGTABLES = "org/eclipse/e4/ui/model/commands/BindingTableContainer/bindingTables/*"; //$NON-NLS-1$
+		public static final String TOPIC_ROOTCONTEXT = "org/eclipse/e4/ui/model/commands/BindingTableContainer/rootContext/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String BINDINGTABLES = "bindingTables"; //$NON-NLS-1$
+		public static final String ROOTCONTEXT = "rootContext"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Bindings {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/Bindings"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/Bindings/*"; //$NON-NLS-1$
+		public static final String TOPIC_BINDINGCONTEXTS = "org/eclipse/e4/ui/model/commands/Bindings/bindingContexts/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String BINDINGCONTEXTS = "bindingContexts"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Category {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/Category"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/Category/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTION = "org/eclipse/e4/ui/model/commands/Category/description/*"; //$NON-NLS-1$
+		public static final String TOPIC_NAME = "org/eclipse/e4/ui/model/commands/Category/name/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_NAME = "org/eclipse/e4/ui/model/commands/Category/localizedName/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String DESCRIPTION = "description"; //$NON-NLS-1$
+		public static final String NAME = "name"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_NAME = "localizedName"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Command {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/Command"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/Command/*"; //$NON-NLS-1$
+		public static final String TOPIC_CATEGORY = "org/eclipse/e4/ui/model/commands/Command/category/*"; //$NON-NLS-1$
+		public static final String TOPIC_COMMANDNAME = "org/eclipse/e4/ui/model/commands/Command/commandName/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTION = "org/eclipse/e4/ui/model/commands/Command/description/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARAMETERS = "org/eclipse/e4/ui/model/commands/Command/parameters/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_COMMANDNAME = "org/eclipse/e4/ui/model/commands/Command/localizedCommandName/*"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_DESCRIPTION = "org/eclipse/e4/ui/model/commands/Command/localizedDescription/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CATEGORY = "category"; //$NON-NLS-1$
+		public static final String COMMANDNAME = "commandName"; //$NON-NLS-1$
+		public static final String DESCRIPTION = "description"; //$NON-NLS-1$
+		public static final String PARAMETERS = "parameters"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_COMMANDNAME = "localizedCommandName"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_DESCRIPTION = "localizedDescription"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface CommandParameter {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/CommandParameter"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/CommandParameter/*"; //$NON-NLS-1$
+		public static final String TOPIC_NAME = "org/eclipse/e4/ui/model/commands/CommandParameter/name/*"; //$NON-NLS-1$
+		public static final String TOPIC_OPTIONAL = "org/eclipse/e4/ui/model/commands/CommandParameter/optional/*"; //$NON-NLS-1$
+		public static final String TOPIC_TYPEID = "org/eclipse/e4/ui/model/commands/CommandParameter/typeId/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String NAME = "name"; //$NON-NLS-1$
+		public static final String OPTIONAL = "optional"; //$NON-NLS-1$
+		public static final String TYPEID = "typeId"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Handler {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/Handler"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/Handler/*"; //$NON-NLS-1$
+		public static final String TOPIC_COMMAND = "org/eclipse/e4/ui/model/commands/Handler/command/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String COMMAND = "command"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface HandlerContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/HandlerContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/HandlerContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_HANDLERS = "org/eclipse/e4/ui/model/commands/HandlerContainer/handlers/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String HANDLERS = "handlers"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface KeyBinding {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/KeyBinding"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/KeyBinding/*"; //$NON-NLS-1$
+		public static final String TOPIC_COMMAND = "org/eclipse/e4/ui/model/commands/KeyBinding/command/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARAMETERS = "org/eclipse/e4/ui/model/commands/KeyBinding/parameters/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String COMMAND = "command"; //$NON-NLS-1$
+		public static final String PARAMETERS = "parameters"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface KeySequence {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/KeySequence"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/KeySequence/*"; //$NON-NLS-1$
+		public static final String TOPIC_KEYSEQUENCE = "org/eclipse/e4/ui/model/commands/KeySequence/keySequence/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String KEYSEQUENCE = "keySequence"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Parameter {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/commands/Parameter"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/commands/Parameter/*"; //$NON-NLS-1$
+		public static final String TOPIC_NAME = "org/eclipse/e4/ui/model/commands/Parameter/name/*"; //$NON-NLS-1$
+		public static final String TOPIC_VALUE = "org/eclipse/e4/ui/model/commands/Parameter/value/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String NAME = "name"; //$NON-NLS-1$
+		public static final String VALUE = "value"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface PartDescriptor {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/PartDescriptor"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/PartDescriptor/*"; //$NON-NLS-1$
+		public static final String TOPIC_ALLOWMULTIPLE = "org/eclipse/e4/ui/model/basic/PartDescriptor/allowMultiple/*"; //$NON-NLS-1$
+		public static final String TOPIC_CATEGORY = "org/eclipse/e4/ui/model/basic/PartDescriptor/category/*"; //$NON-NLS-1$
+		public static final String TOPIC_CLOSEABLE = "org/eclipse/e4/ui/model/basic/PartDescriptor/closeable/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTIONURI = "org/eclipse/e4/ui/model/basic/PartDescriptor/contributionURI/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTION = "org/eclipse/e4/ui/model/basic/PartDescriptor/description/*"; //$NON-NLS-1$
+		public static final String TOPIC_DIRTYABLE = "org/eclipse/e4/ui/model/basic/PartDescriptor/dirtyable/*"; //$NON-NLS-1$
+		public static final String TOPIC_MENUS = "org/eclipse/e4/ui/model/basic/PartDescriptor/menus/*"; //$NON-NLS-1$
+		public static final String TOPIC_TOOLBAR = "org/eclipse/e4/ui/model/basic/PartDescriptor/toolbar/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_DESCRIPTION = "org/eclipse/e4/ui/model/basic/PartDescriptor/localizedDescription/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ALLOWMULTIPLE = "allowMultiple"; //$NON-NLS-1$
+		public static final String CATEGORY = "category"; //$NON-NLS-1$
+		public static final String CLOSEABLE = "closeable"; //$NON-NLS-1$
+		public static final String CONTRIBUTIONURI = "contributionURI"; //$NON-NLS-1$
+		public static final String DESCRIPTION = "description"; //$NON-NLS-1$
+		public static final String DIRTYABLE = "dirtyable"; //$NON-NLS-1$
+		public static final String MENUS = "menus"; //$NON-NLS-1$
+		public static final String TOOLBAR = "toolbar"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_DESCRIPTION = "localizedDescription"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface PartDescriptorContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/PartDescriptorContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/PartDescriptorContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTORS = "org/eclipse/e4/ui/model/basic/PartDescriptorContainer/descriptors/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String DESCRIPTORS = "descriptors"; //$NON-NLS-1$
+	}
+
+	/**
+	 * @since 1.1
+	 */
+	@SuppressWarnings("javadoc")
+	public static interface Application {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/application/Application"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/application/Application/*"; //$NON-NLS-1$
+		public static final String TOPIC_ADDONS = "org/eclipse/e4/ui/model/application/Application/addons/*"; //$NON-NLS-1$
+		public static final String TOPIC_CATEGORIES = "org/eclipse/e4/ui/model/application/Application/categories/*"; //$NON-NLS-1$
+		public static final String TOPIC_COMMANDS = "org/eclipse/e4/ui/model/application/Application/commands/*"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_DIALOGS = "org/eclipse/e4/ui/model/application/Application/dialogs/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ADDONS = "addons"; //$NON-NLS-1$
+		public static final String CATEGORIES = "categories"; //$NON-NLS-1$
+		public static final String COMMANDS = "commands"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String DIALOGS = "dialogs"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface ApplicationElement {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/application/ApplicationElement"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/application/ApplicationElement/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTORURI = "org/eclipse/e4/ui/model/application/ApplicationElement/contributorURI/*"; //$NON-NLS-1$
+		public static final String TOPIC_ELEMENTID = "org/eclipse/e4/ui/model/application/ApplicationElement/elementId/*"; //$NON-NLS-1$
+		public static final String TOPIC_PERSISTEDSTATE = "org/eclipse/e4/ui/model/application/ApplicationElement/persistedState/*"; //$NON-NLS-1$
+		public static final String TOPIC_TAGS = "org/eclipse/e4/ui/model/application/ApplicationElement/tags/*"; //$NON-NLS-1$
+		public static final String TOPIC_TRANSIENTDATA = "org/eclipse/e4/ui/model/application/ApplicationElement/transientData/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTRIBUTORURI = "contributorURI"; //$NON-NLS-1$
+		public static final String ELEMENTID = "elementId"; //$NON-NLS-1$
+		public static final String PERSISTEDSTATE = "persistedState"; //$NON-NLS-1$
+		public static final String TAGS = "tags"; //$NON-NLS-1$
+		public static final String TRANSIENTDATA = "transientData"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Contribution {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/application/Contribution"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/application/Contribution/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTIONURI = "org/eclipse/e4/ui/model/application/Contribution/contributionURI/*"; //$NON-NLS-1$
+		public static final String TOPIC_OBJECT = "org/eclipse/e4/ui/model/application/Contribution/object/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTRIBUTIONURI = "contributionURI"; //$NON-NLS-1$
+		public static final String OBJECT = "object"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface StringToObjectMap {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/application/StringToObjectMap"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/application/StringToObjectMap/*"; //$NON-NLS-1$
+		public static final String TOPIC_KEY = "org/eclipse/e4/ui/model/application/StringToObjectMap/key/*"; //$NON-NLS-1$
+		public static final String TOPIC_VALUE = "org/eclipse/e4/ui/model/application/StringToObjectMap/value/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String KEY = "key"; //$NON-NLS-1$
+		public static final String VALUE = "value"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface StringToStringMap {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/application/StringToStringMap"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/application/StringToStringMap/*"; //$NON-NLS-1$
+		public static final String TOPIC_KEY = "org/eclipse/e4/ui/model/application/StringToStringMap/key/*"; //$NON-NLS-1$
+		public static final String TOPIC_VALUE = "org/eclipse/e4/ui/model/application/StringToStringMap/value/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String KEY = "key"; //$NON-NLS-1$
+		public static final String VALUE = "value"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Perspective {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/advanced/Perspective"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/advanced/Perspective/*"; //$NON-NLS-1$
+		public static final String TOPIC_WINDOWS = "org/eclipse/e4/ui/model/advanced/Perspective/windows/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String WINDOWS = "windows"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Placeholder {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/advanced/Placeholder"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/advanced/Placeholder/*"; //$NON-NLS-1$
+		public static final String TOPIC_CLOSEABLE = "org/eclipse/e4/ui/model/advanced/Placeholder/closeable/*"; //$NON-NLS-1$
+		public static final String TOPIC_REF = "org/eclipse/e4/ui/model/advanced/Placeholder/ref/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CLOSEABLE = "closeable"; //$NON-NLS-1$
+		public static final String REF = "ref"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Part {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/Part"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/Part/*"; //$NON-NLS-1$
+		public static final String TOPIC_CLOSEABLE = "org/eclipse/e4/ui/model/basic/Part/closeable/*"; //$NON-NLS-1$
+		public static final String TOPIC_DESCRIPTION = "org/eclipse/e4/ui/model/basic/Part/description/*"; //$NON-NLS-1$
+		public static final String TOPIC_MENUS = "org/eclipse/e4/ui/model/basic/Part/menus/*"; //$NON-NLS-1$
+		public static final String TOPIC_TOOLBAR = "org/eclipse/e4/ui/model/basic/Part/toolbar/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_DESCRIPTION = "org/eclipse/e4/ui/model/basic/Part/localizedDescription/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CLOSEABLE = "closeable"; //$NON-NLS-1$
+		public static final String DESCRIPTION = "description"; //$NON-NLS-1$
+		public static final String MENUS = "menus"; //$NON-NLS-1$
+		public static final String TOOLBAR = "toolbar"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_DESCRIPTION = "localizedDescription"; //$NON-NLS-1$
+	}
+
+	/**
+	 * @since 1.1
+	 */
+	@SuppressWarnings("javadoc")
+	public static interface TrimBar {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/TrimBar"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/TrimBar/*"; //$NON-NLS-1$
+		public static final String TOPIC_PENDINGCLEANUP = "org/eclipse/e4/ui/model/basic/TrimBar/pendingCleanup/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String PENDINGCLEANUP = "pendingCleanup"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface TrimmedWindow {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/TrimmedWindow"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/TrimmedWindow/*"; //$NON-NLS-1$
+		public static final String TOPIC_TRIMBARS = "org/eclipse/e4/ui/model/basic/TrimmedWindow/trimBars/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String TRIMBARS = "trimBars"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Window {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/basic/Window"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/basic/Window/*"; //$NON-NLS-1$
+		public static final String TOPIC_HEIGHT = "org/eclipse/e4/ui/model/basic/Window/height/*"; //$NON-NLS-1$
+		public static final String TOPIC_MAINMENU = "org/eclipse/e4/ui/model/basic/Window/mainMenu/*"; //$NON-NLS-1$
+		public static final String TOPIC_SHAREDELEMENTS = "org/eclipse/e4/ui/model/basic/Window/sharedElements/*"; //$NON-NLS-1$
+		public static final String TOPIC_WIDTH = "org/eclipse/e4/ui/model/basic/Window/width/*"; //$NON-NLS-1$
+		public static final String TOPIC_WINDOWS = "org/eclipse/e4/ui/model/basic/Window/windows/*"; //$NON-NLS-1$
+		public static final String TOPIC_X = "org/eclipse/e4/ui/model/basic/Window/x/*"; //$NON-NLS-1$
+		public static final String TOPIC_Y = "org/eclipse/e4/ui/model/basic/Window/y/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String HEIGHT = "height"; //$NON-NLS-1$
+		public static final String MAINMENU = "mainMenu"; //$NON-NLS-1$
+		public static final String SHAREDELEMENTS = "sharedElements"; //$NON-NLS-1$
+		public static final String WIDTH = "width"; //$NON-NLS-1$
+		public static final String WINDOWS = "windows"; //$NON-NLS-1$
+		public static final String X = "x"; //$NON-NLS-1$
+		public static final String Y = "y"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Context {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/Context"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/Context/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTEXT = "org/eclipse/e4/ui/model/ui/Context/context/*"; //$NON-NLS-1$
+		public static final String TOPIC_PROPERTIES = "org/eclipse/e4/ui/model/ui/Context/properties/*"; //$NON-NLS-1$
+		public static final String TOPIC_VARIABLES = "org/eclipse/e4/ui/model/ui/Context/variables/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTEXT = "context"; //$NON-NLS-1$
+		public static final String PROPERTIES = "properties"; //$NON-NLS-1$
+		public static final String VARIABLES = "variables"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface CoreExpression {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/CoreExpression"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/CoreExpression/*"; //$NON-NLS-1$
+		public static final String TOPIC_COREEXPRESSION = "org/eclipse/e4/ui/model/ui/CoreExpression/coreExpression/*"; //$NON-NLS-1$
+		public static final String TOPIC_COREEXPRESSIONID = "org/eclipse/e4/ui/model/ui/CoreExpression/coreExpressionId/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String COREEXPRESSION = "coreExpression"; //$NON-NLS-1$
+		public static final String COREEXPRESSIONID = "coreExpressionId"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Dirtyable {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/Dirtyable"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/Dirtyable/*"; //$NON-NLS-1$
+		public static final String TOPIC_DIRTY = "org/eclipse/e4/ui/model/ui/Dirtyable/dirty/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String DIRTY = "dirty"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface ElementContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/ElementContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/ElementContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_CHILDREN = "org/eclipse/e4/ui/model/ui/ElementContainer/children/*"; //$NON-NLS-1$
+		public static final String TOPIC_SELECTEDELEMENT = "org/eclipse/e4/ui/model/ui/ElementContainer/selectedElement/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CHILDREN = "children"; //$NON-NLS-1$
+		public static final String SELECTEDELEMENT = "selectedElement"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface GenericTile {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/GenericTile"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/GenericTile/*"; //$NON-NLS-1$
+		public static final String TOPIC_HORIZONTAL = "org/eclipse/e4/ui/model/ui/GenericTile/horizontal/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String HORIZONTAL = "horizontal"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface GenericTrimContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/GenericTrimContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/GenericTrimContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_SIDE = "org/eclipse/e4/ui/model/ui/GenericTrimContainer/side/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String SIDE = "side"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Input {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/Input"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/Input/*"; //$NON-NLS-1$
+		public static final String TOPIC_INPUTURI = "org/eclipse/e4/ui/model/ui/Input/inputURI/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String INPUTURI = "inputURI"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface SnippetContainer {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/SnippetContainer"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/SnippetContainer/*"; //$NON-NLS-1$
+		public static final String TOPIC_SNIPPETS = "org/eclipse/e4/ui/model/ui/SnippetContainer/snippets/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String SNIPPETS = "snippets"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface UIElement {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/UIElement"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/UIElement/*"; //$NON-NLS-1$
+		public static final String TOPIC_ACCESSIBILITYPHRASE = "org/eclipse/e4/ui/model/ui/UIElement/accessibilityPhrase/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTAINERDATA = "org/eclipse/e4/ui/model/ui/UIElement/containerData/*"; //$NON-NLS-1$
+		public static final String TOPIC_CURSHAREDREF = "org/eclipse/e4/ui/model/ui/UIElement/curSharedRef/*"; //$NON-NLS-1$
+		public static final String TOPIC_ONTOP = "org/eclipse/e4/ui/model/ui/UIElement/onTop/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARENT = "org/eclipse/e4/ui/model/ui/UIElement/parent/*"; //$NON-NLS-1$
+		public static final String TOPIC_RENDERER = "org/eclipse/e4/ui/model/ui/UIElement/renderer/*"; //$NON-NLS-1$
+		public static final String TOPIC_TOBERENDERED = "org/eclipse/e4/ui/model/ui/UIElement/toBeRendered/*"; //$NON-NLS-1$
+		public static final String TOPIC_VISIBLE = "org/eclipse/e4/ui/model/ui/UIElement/visible/*"; //$NON-NLS-1$
+		public static final String TOPIC_VISIBLEWHEN = "org/eclipse/e4/ui/model/ui/UIElement/visibleWhen/*"; //$NON-NLS-1$
+		public static final String TOPIC_WIDGET = "org/eclipse/e4/ui/model/ui/UIElement/widget/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_ACCESSIBILITYPHRASE = "org/eclipse/e4/ui/model/ui/UIElement/localizedAccessibilityPhrase/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ACCESSIBILITYPHRASE = "accessibilityPhrase"; //$NON-NLS-1$
+		public static final String CONTAINERDATA = "containerData"; //$NON-NLS-1$
+		public static final String CURSHAREDREF = "curSharedRef"; //$NON-NLS-1$
+		public static final String ONTOP = "onTop"; //$NON-NLS-1$
+		public static final String PARENT = "parent"; //$NON-NLS-1$
+		public static final String RENDERER = "renderer"; //$NON-NLS-1$
+		public static final String TOBERENDERED = "toBeRendered"; //$NON-NLS-1$
+		public static final String VISIBLE = "visible"; //$NON-NLS-1$
+		public static final String VISIBLEWHEN = "visibleWhen"; //$NON-NLS-1$
+		public static final String WIDGET = "widget"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_ACCESSIBILITYPHRASE = "localizedAccessibilityPhrase"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface UILabel {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/ui/UILabel"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/UILabel/*"; //$NON-NLS-1$
+		public static final String TOPIC_ICONURI = "org/eclipse/e4/ui/model/ui/UILabel/iconURI/*"; //$NON-NLS-1$
+		public static final String TOPIC_LABEL = "org/eclipse/e4/ui/model/ui/UILabel/label/*"; //$NON-NLS-1$
+		public static final String TOPIC_TOOLTIP = "org/eclipse/e4/ui/model/ui/UILabel/tooltip/*"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_LABEL = "org/eclipse/e4/ui/model/ui/UILabel/localizedLabel/*"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String TOPIC_LOCALIZED_TOOLTIP = "org/eclipse/e4/ui/model/ui/UILabel/localizedTooltip/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ICONURI = "iconURI"; //$NON-NLS-1$
+		public static final String LABEL = "label"; //$NON-NLS-1$
+		public static final String TOOLTIP = "tooltip"; //$NON-NLS-1$
+
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_LABEL = "localizedLabel"; //$NON-NLS-1$
+		/**
+		 * @since 1.1
+		 */
+		public static final String LOCALIZED_TOOLTIP = "localizedTooltip"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface HandledItem {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/HandledItem"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/HandledItem/*"; //$NON-NLS-1$
+		public static final String TOPIC_COMMAND = "org/eclipse/e4/ui/model/menu/HandledItem/command/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARAMETERS = "org/eclipse/e4/ui/model/menu/HandledItem/parameters/*"; //$NON-NLS-1$
+		public static final String TOPIC_WBCOMMAND = "org/eclipse/e4/ui/model/menu/HandledItem/wbCommand/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String COMMAND = "command"; //$NON-NLS-1$
+		public static final String PARAMETERS = "parameters"; //$NON-NLS-1$
+		public static final String WBCOMMAND = "wbCommand"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Item {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/Item"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/Item/*"; //$NON-NLS-1$
+		public static final String TOPIC_ENABLED = "org/eclipse/e4/ui/model/menu/Item/enabled/*"; //$NON-NLS-1$
+		public static final String TOPIC_SELECTED = "org/eclipse/e4/ui/model/menu/Item/selected/*"; //$NON-NLS-1$
+		public static final String TOPIC_TYPE = "org/eclipse/e4/ui/model/menu/Item/type/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ENABLED = "enabled"; //$NON-NLS-1$
+		public static final String SELECTED = "selected"; //$NON-NLS-1$
+		public static final String TYPE = "type"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface Menu {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/Menu"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/Menu/*"; //$NON-NLS-1$
+		public static final String TOPIC_ENABLED = "org/eclipse/e4/ui/model/menu/Menu/enabled/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String ENABLED = "enabled"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface MenuContribution {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/MenuContribution"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/MenuContribution/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARENTID = "org/eclipse/e4/ui/model/menu/MenuContribution/parentId/*"; //$NON-NLS-1$
+		public static final String TOPIC_POSITIONINPARENT = "org/eclipse/e4/ui/model/menu/MenuContribution/positionInParent/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String PARENTID = "parentId"; //$NON-NLS-1$
+		public static final String POSITIONINPARENT = "positionInParent"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface MenuContributions {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/MenuContributions"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/MenuContributions/*"; //$NON-NLS-1$
+		public static final String TOPIC_MENUCONTRIBUTIONS = "org/eclipse/e4/ui/model/menu/MenuContributions/menuContributions/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String MENUCONTRIBUTIONS = "menuContributions"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface MenuElement {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/MenuElement"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/MenuElement/*"; //$NON-NLS-1$
+		public static final String TOPIC_MNEMONICS = "org/eclipse/e4/ui/model/menu/MenuElement/mnemonics/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String MNEMONICS = "mnemonics"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface OpaqueMenuItem {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/OpaqueMenuItem"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/OpaqueMenuItem/*"; //$NON-NLS-1$
+		public static final String TOPIC_OPAQUEITEM = "org/eclipse/e4/ui/model/menu/OpaqueMenuItem/opaqueItem/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String OPAQUEITEM = "opaqueItem"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface OpaqueMenuSeparator {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/OpaqueMenuSeparator"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/OpaqueMenuSeparator/*"; //$NON-NLS-1$
+		public static final String TOPIC_OPAQUEITEM = "org/eclipse/e4/ui/model/menu/OpaqueMenuSeparator/opaqueItem/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String OPAQUEITEM = "opaqueItem"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface OpaqueToolItem {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/OpaqueToolItem"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/OpaqueToolItem/*"; //$NON-NLS-1$
+		public static final String TOPIC_OPAQUEITEM = "org/eclipse/e4/ui/model/menu/OpaqueToolItem/opaqueItem/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String OPAQUEITEM = "opaqueItem"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface RenderedMenu {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/RenderedMenu"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/RenderedMenu/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTIONMANAGER = "org/eclipse/e4/ui/model/menu/RenderedMenu/contributionManager/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTRIBUTIONMANAGER = "contributionManager"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface RenderedMenuItem {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/RenderedMenuItem"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/RenderedMenuItem/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTIONITEM = "org/eclipse/e4/ui/model/menu/RenderedMenuItem/contributionItem/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTRIBUTIONITEM = "contributionItem"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface RenderedToolBar {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/RenderedToolBar"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/RenderedToolBar/*"; //$NON-NLS-1$
+		public static final String TOPIC_CONTRIBUTIONMANAGER = "org/eclipse/e4/ui/model/menu/RenderedToolBar/contributionManager/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String CONTRIBUTIONMANAGER = "contributionManager"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface ToolBarContribution {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/ToolBarContribution"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/ToolBarContribution/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARENTID = "org/eclipse/e4/ui/model/menu/ToolBarContribution/parentId/*"; //$NON-NLS-1$
+		public static final String TOPIC_POSITIONINPARENT = "org/eclipse/e4/ui/model/menu/ToolBarContribution/positionInParent/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String PARENTID = "parentId"; //$NON-NLS-1$
+		public static final String POSITIONINPARENT = "positionInParent"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface ToolBarContributions {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/ToolBarContributions"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/ToolBarContributions/*"; //$NON-NLS-1$
+		public static final String TOPIC_TOOLBARCONTRIBUTIONS = "org/eclipse/e4/ui/model/menu/ToolBarContributions/toolBarContributions/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String TOOLBARCONTRIBUTIONS = "toolBarContributions"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface ToolItem {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/ToolItem"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/ToolItem/*"; //$NON-NLS-1$
+		public static final String TOPIC_MENU = "org/eclipse/e4/ui/model/menu/ToolItem/menu/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String MENU = "menu"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface TrimContribution {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/TrimContribution"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/TrimContribution/*"; //$NON-NLS-1$
+		public static final String TOPIC_PARENTID = "org/eclipse/e4/ui/model/menu/TrimContribution/parentId/*"; //$NON-NLS-1$
+		public static final String TOPIC_POSITIONINPARENT = "org/eclipse/e4/ui/model/menu/TrimContribution/positionInParent/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String PARENTID = "parentId"; //$NON-NLS-1$
+		public static final String POSITIONINPARENT = "positionInParent"; //$NON-NLS-1$
+	}
+
+	@SuppressWarnings("javadoc")
+	public static interface TrimContributions {
+
+		// Topics that can be subscribed to
+
+		@Deprecated
+		public static final String TOPIC = "org/eclipse/e4/ui/model/menu/TrimContributions"; //$NON-NLS-1$
+
+		public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/menu/TrimContributions/*"; //$NON-NLS-1$
+		public static final String TOPIC_TRIMCONTRIBUTIONS = "org/eclipse/e4/ui/model/menu/TrimContributions/trimContributions/*"; //$NON-NLS-1$
+
+		// Attributes that can be tested in event handlers
+		public static final String TRIMCONTRIBUTIONS = "trimContributions"; //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PostContextCreate.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PostContextCreate.java
new file mode 100644
index 0000000..87df75f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PostContextCreate.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.lifecycle;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to describe methods that will participate in the application lifecycle. This
+ * method will be called after application context is created.
+ */
+@Documented
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PostContextCreate {
+	// intentionally left empty
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PreSave.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PreSave.java
new file mode 100644
index 0000000..9c65cb4
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/PreSave.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.lifecycle;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to describe methods that will participate in the application lifecycle. This
+ * method will be called before the model is persisted.
+ */
+@Documented
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PreSave {
+	// intentionally left empty
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessAdditions.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessAdditions.java
new file mode 100644
index 0000000..4ec5d79
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessAdditions.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.lifecycle;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to describe methods that will participate in the application lifecycle. This
+ * method will be called once the model is loaded.
+ */
+@Documented
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ProcessAdditions {
+	// intentionally left empty
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessRemovals.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessRemovals.java
new file mode 100644
index 0000000..c5e8c11
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/lifecycle/ProcessRemovals.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.lifecycle;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to describe methods that will participate in the application lifecycle. This
+ * method will be called after the {@link ProcessAdditions} calls are done.
+ */
+@Documented
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ProcessRemovals {
+	// intentionally left empty
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java
new file mode 100644
index 0000000..244f83e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.modeling;
+
+import java.util.List;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MSnippetContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.workbench.Selector;
+
+/**
+ * This service is used to find, create and handle model elements
+ *
+ * @since 1.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface EModelService {
+	// Insertion constants
+
+	/** Insert the new element above the existing one */
+	public static final int ABOVE = 0;
+
+	/** Insert the new element below the existing one */
+	public static final int BELOW = 1;
+
+	/** Insert the new element to the left of the existing one */
+	public static final int LEFT_OF = 2;
+
+	/** Insert the new element to the right of the existing one */
+	public static final int RIGHT_OF = 3;
+
+	// Search modifiers / Location Constants
+
+	/** Returned Location if the element's parent chain does not relate to the MApplication's model */
+	public static final int NOT_IN_UI = 0x00;
+
+	/** Returned Location if the element is in the UI but not in an MPerspective */
+	public static final int OUTSIDE_PERSPECTIVE = 0x01;
+
+	/** Returned Location if the element is in the currently active perspective */
+	public static final int IN_ACTIVE_PERSPECTIVE = 0x02;
+
+	/** Returned Location if the element is in a non-active perspective */
+	public static final int IN_ANY_PERSPECTIVE = 0x04;
+
+	/** Returned Location if the element is contained in an MArea */
+	public static final int IN_SHARED_AREA = 0x08;
+
+	/** Returned Location if the element is in an MTrimBar */
+	public static final int IN_TRIM = 0x10;
+
+	/**
+	 * Returned Location if the element is in a main menu of an MWindow
+	 *
+	 * @since 1.1
+	 */
+	public static final int IN_MAIN_MENU = 0x20;
+
+	/**
+	 * Returned Location if the element is in an MPart
+	 *
+	 * @since 1.1
+	 */
+	public static final int IN_PART = 0x40;
+
+	// 'Standard' searches
+
+	/** Searches for elements in the UI that the user is currently seeing (excluding trim) */
+	public static final int PRESENTATION = OUTSIDE_PERSPECTIVE | IN_ACTIVE_PERSPECTIVE
+			| IN_SHARED_AREA;
+
+	/** Searches for elements in the UI presentation, including all perspectives */
+	public static final int ANYWHERE = OUTSIDE_PERSPECTIVE | IN_ANY_PERSPECTIVE | IN_SHARED_AREA
+			| IN_TRIM;
+
+	/**
+	 * Searches for elements in the UI that the user is currently seeing that are OUTSIDE the
+	 * perspective (i.e. visible regardless of the current perspective)
+	 */
+	public static final int GLOBAL = OUTSIDE_PERSPECTIVE | IN_SHARED_AREA;
+
+	/**
+	 * When invoking the 'cloneElement' method the newly cloned element's 'transientData' map will
+	 * contain a reference to the original element using this as a key.
+	 *
+	 * @since 1.1
+	 */
+	public static String CLONED_FROM_KEY = "Cloned From"; //$NON-NLS-1$
+
+	/**
+	 * Creates instances of model elements. The method supports any type extending
+	 * {@link MApplicationElement}, both in the standard e4 UI model and in an extension models.
+	 *
+	 * <p>
+	 * <b>Caution:</b> To create model element instances of extension models you need to register
+	 * them with the <code>the org.eclipse.e4.workbench.model.definition.enrichment</code>
+	 * ExtensionPoint.
+	 * </p>
+	 *
+	 * @param elementType
+	 *            the class to instantiate. Cannot be <code>null</code>
+	 * @return a new instance
+	 * @throws NullPointerException
+	 *             if the passed class is <code>null</code>
+	 * @throws IllegalArgumentException
+	 *             if the passed class is not supported.
+	 */
+	public <T extends MApplicationElement> T createModelElement(Class<T> elementType);
+
+	/**
+	 * This is a convenience method that constructs a new Selector based on {@link ElementMatcher}
+	 * and forwards the call on to the base API
+	 * {@link EModelService#findElements(MApplicationElement, Class, int, Selector)}.
+	 *
+	 * @see EModelService#findElements(MApplicationElement, Class, int, Selector)
+	 */
+	public <T> List<T> findElements(MUIElement searchRoot, String id, Class<T> clazz,
+			List<String> tagsToMatch, int searchFlags);
+
+	/**
+	 * This is a convenience method that forwards the parameters on to
+	 * {@link EModelService#findElements(MUIElement, String, Class, List, int)}, passing
+	 * {@link EModelService#ANYWHERE} as the 'searchFlags'.
+	 *
+	 */
+	public <T> List<T> findElements(MUIElement searchRoot, String id, Class<T> clazz,
+			List<String> tagsToMatch);
+
+	/**
+	 * Return a list of any elements that match the given search criteria. The search is recursive
+	 * and includes the specified search root. Any of the search parameters may be specified as
+	 * <code>null</code> in which case that field will always 'match'.
+	 * <p>
+	 * NOTE: This is a generically typed method with the List's generic type expected to be the
+	 * value of the 'clazz' parameter. If the 'clazz' parameter is null then the returned list is
+	 * untyped.
+	 * </p>
+	 *
+	 * @param <T>
+	 *            The generic type of the returned list
+	 * @param searchRoot
+	 *            The element at which to start the search. This element must be non-null and is
+	 *            included in the search.
+	 * @param clazz
+	 *            The type of element to be searched for. If non-null this also defines the return
+	 *            type of the List.
+	 * @param searchFlags
+	 *            A bitwise combination of the following constants:
+	 *            <ul>
+	 *            <li><b>OUTSIDE_PERSPECTIVE</b> Include the elements in the window's model that are
+	 *            not in a perspective</;i>
+	 *            <li><b>IN_ANY_PERSPECTIVE</b> Include the elements in all perspectives</;i>
+	 *            <li><b>IN_ACTIVE_PERSPECTIVE</b> Include the elements in the currently active
+	 *            perspective only</;i>
+	 *            <li><b>IN_MAIN_MENU</b> Include elements in an MWindow's main menu</;i>
+	 *            <li><b>IN_PART</b> Include MMenu and MToolbar elements owned by parts</;i>
+	 *            <li><b>IN_ACTIVE_PERSPECTIVE</b> Include the elements in the currently active
+	 *            perspective only</;i>
+	 *            <li><b>IN_SHARED_AREA</b> Include the elements in the shared area</;i>
+	 *            <li><b>IN_TRIM</b> Include the elements in the window's trim</;i>
+	 *            </ul>
+	 *            Note that you may omit both perspective flags but still define
+	 *            <b>IN_SHARED_AREA</b>; the flags <b>OUTSIDE_PERSPECTIVE | IN_SHARED_AREA</b> for
+	 *            example will search the presentation <i>excluding</i> the elements in perspective
+	 *            stacks.
+	 * @param matcher
+	 *            An implementation of a Selector that will return true for elements that it wants
+	 *            in the returned list.
+	 * @return The generically typed list of matching elements.
+	 *
+	 * @since 1.1
+	 */
+	public <T> List<T> findElements(MApplicationElement searchRoot, Class<T> clazz,
+			int searchFlags, Selector matcher);
+
+	/**
+	 * Returns the first element, recursively searching under the specified search root (inclusive)
+	 *
+	 * @param id
+	 *            The id to search for, must not be null
+	 * @param searchRoot
+	 *            The element at which to start the search, must not be null
+	 * @return The first element with a matching id or <code>null</code> if one is not found
+	 */
+	public MUIElement find(String id, MUIElement searchRoot);
+
+	/**
+	 * Locate the context that is closest to the given element in the parent hierarchy. It does not
+	 * include the context of the supplied element (should it have one).
+	 *
+	 * @param element
+	 *            the element to locate parent context for
+	 * @return the containing context for this element
+	 */
+	public IEclipseContext getContainingContext(MUIElement element);
+
+	/**
+	 * Brings the specified element to the top of its containment structure. If the specified
+	 * element is a top-level window, then it will be selected as the application's currently active
+	 * window. Otherwise, the element may merely be brought up to be seen by the user but not
+	 * necessarily have its containing window become the application's active window.
+	 *
+	 * @param element
+	 *            The element to bring to the top
+	 */
+	public void bringToTop(MUIElement element);
+
+	/**
+	 * Clones the element, creating a deep copy of its structure.
+	 *
+	 * NOTE: The cloned element gets the original element added into its 'transientData' map using
+	 * the CLONED_FROM_KEY key. This is useful in cases where there may be other information the
+	 * newly cloned element needs from the original.
+	 *
+	 * @param element
+	 *            The element to clone
+	 * @param snippetContainer
+	 *            An optional MUIElement where the cloned snippet is to be saved. null if the clone
+	 *            need not be saved
+	 * @return The newly cloned element
+	 */
+	public MUIElement cloneElement(MUIElement element, MSnippetContainer snippetContainer);
+
+	/**
+	 * If a snippet with the given id exists a clone is created and returned. returns
+	 * <code>null</code> if no snippet can be found.
+	 *
+	 * @param snippetContainer
+	 *            The container of the snippet to clone used
+	 * @param snippetId
+	 *            The element id of the snippet to clone
+	 * @param refWin
+	 *            The window that Placeholder references should be resolved using
+	 *
+	 * @return The cloned snippet or <code>null</code> if no snippet with the given id can be found
+	 */
+	public MUIElement cloneSnippet(MSnippetContainer snippetContainer, String snippetId,
+			MWindow refWin);
+
+	/**
+	 * Convenience method to find a snippet by id in a particular container
+	 *
+	 * @param snippetContainer
+	 *            The container to look in
+	 * @param id
+	 *            The id of the root element of the snippet
+	 * @return The root element of the snippet or <code>null</code> if none is found
+	 */
+	public MUIElement findSnippet(MSnippetContainer snippetContainer, String id);
+
+	/**
+	 * Return the count of the children whose 'toBeRendered' flag is true
+	 *
+	 * @param element
+	 *            The element to test
+	 * @return the number of children with 'toBeRendered' == true
+	 */
+	public int countRenderableChildren(MUIElement element);
+
+	/**
+	 * Given a containing MWindow find the MPlaceholder that is currently being used to host the
+	 * given element (if any)
+	 *
+	 * @param window
+	 *            The containing window
+	 * @param element
+	 *            The element to find the MPlaceholder for
+	 * @return the MPlaceholder or null if none is found
+	 */
+	public MPlaceholder findPlaceholderFor(MWindow window, MUIElement element);
+
+	/**
+	 * Move the element to a new location. The element will be placed at the end of the new parent's
+	 * list of children.
+	 *
+	 * @param element
+	 *            The element to move
+	 * @param newParent
+	 *            The new parent for the element.
+	 */
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent);
+
+	/**
+	 * Move the element to a new location. The element will be placed at the end of the new parent's
+	 * list of children. If 'leavePlaceholder is true then an instance of MPlaceholder will be
+	 * inserted into the model at the element's original location.
+	 *
+	 * @param element
+	 *            The element to move
+	 * @param newParent
+	 *            The new parent for the element.
+	 * @param leavePlaceholder
+	 *            true if a placeholder for the element should be added
+	 */
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent,
+			boolean leavePlaceholder);
+
+	/**
+	 * Move the element to a new location. The element will be placed at the specified index in the
+	 * new parent's list of children.
+	 *
+	 * @param element
+	 *            The element to move
+	 * @param newParent
+	 *            The new parent for the element.
+	 * @param index
+	 *            The index to insert the element at; -1 means at the end
+	 */
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent, int index);
+
+	/**
+	 * Move the element to a new location. The element will be placed at the end of the new parent's
+	 * list of children.
+	 *
+	 * @param element
+	 *            The element to move
+	 * @param newParent
+	 *            The new parent for the element.
+	 * @param index
+	 *            The index to insert the element at; -1 means at the end
+	 * @param leavePlaceholder
+	 *            true if a placeholder for the element should be added
+	 */
+	public void move(MUIElement element, MElementContainer<MUIElement> newParent, int index,
+			boolean leavePlaceholder);
+
+	/**
+	 * Inserts the given element into the UI Model by either creating a new sash or augmenting an
+	 * existing sash if the orientation permits.
+	 *
+	 * @param toInsert
+	 *            The element to insert
+	 * @param relTo
+	 *            The element that the new one is to be relative to
+	 * @param where
+	 *            An SWT constant indicating where the inserted element should be placed
+	 * @param ratio
+	 *            The percentage of the area to be occupied by the inserted element
+	 */
+	public void insert(MPartSashContainerElement toInsert, MPartSashContainerElement relTo,
+			int where, float ratio);
+
+	/**
+	 * Created a separate (detached) window containing the given element.
+	 *
+	 * @param mPartSashContainerElement
+	 *            The element to detach
+	 * @param x
+	 *            The X position of the new window
+	 * @param y
+	 *            The Y position of the new window
+	 * @param width
+	 *            The Width of the new window
+	 * @param height
+	 *            The Height of the new window
+	 */
+	public void detach(MPartSashContainerElement mPartSashContainerElement, int x, int y,
+			int width, int height);
+
+	/**
+	 * Get the top-level window containing this UI element. A <code>null</code> return value
+	 * indicates that the element is not directly contained in the UI model (but may, for example,
+	 * be a model snippet hosted in a Dialog...)
+	 *
+	 * @param element
+	 *            The element to get the window for
+	 *
+	 * @return the top-level window containing this UI element. A <code>null</code> return value
+	 *         indicates that the element is not directly contained in the UI model (but may, for
+	 *         example, be a model snippet hosted in a Dialog...)
+	 */
+	public MWindow getTopLevelWindowFor(MUIElement element);
+
+	/**
+	 * @param element
+	 *            The element to get the perspective for
+	 * @return The MPerspective containing this element or <code>null</code> if the element is not
+	 *         in a perspective
+	 */
+	public MPerspective getPerspectiveFor(MUIElement element);
+
+	/**
+	 * Returns the window's MTrimBar for the specified side. If necessary the bar will be created.
+	 *
+	 * @param window
+	 *            The window to get the trim bar for
+	 * @param sv
+	 *            The value for the specified side
+	 *
+	 * @return The appropriate trim bar
+	 */
+	public MTrimBar getTrim(MTrimmedWindow window, SideValue sv);
+
+	/**
+	 * Return the active perspective for the given window. This is a convenience method that just
+	 * returns the MPerspectiveStack's selectedElement.
+	 *
+	 * @param window
+	 *            The window to determine the active perspective for.
+	 *
+	 * @return The active perspective or <code>null</code> if there is no MPerspectiveStack, it's
+	 *         empty or has no selected element.
+	 */
+	public MPerspective getActivePerspective(MWindow window);
+
+	/**
+	 * This is a convenience method that will clean the model of all traces of a given perspective.
+	 * There may be elements (i.e. minimized stacks...) in the window's trim that are associated
+	 * with a perspective as well as the need to properly clean up any detached windows associated
+	 * with the perspective.
+	 *
+	 * @param persp
+	 *            the perspective to remove
+	 * @param window
+	 *            the window to remove it from
+	 */
+	public void resetPerspectiveModel(MPerspective persp, MWindow window);
+
+	/**
+	 * Remove the given perspective completely from the model.
+	 *
+	 * @param persp
+	 *            the perspective to remove
+	 * @param window
+	 *            the window to remove it from
+	 */
+	public void removePerspectiveModel(MPerspective persp, MWindow window);
+
+	/**
+	 * Count the number of 'toBeRendered' children
+	 *
+	 * @param container
+	 *            The container to check
+	 * @return The number of children whose toBeRendered flag is <code>true</code>
+	 *
+	 */
+	public int toBeRenderedCount(MElementContainer<?> container);
+
+	/**
+	 * Get the container of the given element. This is a convenience method that will always return
+	 * the actual container for the element, even where the element's 'getParent' might return null
+	 * (trim, detached windows...)
+	 *
+	 * @param element
+	 *            The element to get the container for
+	 * @return The element's container. This may be <code>null</code> if the element being checked
+	 *         is a snippet unattached to the UI Model itself.
+	 */
+	public MUIElement getContainer(MUIElement element);
+
+	/**
+	 * Given an element this method responds with information about where the element exists within
+	 * the current UI Model. This is used in cases where it is necessary to know if an element is in
+	 * the 'shared area' or outside of any perspective.
+	 *
+	 * @param element
+	 * @return The location of the element in the UI, will be one of:
+	 *         <ul>
+	 *         <li><b>NOT_IN_UI:</b> The element is not in the UI model at all</li>
+	 *         <li><b>OUTSIDE_PERSPECTIVE:</b> The element not within a perspective stack</li>
+	 *         <li><b>IN_ACTIVE_PERSPECTIVE:</b> The element is within the currently active
+	 *         perspective</li>
+	 *         <li><b>IN_ANY_PERSPECTIVE:</b> The element is within a perspective but not the active
+	 *         one</li>
+	 *         <li><b>IN_SHARED_AREA:</b> The element is within an area that is shared between
+	 *         different perspectives</li>
+	 *         </ul>
+	 */
+	public int getElementLocation(MUIElement element);
+
+	/**
+	 * Returns the descriptor for the given part id.
+	 * <p>
+	 * <b>NOTE:</b> In order to support multiple instance parts there is a convention where the
+	 * part's id may be in the form 'partId:secondaryId'. If the given id contains a ':' then only
+	 * the substring before the ':' will be used to find the descriptor.
+	 * </p>
+	 * <p>
+	 * In order to support this convention it's required that no descriptor contain a ':' in its id
+	 * </p>
+	 *
+	 * @param id
+	 *            The id of the descriptor to return
+	 * @return The descriptor matching the id or <code>null</code> if none exists
+	 */
+	public MPartDescriptor getPartDescriptor(String id);
+
+	/**
+	 * This method ensures that there will never be two placeholders for the same referenced element
+	 * visible in the presentation at the same time. It does this by hiding placeholders which are
+	 * contained in any MPerspective if there is a placeholder for the element in any 'shared' area
+	 * (i.e. visible regardless of which perspective is visible) by setting its 'toBeRendered' state
+	 * to <code>false</code>.
+	 *
+	 * @param window
+	 *            The window to modify
+	 * @param perspective
+	 *            if non-null specifies the specific perspective to modify, otherwise all
+	 *            perspectives in the window are checked
+	 */
+	public void hideLocalPlaceholders(MWindow window, MPerspective perspective);
+
+	/**
+	 * Returns <code>true</code> iff the supplied element represents the single visible element in
+	 * the shared area. This method is used to test for this condition since (by convention) there
+	 * must be at least one stack in the shared area at all times.
+	 *
+	 * @param stack
+	 *            The element to test
+	 * @return <code>true</code> iff the element is the last visible stack
+	 */
+	public boolean isLastEditorStack(MUIElement stack);
+
+	/**
+	 * Allows an element to be rendered in an arbitrary UI container (I.e. SWT Composite).
+	 *
+	 * @param element
+	 *            The element to be rendered.
+	 * @param hostWindow
+	 *            The MWindow the element is being hosted under. Must be non-nulland rendered.
+	 * @param uiContainer
+	 *            The UI container acting as the rendered element's parent. Must be non-null.
+	 * @param hostContext
+	 *            The IEclipseContext to use for hosting the element. Must be non-null.
+	 */
+	public void hostElement(MUIElement element, MWindow hostWindow, Object uiContainer,
+			IEclipseContext hostContext);
+
+	/**
+	 * Tests whether the given element is being 'hosted'. This method is used to allow UI Elements
+	 * to act as if they are contained within a given MWindow even though the element is not
+	 * actually structurally contained in that window's UI Model.
+	 *
+	 * @param element
+	 *            The element to test. Must be non-null.
+	 * @param hostWindow
+	 *            The window to test the element against. Must be non-null.
+	 *
+	 * @return <code>true</code> iff the given element or one of its ancestors is currently being
+	 *         hosted in the given MWindow.
+	 */
+	public boolean isHostedElement(MUIElement element, MWindow hostWindow);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EObjModelHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EObjModelHandler.java
new file mode 100644
index 0000000..13c2fc8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EObjModelHandler.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2015 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
+ *     Simon Scholz <simon.scholz@vogella.com> - Bug 460405
+ *******************************************************************************/
+package org.eclipse.e4.ui.workbench.modeling;
+
+import java.util.Iterator;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @noreference This class is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public class EObjModelHandler extends ModelHandlerBase implements IAdapterFactory {
+
+	@Override
+	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
+		if (adapterType.isInstance(this)) {
+			return adapterType.cast(this);
+		}
+		return null;
+	}
+
+	@Override
+	public Class<?>[] getAdapterList() {
+		return new Class[] { ModelHandlerBase.class };
+	}
+
+	@Override
+	public Object[] getChildren(Object element, String id) {
+		EObject eObj = (EObject) element;
+		return eObj.eContents().toArray();
+	}
+
+	@Override
+	public Object getProperty(Object element, String id) {
+		EObject eObj = (EObject) element;
+		if (eObj == null)
+			return null;
+
+		EStructuralFeature eFeature = eObj.eClass().getEStructuralFeature(id);
+		if (eFeature == null)
+			return null;
+
+		return eObj.eGet(eFeature);
+	}
+
+	@Override
+	public String[] getPropIds(Object element) {
+		if (element == null)
+			return new String[0];
+
+		EObject eObj = (EObject) element;
+		EList<EStructuralFeature> features = eObj.eClass().getEAllStructuralFeatures();
+		String[] ids = new String[features.size()];
+		int count = 0;
+		for (Iterator<?> iterator = features.iterator(); iterator.hasNext();) {
+			EStructuralFeature structuralFeature = (EStructuralFeature) iterator.next();
+			String featureName = structuralFeature.getName();
+			ids[count++] = featureName;
+		}
+
+		return ids;
+	}
+
+	@Override
+	public void setProperty(Object element, String id, Object value) {
+		EObject eObj = (EObject) element;
+		if (eObj == null)
+			return;
+
+		EStructuralFeature eFeature = eObj.eClass().getEStructuralFeature(id);
+		if (eFeature == null)
+			return;
+
+		eObj.eSet(eFeature, value);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPartService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPartService.java
new file mode 100644
index 0000000..1f24904
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPartService.java
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     Simon Scholz <simon.scholz@vogella.com> - Bug 450411
+ ******************************************************************************/
+package org.eclipse.e4.ui.workbench.modeling;
+
+import java.util.Collection;
+import org.eclipse.core.runtime.AssertionFailedException;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+
+/**
+ * The part service provides clients with the functionalities of showing and hiding parts. Part
+ * events can also be tracked via the part service.
+ * <p>
+ * It is expected that any methods that are exposed by this service that takes an <code>MPart</code>
+ * as an argument be a part that is actually being managed by this service.
+ * </p>
+ *
+ * @since 1.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface EPartService {
+
+	/**
+	 * Used to tag the currently active part in a presentation for subsequent activation on session
+	 * startup
+	 */
+	public static final String ACTIVE_ON_CLOSE_TAG = "activeOnClose"; //$NON-NLS-1$
+
+	/**
+	 * Applicable states that a part can be in. This will be used in conjunction with
+	 * {@link EPartService#showPart(String, PartState)}.
+	 */
+	public enum PartState {
+
+		/**
+		 * Part state that indicates the part should be made visible and activated.
+		 */
+		ACTIVATE,
+
+		/**
+		 * Part state that indicates the part should be made visible though it may not necessarily
+		 * be granted focus. If the part will be displayed in the same stack as the currently active
+		 * part, then this has the same effect as <code>ACTIVATE</code>.
+		 */
+		VISIBLE,
+
+		/**
+		 * Part state that indicates the part should be created but not necessarily made visible.
+		 */
+		CREATE
+	}
+
+	/**
+	 * A tag on a part to indicate that it should be removed from the model when it is hidden.
+	 *
+	 * @see #hidePart(MPart)
+	 */
+	public static final String REMOVE_ON_HIDE_TAG = "removeOnHide"; //$NON-NLS-1$
+
+	/**
+	 * Adds the given listener for part lifecycle events. Has no effect if an identical listener has
+	 * already been registered.
+	 * <p>
+	 * <b>Note:</b> Listeners should be removed when no longer necessary.
+	 * </p>
+	 *
+	 * @param listener
+	 *            the listener to attach
+	 */
+	public void addPartListener(IPartListener listener);
+
+	/**
+	 * Removes the given listener so that it will no longer be notified of part lifecycle events.
+	 * Has no effect if an identical listener has not been registered.
+	 *
+	 * @param listener
+	 *            the listener to remove
+	 */
+	public void removePartListener(IPartListener listener);
+
+	/**
+	 * Activates the given part. The part will be brought to top (if necessary) and granted focus.
+	 *
+	 * @param part
+	 *            the part to activate, must not be <code>null</code>
+	 */
+	public void activate(MPart part);
+
+	/**
+	 * Activates the given part. The part will be brought to top (if necessary) and, if
+	 * {@code requiresFocus} is true, then granted focus.
+	 *
+	 * @param part
+	 *            the part to activate, must not be <code>null</code>
+	 * @param requiresFocus
+	 *            if true, then also cause the part to acquire focus
+	 */
+	public void activate(MPart part, boolean requiresFocus);
+
+	/**
+	 * Ask the service to assign activation to a valid part in the currently active presentation.
+	 */
+	public void requestActivation();
+
+	/**
+	 * Brings this part to the top so that it will become visible to the end user. This does not
+	 * imply that the part will be granted focus.
+	 *
+	 * @param part
+	 *            the part to bring to top
+	 */
+	public void bringToTop(MPart part);
+
+	/**
+	 * Finds and returns a part with the given id.
+	 *
+	 * @param id
+	 *            the id of the part to search for, must not be <code>null</code>
+	 * @return the part with the specified id, or <code>null</code> if no such part could be found
+	 */
+	public MPart findPart(String id);
+
+	/**
+	 * Returns a collection of all the parts that are being managed by this part service.
+	 *
+	 * @return a collection of parts that are being managed by this service, never <code>null</code>
+	 */
+	public Collection<MPart> getParts();
+
+	/**
+	 * Returns the active part.
+	 *
+	 * @return an active part within the scope of this service, or <code>null</code> if no part is
+	 *         currently active
+	 */
+	public MPart getActivePart();
+
+	/**
+	 * Returns whether the specified part is currently visible to the end user.
+	 *
+	 * @param part
+	 *            the part to check
+	 * @return <code>true</code> if the part is currently visible, <code>false</code> otherwise
+	 */
+	public boolean isPartVisible(MPart part);
+
+	/**
+	 * Creates a new part of the given id.
+	 *
+	 * @param id
+	 *            the identifier of the part, must not be <code>null</code>
+	 * @return a new part of the given id, or <code>null</code> if no part descriptors can be found
+	 *         that match the specified id
+	 */
+	public MPart createPart(String id);
+
+	/**
+	 * Creates a new placeholder for a part of the given id.
+	 *
+	 * @param id
+	 *            the identifier of the part, must not be <code>null</code>
+	 * @return a new part of the given id, or <code>null</code> if no part descriptors can be found
+	 *         that match the specified id
+	 */
+	public MPlaceholder createSharedPart(String id);
+
+	/**
+	 * Creates a new placeholder for a part of the given id.
+	 *
+	 * @param id
+	 *            the identifier of the part, must not be <code>null</code>
+	 * @param force
+	 *            <code>true</code> if a new part should be created, <code>false</code> if the
+	 *            window should be queried for a shared part first
+	 * @return a new part of the given id, or <code>null</code> if no part descriptors can be found
+	 *         that match the specified id
+	 */
+	public MPlaceholder createSharedPart(String id, boolean force);
+
+	/**
+	 * Shows a part with the identified by the given id. In the event that there are multiple parts
+	 * with the specified id, the client is recommended to use {@link #getParts()} and iterate over
+	 * the collection to find the interested part and invoke {@link #showPart(MPart, PartState)} on
+	 * it. The behavior of this method is dictated by the supplied state.
+	 * <ul>
+	 * <li>If <code>ACTIVATE</code> is supplied, then the part is made visible and granted focus.
+	 * </li>
+	 * <li>If <code>VISIBLE</code> is supplied, then the part will be made visible and possibly be
+	 * granted focus depending on where it is relative to the active part. If it is in the same
+	 * stack as the currently active part, then it will be granted focus.</li>
+	 * <li>If <code>CREATE</code> is supplied, then the part will be instantiated though its
+	 * contents may not necessarily be visible to the end user. visible to the end user.</li>
+	 * </ul>
+	 * </p>
+	 *
+	 * @param id
+	 *            the identifier of the part, must not be <code>null</code>
+	 * @param partState
+	 *            the desired state of the shown part to be in
+	 * @return the shown part, or <code>null</code> if no parts or part descriptors can be found
+	 *         that match the specified id
+	 */
+	public MPart showPart(String id, PartState partState);
+
+	/**
+	 * Shows the given part.
+	 * <p>
+	 * <ul>
+	 * <li>If there cannot be multiple parts of this type and a part already exists, the already
+	 * existing part will be shown and returned.</li>
+	 * <li>If multiple parts of this type is allowed, then the provided part will be shown and
+	 * returned</li>
+	 * </ul>
+	 * </p>
+	 * <p>
+	 * The behavior of this method is dictated by the supplied state.
+	 * <ul>
+	 * <li>If <code>ACTIVATE</code> is supplied, then the part is made visible and granted focus.
+	 * </li>
+	 * <li>If <code>VISIBLE</code> is supplied, then the part will be made visible and possibly be
+	 * granted focus depending on where it is relative to the active part. If it is in the same
+	 * stack as the currently active part, then it will be granted focus.</li>
+	 * <li>If <code>CREATE</code> is supplied, then the part will be instantiated though its
+	 * contents may not necessarily be visible to the end user. visible to the end user.</li>
+	 * </ul>
+	 * </p>
+	 *
+	 * @param part
+	 *            the part to show
+	 * @param partState
+	 *            the desired state of the shown part to be in
+	 * @return the shown part
+	 */
+	public MPart showPart(MPart part, PartState partState);
+
+	/**
+	 * Hides the given part. The part must be a part managed by this service.
+	 * <p>
+	 * If the part has been tagged with the {@link #REMOVE_ON_HIDE_TAG} tag, it will be removed from
+	 * the model when the service hides it.
+	 * </p>
+	 * <p>
+	 * To save the part before hiding, use {@link #savePart(MPart, boolean)}:
+	 * </p>
+	 *
+	 * <pre>
+	 * if (partService.savePart(part, true)) {
+	 * 	partService.hidePart(part);
+	 * }
+	 * </pre>
+	 *
+	 * @param part
+	 *            the part to hide
+	 * @see #savePart(MPart, boolean)
+	 */
+	public void hidePart(MPart part);
+
+	/**
+	 * Hides the given part. The part must be a part managed by this service.
+	 * <p>
+	 * If <code>force</code> is <code>true</code> or the part has been tagged with the
+	 * {@link #REMOVE_ON_HIDE_TAG} tag, it will be removed from the model when the service hides it.
+	 * </p>
+	 * <p>
+	 * To save the part before hiding, use {@link #savePart(MPart, boolean)}:
+	 * </p>
+	 *
+	 * <pre>
+	 * if (partService.savePart(part, true)) {
+	 * 	partService.hidePart(part);
+	 * }
+	 * </pre>
+	 *
+	 * @param part
+	 *            the part to hide
+	 * @param force
+	 *            if the part should be removed from the model regardless of its
+	 *            {@link #REMOVE_ON_HIDE_TAG} tag
+	 * @see #savePart(MPart, boolean)
+	 */
+	public void hidePart(MPart part, boolean force);
+
+	/**
+	 * Returns a collection of all the dirty parts that are being managed by this service.
+	 *
+	 *
+	 * @return a collection of dirty parts that are being managed by this service, never
+	 *         <code>null</code>
+	 */
+	public Collection<MPart> getDirtyParts();
+
+	/**
+	 * Saves the contents of the part if it is dirty and returns whether the operation completed.
+	 *
+	 * @param part
+	 *            the part to save
+	 * @param confirm
+	 *            <code>true</code> if the user should be prompted prior to saving the changes, and
+	 *            <code>false</code> to save changes without asking
+	 * @return <code>true</code> if the operation completed successfully, <code>false</code> if the
+	 *         user canceled the operation or if an error occurred while saving the changes
+	 * @see #hidePart(MPart, boolean)
+	 */
+	public boolean savePart(MPart part, boolean confirm);
+
+	/**
+	 * Saves the contents of all dirty parts and returns whether the operation completed.
+	 *
+	 * @param confirm
+	 *            <code>true</code> if the user should be prompted prior to saving the changes, and
+	 *            <code>false</code> to save changes without asking
+	 * @return <code>true</code> if the operation completed successfully, <code>false</code> if the
+	 *         user canceled the operation or if an error occurred while saving the changes
+	 */
+	public boolean saveAll(boolean confirm);
+
+	/**
+	 * Returns a collection of all {@link MInputPart} with the inputURI-Attribute set to the given
+	 * value
+	 *
+	 * @param inputUri
+	 *            the input uri to search for, must not be <code>null</code>
+	 * @return list of parts or an empty collection
+	 * @throws AssertionFailedException
+	 *             if null passed as argument
+	 */
+	public Collection<MInputPart> getInputParts(String inputUri);
+
+	/**
+	 * Switch to the specified perspective. It will be selected and brought to top (if necessary).
+	 * It may not necessarily be granted focus if there is another active window present.
+	 *
+	 * @param perspective
+	 *            the perspective to switch to, must not be <code>null</code> and it must be a
+	 *            perspective that's being managed by this service
+	 * @noreference This method is not intended to be referenced by clients.
+	 */
+	public void switchPerspective(MPerspective perspective);
+
+	/**
+	 * Indicates whether a part with a certain elementId is currently rendered in a certain
+	 * perspective or not.
+	 *
+	 * @param elementId
+	 *            the id of the part, which should be checked
+	 * @param perspective
+	 *            the perspective, which may contain the part with the given elementId
+	 * @return <code>true</code> if the part with the given elementId is rendered in the given
+	 *         perspective and <code>false</code> otherwise
+	 * @since 1.3
+	 */
+	public boolean isPartOrPlaceholderInPerspective(String elementId, MPerspective perspective);
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPlaceholderResolver.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPlaceholderResolver.java
new file mode 100644
index 0000000..de4b5ab
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EPlaceholderResolver.java
@@ -0,0 +1,43 @@
+/*******************************************************************************

+ * Copyright (c) 2011, 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.workbench.modeling;

+

+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;

+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;

+

+/**

+ * This service is used to resolve references from MPlaceholders.

+ *

+ * The issue is that we may be storing a cloned snippet which contains references to 'shared

+ * elements' but instantiating the snippet in a new window requires that the shared elements list be

+ * updated.

+ *

+ * @noreference This interface is not intended to be referenced by clients.

+ * @since 1.0

+ */

+public interface EPlaceholderResolver {

+	/**

+	 * This method is used to re-resolve a placeholder's reference to a 'shared part' within the

+	 * context of a particular window. This is necessary because placeholders must be referencing an

+	 * element in that window's 'sharedParts' list.

+	 * <p>

+	 * Implementors may presume that the if the placeholder's reference is already non-null then it

+	 * has already been resolved.

+	 * </p>

+	 *

+	 * @param ph

+	 *            The placeholder to set the reference for (if necessary)

+	 * @param refWin

+	 *            The window the whose shared parts are to be referenced

+	 */

+	public void resolvePlaceholderRef(MPlaceholder ph, MWindow refWin);

+}

diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java
new file mode 100644
index 0000000..67a231a
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ESelectionService.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+import org.eclipse.e4.ui.services.IServiceConstants;
+
+/**
+ * This interface describes the workbench selection service
+ *
+ * @since 1.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ESelectionService {
+
+	/**
+	 * Due to the possibly misleading nature of this field's name, it has been replaced with
+	 * {@link IServiceConstants#ACTIVE_SELECTION}. All clients of this API should change their
+	 * references to <code>IServiceConstants.ACTIVE_SELECTION</code>.
+	 */
+	@Deprecated
+	public static final String SELECTION = IServiceConstants.ACTIVE_SELECTION; // "in.selection";
+
+	/**
+	 * Sets the given selection in the active context
+	 *
+	 * @param selection
+	 *            the new selection
+	 */
+	public void setSelection(Object selection);
+
+	/**
+	 * Sets the given selection as the post selection for the active context
+	 *
+	 * @param selection
+	 *            the new selection
+	 */
+	public void setPostSelection(Object selection);
+
+	/**
+	 * Returns the current selection from the active context or <code>null</code> if the is nothing
+	 * selected.
+	 *
+	 * @return the current selection or <code>null</code>
+	 */
+	public Object getSelection();
+
+	/**
+	 * Returns the current selection from the the part with the given id. Returns <code>null</code>
+	 * if there is no selection or the part does not exist.
+	 *
+	 * @param partId
+	 *            the id of the part to get the selection from
+	 * @return the current selection in the part or <code>null</code>
+	 */
+	public Object getSelection(String partId);
+
+	/**
+	 * Adds the given {@link ISelectionListener} to the service
+	 *
+	 * @param listener
+	 *            the listener to register
+	 */
+	public void addSelectionListener(ISelectionListener listener);
+
+	/**
+	 * Removes the given {@link ISelectionListener} from the service
+	 *
+	 * @param listener
+	 *            the listener to unregister
+	 */
+	public void removeSelectionListener(ISelectionListener listener);
+
+	/**
+	 * Adds the {@link ISelectionListener} to the service for the part with the given id.
+	 *
+	 * @param partId
+	 *            the id of the part to add the listener for
+	 * @param listener
+	 *            the listener to register
+	 */
+	public void addSelectionListener(String partId, ISelectionListener listener);
+
+	/**
+	 * Removes the {@link ISelectionListener} from the service for the given part id.
+	 *
+	 * @param partId
+	 *            the id of the part to remove the listener for
+	 * @param listener
+	 *            the listener to unregister
+	 */
+	public void removeSelectionListener(String partId, ISelectionListener listener);
+
+	/**
+	 * Adds the {@link ISelectionListener} as a post selection listener for the service.
+	 *
+	 * @param listener
+	 *            the listener to register
+	 */
+	public void addPostSelectionListener(ISelectionListener listener);
+
+	/**
+	 * Removes the {@link ISelectionListener} as a post selection listener for the service.
+	 *
+	 * @param listener
+	 *            the listener to unregister
+	 */
+	public void removePostSelectionListener(ISelectionListener listener);
+
+	/**
+	 * Adds the {@link ISelectionListener} as a post selection listener for the part with the given
+	 * id.
+	 *
+	 * @param partId
+	 *            the id of the part to add the listener for
+	 * @param listener
+	 *            the listener to register
+	 */
+	public void addPostSelectionListener(String partId, ISelectionListener listener);
+
+	/**
+	 * Removes the {@link ISelectionListener} as a post selection listener for the part with the
+	 * given id.
+	 *
+	 * @param partId
+	 *            the id of the part to remove the listener for
+	 * @param listener
+	 *            the listener to unregister
+	 */
+	public void removePostSelectionListener(String partId, ISelectionListener listener);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ElementMatcher.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ElementMatcher.java
new file mode 100644
index 0000000..56558f5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ElementMatcher.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 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.workbench.modeling;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+import org.eclipse.e4.ui.workbench.Selector;
+
+/**
+ * This is an implementation of a Selector that implements the existing 'findElements'. Clients may
+ * subclass this and override the 'select' method in order to define custom filters.
+ *
+ * @since 1.1
+ *
+ */
+public class ElementMatcher implements Selector {
+	private String id = null;
+	private Class<?> clazz = null;
+	private List<String> tagsToMatch = null;
+
+	/**
+	 * @param id
+	 *            The elementId of the desired element
+	 * @param clazz
+	 *            The class specification of the desired element
+	 * @param tag
+	 *            A tag which must be specified on the desired element
+	 *
+	 */
+	public ElementMatcher(String id, Class<?> clazz, String tag) {
+		this.id = id;
+		this.clazz = clazz;
+
+		if (tag != null) {
+			tagsToMatch = new ArrayList<String>();
+			tagsToMatch.add(tag);
+		}
+	}
+
+	/**
+	 * @param id
+	 *            The elementId of the desired element
+	 * @param clazz
+	 *            The class specification of the desired element
+	 * @param tagsToMatch
+	 *            A list of tags which must <b>all</b> be specified on the desired element
+	 *
+	 */
+	public ElementMatcher(String id, Class<?> clazz, List<String> tagsToMatch) {
+		this.id = id;
+		this.clazz = clazz;
+		this.tagsToMatch = tagsToMatch;
+	}
+
+	@Override
+	public boolean select(MApplicationElement element) {
+		if (id != null && !id.equals(element.getElementId())) {
+			return false;
+		}
+
+		if (clazz != null && !(clazz.isInstance(element))) {
+			return false;
+		}
+
+		if (tagsToMatch != null) {
+			List<String> elementTags = element.getTags();
+			for (String tag : tagsToMatch) {
+				if (!elementTags.contains(tag)) {
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IDelta.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IDelta.java
new file mode 100644
index 0000000..2c39c78
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IDelta.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface IDelta {
+
+	public Object getObject();
+
+	public IStatus apply();
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IModelReconcilingService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IModelReconcilingService.java
new file mode 100644
index 0000000..c19d177
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IModelReconcilingService.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+import java.util.Collection;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface IModelReconcilingService {
+
+	/**
+	 * Creates a model reconciler that is capable of tracking delta changes of a model and applying
+	 * said changes to a model.
+	 *
+	 * @return a reconciler for tracking and applying model changes
+	 */
+	public ModelReconciler createModelReconciler();
+
+	/**
+	 * Applies all of the deltas to the model and returns a status representing the result of the
+	 * merging operation.
+	 * <p>
+	 * This is a convenience method, fully equivalent to <code>applyDeltas(deltas, null)</code>.
+	 * </p>
+	 *
+	 * @param deltas
+	 *            the deltas to apply to the model
+	 * @return the resulting outcome of the merge
+	 */
+	public IStatus applyDeltas(Collection<ModelDelta> deltas);
+
+	/**
+	 * Applies all of the deltas to the model and returns a status representing the result of the
+	 * merging operation.
+	 *
+	 * @param deltas
+	 *            the deltas to apply to the model
+	 * @param filters
+	 *            a list of filters for preventing the application of a certain delta, valid
+	 *            candidates are listed in {@link ModelReconciler}
+	 * @return the resulting outcome of the merge
+	 */
+	public IStatus applyDeltas(Collection<ModelDelta> deltas, String[] filters);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IPartListener.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IPartListener.java
new file mode 100644
index 0000000..6c286cd
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IPartListener.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.modeling;
+
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+
+/**
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface IPartListener {
+
+	public void partActivated(MPart part);
+
+	public void partBroughtToTop(MPart part);
+
+	public void partDeactivated(MPart part);
+
+	public void partHidden(MPart part);
+
+	public void partVisible(MPart part);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java
new file mode 100644
index 0000000..e08f712
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.modeling;
+
+import java.util.Collection;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+
+/**
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface ISaveHandler {
+
+	public enum Save {
+		YES, NO, CANCEL
+	}
+
+	public boolean save(MPart dirtyPart, boolean confirm);
+
+	public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm);
+
+	public Save promptToSave(MPart dirtyPart);
+
+	public Save[] promptToSave(Collection<MPart> dirtyParts);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISelectionListener.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISelectionListener.java
new file mode 100644
index 0000000..200d002
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISelectionListener.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.modeling;
+
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+
+/**
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface ISelectionListener {
+
+	public void selectionChanged(MPart part, Object selection);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IWindowCloseHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IWindowCloseHandler.java
new file mode 100644
index 0000000..a997e2c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/IWindowCloseHandler.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.workbench.modeling;
+
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+
+/**
+ * A handler that can be inserted into the context of the application or a particular window to
+ * determine whether the window should be closed or not.
+ *
+ * @noreference This interface is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public interface IWindowCloseHandler {
+
+	public boolean close(MWindow window);
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelDelta.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelDelta.java
new file mode 100644
index 0000000..f6ee11b
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelDelta.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * @noreference This class is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public abstract class ModelDelta implements IDelta {
+
+	private final Object object;
+	private final String attributeName;
+	private final Object attributeValue;
+
+	public ModelDelta(Object object, String attributeName, Object attributeValue) {
+		Assert.isNotNull(object);
+		Assert.isNotNull(attributeName);
+
+		this.object = object;
+		this.attributeName = attributeName;
+		this.attributeValue = attributeValue;
+	}
+
+	@Override
+	public Object getObject() {
+		return object;
+	}
+
+	public String getAttributeName() {
+		return attributeName;
+	}
+
+	protected Object convert(Object value) {
+		if (value instanceof IDelta) {
+			IDelta delta = (IDelta) value;
+			delta.apply();
+			return delta.getObject();
+		} else if (value instanceof List<?>) {
+			List<?> values = (List<?>) value;
+			List<Object> objects = new ArrayList<Object>(values.size());
+			for (int i = 0; i < values.size(); i++) {
+				Object object = values.get(i);
+				if (object instanceof IDelta) {
+					IDelta delta = (IDelta) object;
+					delta.apply();
+					object = delta.getObject();
+				}
+				objects.add(object);
+			}
+
+			return objects;
+		}
+
+		return value;
+	}
+
+	public Object getAttributeValue() {
+		return convert(attributeValue);
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelHandlerBase.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelHandlerBase.java
new file mode 100644
index 0000000..5bad29e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelHandlerBase.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+/**
+ * @noreference This class is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public class ModelHandlerBase {
+	protected ModelHandlerBase() {
+	}
+
+	public Object getProperty(Object element, String id) {
+		return null;
+	}
+
+	public void setProperty(Object element, String id, Object value) {
+	}
+
+	public Object[] getChildren(Object element, String id) {
+		return new Object[0];
+	}
+
+	public String[] getPropIds(Object element) {
+		return new String[0];
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelReconciler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelReconciler.java
new file mode 100644
index 0000000..5c32c6f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ModelReconciler.java
@@ -0,0 +1,462 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.workbench.modeling;
+
+import java.util.Collection;
+import org.eclipse.e4.ui.model.application.commands.impl.CommandsPackageImpl;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+
+/**
+ * @noreference This class is not intended to be referenced by clients.
+ * @since 1.0
+ */
+public abstract class ModelReconciler {
+
+	/**
+	 * Attribute defined by MApplicationElements (value is <code>elementId</code>).
+	 */
+	public static final String APPLICATIONELEMENT_ELEMENTID_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getApplicationElement_ElementId().getName();
+
+	/**
+	 * Attribute defined by MApplicationElements (value is <code>tags</code>).
+	 */
+	public static final String APPLICATIONELEMENT_TAGS_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getApplicationElement_Tags().getName();
+
+	/**
+	 * Attribute defined by MApplicationElements (value is <code>clonableSnippets</code>).
+	 */
+	public static final String SNIPPETCONTAINER_SNIPPETS_ATTNAME = UiPackageImpl.eINSTANCE
+			.getSnippetContainer_Snippets().getName();
+
+	/**
+	 * Attribute defined by MApplications (value is <code>commands</code>).
+	 */
+	public static final String APPLICATION_COMMANDS_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getApplication_Commands().getName();
+
+	/**
+	 * Attribute defined by MApplications (value is <code>addons</code>).
+	 */
+	public static final String APPLICATION_ADDONS_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getApplication_Addons().getName();
+
+	/**
+	 * Attribute defined by MContexts (value is <code>properties</code>).
+	 */
+	public static final String CONTEXT_PROPERTIES_ATTNAME = UiPackageImpl.eINSTANCE
+			.getContext_Properties().getName();
+
+	/**
+	 * Attribute defined by MApplicationElements (value is <code>persistedState</code>).
+	 */
+	public static final String APPLICATIONELEMENT_PERSISTEDSTATE_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getApplicationElement_PersistedState().getName();
+
+	/**
+	 * Attribute defined by MContributions (value is <code>contributionURI</code>).
+	 */
+	public static final String CONTRIBUTION_URI_ATTNAME = ApplicationPackageImpl.eINSTANCE
+			.getContribution_ContributionURI().getName();
+
+	/**
+	 * Attribute defined by MHandlerContainers (value is <code>handlers</code>).
+	 */
+	public static final String HANDLERCONTAINER_HANDLERS_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getHandlerContainer_Handlers().getName();
+
+	/**
+	 * Attribute defined by MUILabels (value is <code>label</code>).
+	 */
+	public static final String UILABEL_LABEL_ATTNAME = UiPackageImpl.eINSTANCE.getUILabel_Label()
+			.getName();
+
+	/**
+	 * Attribute defined by MUILabels (value is <code>tooltip</code>).
+	 */
+	public static final String UILABEL_TOOLTIP_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUILabel_Tooltip().getName();
+
+	/**
+	 * Attribute defined by MUILabels (value is <code>iconURI</code>).
+	 */
+	public static final String UILABEL_ICONURI_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUILabel_IconURI().getName();
+
+	/**
+	 * Attribute defined by MUIElements (value is <code>toBeRendered</code>).
+	 */
+	public static final String UIELEMENT_TOBERENDERED_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUIElement_ToBeRendered().getName();
+
+	/**
+	 * Attribute defined by MUIElements (value is <code>visible</code>).
+	 */
+	public static final String UIELEMENT_VISIBLE_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUIElement_Visible().getName();
+
+	/**
+	 * Attribute defined by MUIElements (value is <code>parent</code>).
+	 */
+	public static final String UIELEMENT_PARENT_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUIElement_Parent().getName();
+
+	/**
+	 * Attribute defined by MUIElements (value is <code>containerData</code>).
+	 */
+	public static final String UIELEMENT_CONTAINERDATA_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUIElement_ContainerData().getName();
+
+	/**
+	 * Attribute defined by MUIElements (value is <code>visibleWhen</code>).
+	 */
+	public static final String UIELEMENT_VISIBLEWHEN_ATTNAME = UiPackageImpl.eINSTANCE
+			.getUIElement_VisibleWhen().getName();
+
+	/**
+	 * Attribute defined by MElementContainers (value is <code>children</code>).
+	 */
+	public static final String ELEMENTCONTAINER_CHILDREN_ATTNAME = UiPackageImpl.eINSTANCE
+			.getElementContainer_Children().getName();
+
+	/**
+	 * Attribute defined by MElementContainers (value is <code>selectedElement</code>).
+	 */
+	public static final String ELEMENTCONTAINER_SELECTEDELEMENT_ATTNAME = UiPackageImpl.eINSTANCE
+			.getElementContainer_SelectedElement().getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>x</code>).
+	 */
+	public static final String WINDOW_X_ATTNAME = BasicPackageImpl.eINSTANCE.getWindow_X()
+			.getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>y</code>).
+	 */
+	public static final String WINDOW_Y_ATTNAME = BasicPackageImpl.eINSTANCE.getWindow_Y()
+			.getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>width</code>).
+	 */
+	public static final String WINDOW_WIDTH_ATTNAME = BasicPackageImpl.eINSTANCE.getWindow_Width()
+			.getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>height</code>).
+	 */
+	public static final String WINDOW_HEIGHT_ATTNAME = BasicPackageImpl.eINSTANCE
+			.getWindow_Height().getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>mainMenu</code>).
+	 */
+	public static final String WINDOW_MAINMENU_ATTNAME = BasicPackageImpl.eINSTANCE
+			.getWindow_MainMenu().getName();
+
+	/**
+	 * Attribute defined by MWindows (value is <code>sharedElements</code>).
+	 */
+	public static final String WINDOW_SHAREDELEMENTS_ATTNAME = BasicPackageImpl.eINSTANCE
+			.getWindow_SharedElements().getName();
+
+	/**
+	 * Attribute defined by MTrimmedWindows (value is <code>trimBars</code>).
+	 */
+	public static final String TRIMMEDWINDOW_TRIMBARS_ATTNAME = BasicPackageImpl.eINSTANCE
+			.getTrimmedWindow_TrimBars().getName();
+
+	/**
+	 * Attribute defined by MCommands (value is <code>commandName</code>).
+	 */
+	public static final String COMMAND_COMMANDNAME_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getCommand_CommandName().getName();
+
+	/**
+	 * Attribute defined by MCommands (value is <code>description</code>).
+	 */
+	public static final String COMMAND_DESCRIPTION_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getCommand_Description().getName();
+
+	/**
+	 * Attribute defined by MCommands (value is <code>parameters</code>).
+	 */
+	public static final String COMMAND_PARAMETERS_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getCommand_Parameters().getName();
+
+	/**
+	 * Attribute defined by MKeySequences (value is <code>keySequence</code>).
+	 */
+	public static final String KEYSEQUENCE_KEYSEQUENCE_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getKeySequence_KeySequence().getName();
+
+	/**
+	 * Attribute defined by MParts (value is <code>closeable</code>).
+	 */
+	public static final String PART_CLOSEABLE_ATTNAME = BasicPackageImpl.eINSTANCE
+			.getPart_Closeable().getName();
+
+	/**
+	 * Attribute defined by MParts (value is <code>menus</code>).
+	 */
+	public static final String PART_MENUS_ATTNAME = BasicPackageImpl.eINSTANCE.getPart_Menus()
+			.getName();
+
+	/**
+	 * Attribute defined by MParts (value is <code>toolbar</code>).
+	 */
+	public static final String PART_TOOLBAR_ATTNAME = BasicPackageImpl.eINSTANCE.getPart_Toolbar()
+			.getName();
+
+	/**
+	 * Attribute defined by MInputs (value is <code>inputURI</code>).
+	 */
+	public static final String INPUT_INPUTURI_ATTNAME = UiPackageImpl.eINSTANCE.getInput_InputURI()
+			.getName();
+
+	/**
+	 * Attribute defined by MGenericTiles (value is <code>horizontal</code>).
+	 */
+	public static final String GENERICTILE_HORIZONTAL_ATTNAME = UiPackageImpl.eINSTANCE
+			.getGenericTile_Horizontal().getName();
+
+	/**
+	 * Attribute defined by MGenericTrimContainers (value is <code>side</code>).
+	 */
+	public static final String GENERICTRIMCONTAINER_SIDE_ATTNAME = UiPackageImpl.eINSTANCE
+			.getGenericTrimContainer_Side().getName();
+
+	/**
+	 * Attribute defined by MBindingContainers (value is <code>rootContext</code>).
+	 */
+	public static final String BINDINGCONTAINER_ROOTCONTEXT_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getBindingTableContainer_RootContext().getName();
+
+	/**
+	 * Attribute defined by MBindingContainers (value is <code>bindingTables</code>).
+	 */
+	public static final String BINDINGCONTAINER_BINDINGTABLES_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getBindingTableContainer_BindingTables().getName();
+
+	/**
+	 * Attribute defined by MBindingTables (value is <code>bindings</code>).
+	 */
+	public static final String BINDINGTABLE_BINDINGS_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getBindingTable_Bindings().getName();
+
+	/**
+	 * Attribute defined by MBindingTables (value is <code>bindingContext</code>).
+	 */
+	public static final String BINDINGTABLE_BINDINGCONTEXT_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getBindingTable_BindingContext().getName();
+
+	/**
+	 * Attribute defined by MBindings (value is <code>bindingContexts</code>).
+	 */
+	public static final String BINDINGS_BINDINGCONTEXTS_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getBindings_BindingContexts().getName();
+
+	/**
+	 * Attribute defined by MHandlers (value is <code>command</code>).
+	 */
+	public static final String HANDLER_COMMAND_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getHandler_Command().getName();
+
+	/**
+	 * Attribute defined by MHandledItems (value is <code>command</code>).
+	 */
+	public static final String HANDLEDITEM_COMMAND_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getHandledItem_Command().getName();
+
+	/**
+	 * Attribute defined by MHandledItems (value is <code>parameters</code>).
+	 */
+	public static final String HANDLEDITEM_PARAMETERS_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getHandledItem_Parameters().getName();
+
+	/**
+	 * Attribute defined by MKeyBindings (value is <code>command</code>).
+	 */
+	public static final String KEYBINDING_COMMAND_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getKeyBinding_Command().getName();
+
+	/**
+	 * Attribute defined by MItems (value is <code>enabled</code>).
+	 */
+	public static final String ITEM_ENABLED_ATTNAME = MenuPackageImpl.eINSTANCE.getItem_Enabled()
+			.getName();
+
+	/**
+	 * Attribute defined by MItems (value is <code>selected</code>).
+	 */
+	public static final String ITEM_SELECTED_ATTNAME = MenuPackageImpl.eINSTANCE.getItem_Selected()
+			.getName();
+
+	/**
+	 * Attribute defined by MItems (value is <code>type</code>).
+	 */
+	public static final String ITEM_TYPE_ATTNAME = MenuPackageImpl.eINSTANCE.getItem_Type()
+			.getName();
+
+	/**
+	 * Attribute defined by MMenuItems (value is <code>mnemonics</code>).
+	 */
+	public static final String MENUITEM_MNEMONICS_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getMenuElement_Mnemonics().getName();
+
+	/**
+	 * Attribute defined by MTrimContribution (value is <code>parentId</code>).
+	 */
+	public static final String TRIMCONTRIBUTION_PARENTID_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getTrimContribution_ParentId().getName();
+
+	/**
+	 * Attribute defined by MTrimContribution (value is <code>positionInParent</code>).
+	 */
+	public static final String TRIMCONTRIBUTION_POSITIONINPARENT_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getTrimContribution_PositionInParent().getName();
+
+	/**
+	 * Attribute defined by MTrimContributions (value is <code>trimContributions</code>).
+	 */
+	public static final String TRIMCONTRIBUTIONS_TRIMCONTRIBUTIONS_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getTrimContributions_TrimContributions().getName();
+
+	/**
+	 * Attribute defined by MToolBarContribution (value is <code>parentId</code>).
+	 */
+	public static final String TOOLBARCONTRIBUTION_PARENTID_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getToolBarContribution_ParentId().getName();
+
+	/**
+	 * Attribute defined by MToolBarContribution (value is <code>positionInParent</code>).
+	 */
+	public static final String TOOLBARCONTRIBUTION_POSITIONINPARENT_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getToolBarContribution_PositionInParent().getName();
+
+	/**
+	 * Attribute defined by MToolBarContributions (value is <code>toolBarContributions</code>).
+	 */
+	public static final String TOOLBARCONTRIBUTIONS_TOOLBARCONTRIBUTIONS_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getToolBarContributions_ToolBarContributions().getName();
+
+	/**
+	 * Attribute defined by MMenuContributions (value is <code>menuContributions</code>).
+	 */
+	public static final String MENUCONTRIBUTIONS_MENUCONTRIBUTIONS_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getMenuContributions_MenuContributions().getName();
+
+	/**
+	 * Attribute defined by MMenuContribution (value is <code>positionInParent</code>).
+	 */
+	public static final String MENUCONTRIBUTION_POSITIONINPARENT_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getMenuContribution_PositionInParent().getName();
+
+	/**
+	 * Attribute defined by MMenuContribution (value is <code>parentID</code>).
+	 */
+	public static final String MENUCONTRIBUTION_PARENTID_ATTNAME = MenuPackageImpl.eINSTANCE
+			.getMenuContribution_ParentId().getName();
+
+	/**
+	 * Attribute defined by MPartDescriptor (value is <code>allowMultiple</code>).
+	 */
+	public static final String PARTDESCRIPTOR_ALLOWMULTIPLE_ATTNAME = org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eINSTANCE
+			.getPartDescriptor_AllowMultiple().getName();
+
+	/**
+	 * Attribute defined by MPartDescriptor (value is <code>category</code>).
+	 */
+	public static final String PARTDESCRIPTOR_CATEGORY_ATTNAME = org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eINSTANCE
+			.getPartDescriptor_Category().getName();
+
+	/**
+	 * Attribute defined by MPartDescriptorContainers (value is <code>descriptors</code>).
+	 */
+	public static final String PARTDESCRIPTORCONTAINER_DESCRIPTORS_ATTNAME = org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eINSTANCE
+			.getPartDescriptorContainer_Descriptors().getName();
+
+	/**
+	 * Attribute defined by MPartDescriptor (value is <code>menus</code>).
+	 */
+	public static final String PARTDESCRIPTOR_MENUS_ATTNAME = org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.eINSTANCE
+			.getPartDescriptor_Menus().getName();
+
+	/**
+	 * Attribute defined by MPlaceholders (value is <code>ref</code>).
+	 */
+	public static final String PLACEHOLDER_REF_NAME = AdvancedPackageImpl.eINSTANCE
+			.getPlaceholder_Ref().getName();
+
+	/**
+	 * Attribute defined by MParameters (value is <code>name</code>).
+	 */
+	public static final String PARAMETER_NAME_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getParameter_Name().getName();
+
+	/**
+	 * Attribute defined by MParameters (value is <code>value</code>).
+	 */
+	public static final String PARAMETER_VALUE_ATTNAME = CommandsPackageImpl.eINSTANCE
+			.getParameter_Value().getName();
+
+	/**
+	 * Attribute defined by MCoreExpressions (value is <code>coreExpressionId</code>).
+	 */
+	public static final String COREEXPRESSION_COREEXPRESSIONID_ATTNAME = UiPackageImpl.eINSTANCE
+			.getCoreExpression_CoreExpressionId().getName();
+
+	/**
+	 * Attribute defined by MPerspective (value is <code>windows</code>).
+	 */
+	public static final String PERSPECTIVE_WINDOWS_ATTNAME = AdvancedPackageImpl.eINSTANCE
+			.getPerspective_Windows().getName();
+
+	/**
+	 * Begin recording changes on the specified object. All changes contained within child elements
+	 * of the object will also be recorded. When the desired changes have been captured,
+	 * {@link #serialize()} should be called.
+	 *
+	 * @param object
+	 *            the object to monitor changes for, must not be <code>null</code>
+	 */
+	public abstract void recordChanges(Object object);
+
+	/**
+	 * Serializes all the changes that have been captured since the last call to
+	 * {@link #recordChanges(Object)} and returns an object that can be used later with
+	 * {@link #constructDeltas(Object, Object)}.
+	 *
+	 * @return a serialization of all the changes that have been made to the model since the last
+	 *         call to <code>recordChanges(Object)</code>
+	 */
+	public abstract Object serialize();
+
+	/**
+	 * Analyzes the model and its serialized state and constructs a collection of deltas between the
+	 * two.
+	 *
+	 * @param model
+	 *            the object to apply changes to
+	 * @param serializedState
+	 *            an object that was returned from {@link #serialize()}
+	 * @return a collection of operations that can be applied to alter the model to the state it was
+	 *         in due to the serialized delta changes
+	 */
+	public abstract Collection<ModelDelta> constructDeltas(Object model, Object serializedState);
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/package.html b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/package.html
new file mode 100644
index 0000000..19d2da8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/package.html
@@ -0,0 +1,18 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <meta name="GENERATOR" content="Mozilla/4.75 [en] (Windows NT 5.0; U) [Netscape]">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+Application programming interfaces describing the Eclipse 4 model services.
+<h2>
+Package Specification</h2>
+<p>
+The package provides interfaces and classes that describe the Eclipse 4 model services. These elements include implementations
+of model, selection and part services as well as descriptions of listeners and deltas.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/package.html b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/package.html
new file mode 100644
index 0000000..cb604e9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/package.html
@@ -0,0 +1,17 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <meta name="GENERATOR" content="Mozilla/4.75 [en] (Windows NT 5.0; U) [Netscape]">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+Application programming interfaces describing Eclipse 4 handlers and the workbench.
+<h2>
+Package Specification</h2>
+<p>
+The package provides interfaces describing Eclipse 4 handlers, the workbench and the event sets for the workbench.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.rap.e4/.classpath b/bundles/org.eclipse.rap.e4/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/.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.rap.e4/.project b/bundles/org.eclipse.rap.e4/.project
new file mode 100644
index 0000000..49371fb
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.rap.e4</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.rap.e4/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.rap.e4/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c537b63
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/.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.rap.e4/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.e4/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..9bff028
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/META-INF/MANIFEST.MF
@@ -0,0 +1,28 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: E4
+Bundle-SymbolicName: org.eclipse.rap.e4
+Bundle-Version: 0.9.0.qualifier
+Require-Bundle: org.eclipse.rap.rwt,
+ org.eclipse.e4.ui.workbench.swt;bundle-version="0.12.100",
+ org.eclipse.e4.ui.workbench,
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.ui.model.workbench,
+ org.eclipse.e4.core.di;bundle-version="1.4.0",
+ org.eclipse.equinox.app,
+ org.eclipse.osgi;bundle-version="3.10.0",
+ org.eclipse.e4.core.services,
+ org.eclipse.osgi.services;bundle-version="3.4.0",
+ org.eclipse.e4.ui.di,
+ org.eclipse.e4.core.di.extensions;bundle-version="0.12.0",
+ org.eclipse.equinox.preferences,
+ org.eclipse.equinox.common;bundle-version="3.6.200"
+Export-Package: org.eclipse.rap.e4,
+ org.eclipse.rap.e4.preferences
+Import-Package: javax.annotation;version="1.2.0",
+ javax.inject;version="1.0.0"
+Service-Component: OSGI-INF/rapeventbroker.xml,OSGI-INF/rapeventobjectsupplier.xml,OSGI-INF/rapuieventobjectsupplier.xml,OSGI-INF/rappreferenceobjectsupplier.xml,
+ OSGI-INF/preferenceserviceCF.xml
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.rap.e4.internal.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/bundles/org.eclipse.rap.e4/OSGI-INF/preferenceserviceCF.xml b/bundles/org.eclipse.rap.e4/OSGI-INF/preferenceserviceCF.xml
new file mode 100644
index 0000000..f682280
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/OSGI-INF/preferenceserviceCF.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.rap.e4.preferenceserviceCF">
+   <implementation class="org.eclipse.rap.e4.preferences.internal.PreferenceServiceContextFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.rap.e4.preferences.EPreferenceService"/>
+   <property name="service.ranking" type="Integer" value="100"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventbroker.xml b/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventbroker.xml
new file mode 100644
index 0000000..e61dba1
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventbroker.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.rap.e4.eventbroker">
+   <implementation class="org.eclipse.rap.e4.internal.RAPEventBrokerContextFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.services.events.IEventBroker"/>
+   <property name="service.ranking" type="Integer" value="100"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventobjectsupplier.xml b/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventobjectsupplier.xml
new file mode 100644
index 0000000..57d2cbe
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/OSGI-INF/rapeventobjectsupplier.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.rap.e4.rapeventobjectsupplier">
+   <implementation class="org.eclipse.rap.e4.internal.RAPEventObjectSupplierDispatcher"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier"/>
+   </service>
+   <property name="dependency.injection.annotation" type="String" value="org.eclipse.e4.core.di.extensions.EventTopic"/>
+   <property name="service.ranking" type="Integer" value="100"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rap.e4/OSGI-INF/rappreferenceobjectsupplier.xml b/bundles/org.eclipse.rap.e4/OSGI-INF/rappreferenceobjectsupplier.xml
new file mode 100644
index 0000000..ec389ca
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/OSGI-INF/rappreferenceobjectsupplier.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.rap.e4.rappreferenceobjectsupplier">
+   <implementation class="org.eclipse.rap.e4.internal.RAPPreferencesObjectSupplierDispatcher"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier"/>
+   </service>
+   <property name="dependency.injection.annotation" type="String" value="org.eclipse.e4.core.di.extensions.Preference"/>
+   <property name="service.ranking" type="Integer" value="100"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rap.e4/OSGI-INF/rapuieventobjectsupplier.xml b/bundles/org.eclipse.rap.e4/OSGI-INF/rapuieventobjectsupplier.xml
new file mode 100644
index 0000000..1757670
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/OSGI-INF/rapuieventobjectsupplier.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.rap.e4.rapuieventobjectsupplier">
+   <implementation class="org.eclipse.rap.e4.internal.RAPUIEventObjectSupplierDispatcher"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier"/>
+   </service>
+   <property name="dependency.injection.annotation" type="String" value="org.eclipse.e4.ui.di.UIEventTopic"/>
+   <property name="service.ranking" type="Integer" value="100"/>
+</scr:component>
diff --git a/bundles/org.eclipse.rap.e4/build.properties b/bundles/org.eclipse.rap.e4/build.properties
new file mode 100644
index 0000000..4df56f6
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/build.properties
@@ -0,0 +1,7 @@
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               OSGI-INF/,\
+               OSGI-INF/rappreferenceobjectsupplier.xml,\
+               OSGI-INF/preferenceserviceCF.xml
+source.. = src/
diff --git a/bundles/org.eclipse.rap.e4/pom.xml b/bundles/org.eclipse.rap.e4/pom.xml
new file mode 100644
index 0000000..61f5ff8
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.rap.e4</artifactId>
+  <version>0.9.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <resources>
+      <!-- to ensure that the feature lookup of the ui test works -->
+      <resource>
+        <directory>.</directory>
+        <includes>
+          <include>META-INF/</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.eclipse.tycho</groupId>
+        <artifactId>tycho-source-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4ApplicationConfig.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4ApplicationConfig.java
new file mode 100644
index 0000000..838c6f7
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4ApplicationConfig.java
@@ -0,0 +1,59 @@
+package org.eclipse.rap.e4;
+
+public class E4ApplicationConfig {
+	private String xmiURI;
+	private boolean persistState;
+	private boolean clearPersistedState;
+	private String lifecycleURI;
+	private String presentationURI;
+	private boolean defaultPush;
+	
+	public E4ApplicationConfig(String xmiURI, String lifecycleURI, String presentationURI, boolean persistState, boolean clearPersistedState, boolean defaultPush) {
+		this.xmiURI = xmiURI;
+		this.lifecycleURI = lifecycleURI;
+		this.presentationURI = presentationURI;
+		this.persistState = persistState;
+		this.clearPersistedState = clearPersistedState;
+		this.defaultPush = defaultPush;
+	}
+	
+	public String getLifecycleURI() {
+		return lifecycleURI;
+	}
+	
+	public boolean isPersistState() {
+		return persistState;
+	}
+	
+	public boolean isClearPersistedState() {
+		return clearPersistedState;
+	}
+	
+	public String getPresentationURI() {
+		return presentationURI;
+	}
+	
+	public String getXmiURI() {
+		return xmiURI;
+	}
+	
+	public boolean isDefaultPush() {
+		return defaultPush;
+	}
+	
+	public static E4ApplicationConfig create(String xmiURI) {
+		return new E4ApplicationConfig(xmiURI, null, null, true, false, true);
+	}
+	
+	public static E4ApplicationConfig create(String xmiURI, String lifecycleURI) {
+		return new E4ApplicationConfig(xmiURI, lifecycleURI, null, true, false, true);
+	}
+	
+	public static E4ApplicationConfig create(String xmiURI, boolean defaultPush) {
+		return new E4ApplicationConfig(xmiURI, null, null, true, false, true);
+	}
+	
+	public static E4ApplicationConfig create(String xmiURI, String lifecycleURI, boolean defaultPush) {
+		return new E4ApplicationConfig(xmiURI, lifecycleURI, null, true, false, true);
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4EntryPointFactory.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4EntryPointFactory.java
new file mode 100644
index 0000000..2e969f0
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/E4EntryPointFactory.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2017 EclipseSource 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:
+ *    Ralf Sternberg - initial API and implementation
+ *    EclipseSource - ongoing development
+ *******************************************************************************/
+package org.eclipse.rap.e4;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.lifecycle.PreSave;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.rap.rwt.application.EntryPoint;
+import org.eclipse.rap.rwt.application.EntryPointFactory;
+import org.eclipse.rap.rwt.service.ServerPushSession;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+@SuppressWarnings("restriction")
+public class E4EntryPointFactory implements EntryPointFactory {
+
+	private static final String PLUGIN_ID = "org.eclipse.e4.ui.workbench.rap";
+
+	private String productName;
+
+	private E4ApplicationConfig config;
+
+	public E4EntryPointFactory(E4ApplicationConfig config) {
+		this.config = config;
+	}
+
+	public EntryPoint create() {
+		return new EntryPoint() {
+
+			public int createUI() {
+				try {
+					// E4Starter.createAndRunApplication(productName);
+					createWorkbench();
+				} catch (Exception exception) {
+					logProblem(exception);
+				}
+				return 0;
+			}
+		};
+	}
+
+	private int createWorkbench() {
+		Display display = new Display();
+		E4Application e4App = new E4Application();
+		E4Workbench workbench = e4App.createE4Workbench(getApplicationContext(config),
+				display);
+
+		if( config.isDefaultPush() ) {
+			ServerPushSession session = new ServerPushSession();
+			session.start();
+		}
+
+//		instanceLocation = (Location) workbench.getContext().get(
+//				E4Workbench.INSTANCE_LOCATION);
+		Shell shell = display.getActiveShell();
+		if (shell == null) {
+			shell = new Shell();
+			// place it off so it's not visible
+			shell.setLocation(0, 10000);
+		}
+//		if (!checkInstanceLocation(instanceLocation, shell,
+//				workbench.getContext()))
+//			return EXIT_OK;
+
+		if( workbench != null ) {
+			IEclipseContext workbenchContext = workbench.getContext();
+			IEclipseContext serviceContext = workbenchContext.getParent();
+
+			// Create and run the UI (if any)
+			try {
+			    workbench.createAndRunUI(workbench.getApplication());
+			} finally {
+				e4App.saveModel();
+				workbench.close();
+				serviceContext.dispose();
+			}
+
+			if (workbench.isRestart()) {
+				return IApplication.EXIT_RESTART;
+			}
+		}
+
+		return IApplication.EXIT_OK;
+	}
+
+	private IApplicationContext getApplicationContext(final E4ApplicationConfig config) {
+		return new IApplicationContext() {
+
+			public org.osgi.framework.Bundle getBrandingBundle() {
+				return null;
+			}
+
+			@Override
+			public void setResult(Object result, IApplication application) {
+				// TODO Auto-generated method stub
+
+			}
+
+			@Override
+			public String getBrandingProperty(String key) {
+				if( IWorkbench.XMI_URI_ARG.equals(key) ) {
+					return config.getXmiURI();
+				} else if( IWorkbench.LIFE_CYCLE_URI_ARG.equals(key) ) {
+					return config.getLifecycleURI();
+				} else if( IWorkbench.PRESENTATION_URI_ARG .equals(key)) {
+					return config.getPresentationURI();
+				} else if( IWorkbench.CLEAR_PERSISTED_STATE.equals(key) ) {
+					return config.isClearPersistedState() + "";
+				} else if( IWorkbench.PERSIST_STATE.equals(key) ) {
+					return config.isPersistState() + "";
+				}
+				return null;
+			}
+
+			@Override
+			public String getBrandingName() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			@Override
+			public String getBrandingId() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			@Override
+			public String getBrandingDescription() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			@Override
+			public String getBrandingApplication() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			@Override
+			public Map getArguments() {
+				Map<Object, Object> rv = new HashMap<Object, Object>();
+				rv.put(IApplicationContext.APPLICATION_ARGS, new String[0]);
+				return rv;
+			}
+
+			@Override
+			public void applicationRunning() {
+				// TODO Auto-generated method stub
+
+			}
+		};
+	}
+
+	private void logProblem(Throwable problem) {
+//		String message = "Error when starting application, productName="
+//				+ productName;
+//		Logger logger = new WorkbenchLogger(PLUGIN_ID);
+//		logger.error(new RuntimeException(message, problem));
+		System.err.println("Problem");
+		problem.printStackTrace();
+	}
+
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/Activator.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/Activator.java
new file mode 100644
index 0000000..243351c
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/Activator.java
@@ -0,0 +1,63 @@
+package org.eclipse.rap.e4.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class Activator implements BundleActivator {
+	private static Activator singleton;
+	
+	private ServiceRegistration contextServiceReg; 
+	private ServiceRegistration handlerServiceReg;
+	
+	private ServiceTracker eventAdminTracker;
+	private BundleContext bundleContext;
+
+	/*
+	 * Returns the singleton for this Activator. Callers should be aware that
+	 * this will return null if the bundle is not active.
+	 */
+	public static Activator getDefault() {
+		return singleton;
+	}
+
+	public void start(BundleContext context) throws Exception {
+		bundleContext = context;
+		singleton = this;
+	}
+	
+	/*
+	 * Return the debug options service, if available.
+	 */
+	public EventAdmin getEventAdmin() {
+		if (eventAdminTracker == null) {
+			eventAdminTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
+			eventAdminTracker.open();
+		}
+		return (EventAdmin) eventAdminTracker.getService();
+	}
+
+	public void stop(BundleContext context) throws Exception {
+		if (contextServiceReg != null) {
+			contextServiceReg.unregister();
+			contextServiceReg = null;
+		}
+		if (handlerServiceReg != null) {
+			handlerServiceReg.unregister();
+			handlerServiceReg = null;
+		}
+		
+		if (eventAdminTracker != null) {
+			eventAdminTracker.close();
+			eventAdminTracker = null;
+		}
+		bundleContext = null;
+		singleton = null;
+	}
+	
+	public BundleContext getBundleContext() {
+		return bundleContext;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPAbstractObjectSupplierDispatcher.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPAbstractObjectSupplierDispatcher.java
new file mode 100644
index 0000000..32f19ee
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPAbstractObjectSupplierDispatcher.java
@@ -0,0 +1,78 @@
+package org.eclipse.rap.e4.internal;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.IInjector;
+import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
+import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
+import org.eclipse.e4.core.di.suppliers.IRequestor;
+import org.eclipse.e4.core.internal.contexts.ContextObjectSupplier;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.core.internal.contexts.IContextDisposalListener;
+import org.eclipse.e4.core.internal.di.Requestor;
+import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
+import org.eclipse.rap.e4.preferences.EPreferenceService;
+
+@SuppressWarnings("restriction")
+public abstract class RAPAbstractObjectSupplierDispatcher<S extends ExtendedObjectSupplier> extends ExtendedObjectSupplier {
+	private Map<IEclipseContext, ExtendedObjectSupplier> supplierCache = Collections.synchronizedMap(new HashMap<IEclipseContext, ExtendedObjectSupplier>());
+	private Map<IEclipseContext, IEclipseContext> rootContextMap = Collections.synchronizedMap(new HashMap<IEclipseContext, IEclipseContext>());
+	
+	private IContextDisposalListener disposeListener = new IContextDisposalListener() {
+		
+		@Override
+		public void disposed(IEclipseContext context) {
+			IEclipseContext rootContext = rootContextMap.remove(context);
+			if (rootContext != null) {
+				supplierCache.remove(rootContext);
+			}
+		}
+	};
+	
+	private final Class<S> supplierType;
+	
+	public RAPAbstractObjectSupplierDispatcher(Class<S> supplierType) {
+		this.supplierType = supplierType;
+	}
+	
+	@Override
+	public Object get(IObjectDescriptor descriptor, IRequestor requestor,
+			boolean track, boolean group) {
+		IEclipseContext c = getContext(requestor);
+		
+		IEclipseContext appContext = rootContextMap.get(c);
+		
+		if( appContext == null ) {
+			IEclipseContext tmp = c;
+			while( tmp != null && tmp.getLocal(E4Application.INSTANCEID) == null ) {
+				tmp = tmp.getParent();
+			}
+			
+			if( tmp == null ) {
+				System.err.println("FATAL: The injection is requested on a context which has no workbench context");
+				return IInjector.NOT_A_VALUE;
+			}
+			
+			((EclipseContext)c).notifyOnDisposal(disposeListener);
+			appContext = tmp;
+			rootContextMap.put(c, appContext);
+		}
+		
+		ExtendedObjectSupplier supplier = supplierCache.get(appContext);
+		if( supplier == null ) {
+			supplier = ContextInjectionFactory.make(supplierType, appContext);
+			supplierCache.put(appContext, supplier);
+		}
+		
+		return supplier.get(descriptor, requestor, track, group);
+	}
+	
+	private static IEclipseContext getContext(IRequestor requestor) {
+		Requestor requestorImpl = (Requestor) requestor;
+		return ((ContextObjectSupplier)requestorImpl.getPrimarySupplier()).getContext();
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java
new file mode 100644
index 0000000..6fdfe1c
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java
@@ -0,0 +1,184 @@
+package org.eclipse.rap.e4.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+
+public class RAPEventBroker implements IEventBroker {
+	    // TBD synchronization
+
+	    private static final String	ASYNC_EVENT = "rap.async.event";
+
+		private Map<EventHandler, Collection<ServiceRegistration<?>>> registrations = new HashMap<EventHandler, Collection<ServiceRegistration<?>>>();
+
+		@Inject
+		Logger logger;
+
+		@Inject
+		@Optional
+		UISynchronize uiSync;
+
+		@Inject
+		@Named(E4Application.INSTANCEID)
+		String instanceId;
+
+		// This is a temporary code to ensure that bundle containing
+		// EventAdmin implementation is started. This code it to be removed once
+		// the proper method to start EventAdmin is added.
+		static {
+			EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
+			if (eventAdmin == null) {
+				Bundle[] bundles = Activator.getDefault().getBundleContext().getBundles();
+				for (Bundle bundle : bundles) {
+					if (!"org.eclipse.equinox.event".equals(bundle.getSymbolicName()))
+						continue;
+					try {
+						bundle.start(Bundle.START_TRANSIENT);
+					} catch (BundleException e) {
+						e.printStackTrace();
+					}
+					break;
+				}
+			}
+		}
+
+		public RAPEventBroker() {
+			// placeholder
+		}
+
+		public boolean send(String topic, Object data) {
+			Event event = constructEvent(topic, data, false);
+			EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
+			if (eventAdmin == null) {
+				logger.error(NLS.bind("No EventAdmin", event.toString()));
+				return false;
+			}
+			eventAdmin.sendEvent(event);
+			return true;
+		}
+
+		public boolean post(String topic, Object data) {
+			Event event = constructEvent(topic, data, true);
+			EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
+			if (eventAdmin == null) {
+				logger.error(NLS.bind("No EventAdmin", event.toString()));
+				return false;
+			}
+			eventAdmin.postEvent(event);
+			return true;
+		}
+
+		@SuppressWarnings("unchecked")
+		private Event constructEvent(String topic, Object data, boolean async) {
+			topic = rapifyTopic(instanceId, topic);
+			Event event;
+			if (data instanceof Dictionary<?,?>) {
+				Dictionary<String,Object> properties = (Dictionary<String,Object>)data;
+				if (async)
+					properties.put(ASYNC_EVENT, Boolean.TRUE);
+				event = new Event(topic, properties);
+			} else if (data instanceof Map<?,?>) {
+				Map<String,Object> properties = (Map<String,Object>)data;
+				if (async)
+					properties.put(ASYNC_EVENT, Boolean.TRUE);
+				event = new Event(topic, properties);
+			} else {
+				Dictionary<String, Object> d = new Hashtable<String, Object>(3);
+				d.put(EventConstants.EVENT_TOPIC, topic);
+				if (data != null)
+					d.put(IEventBroker.DATA, data);
+				if (async)
+					d.put(ASYNC_EVENT, Boolean.TRUE);
+				event = new Event(topic, d);
+			}
+			return event;
+		}
+
+		public boolean subscribe(String topic, EventHandler eventHandler) {
+			return subscribe(topic, null, eventHandler, false);
+		}
+
+		public boolean subscribe(String topic, String filter, EventHandler eventHandler, boolean headless) {
+			topic = rapifyTopic(instanceId, topic);
+			BundleContext bundleContext = Activator.getDefault().getBundleContext();
+			if (bundleContext == null) {
+				logger.error(NLS.bind("No EventAdmin", topic));
+				return false;
+			}
+			String[] topics = new String[] {topic};
+			Dictionary<String, Object> d = new Hashtable<String, Object>();
+			d.put(EventConstants.EVENT_TOPIC, topics);
+			if (filter != null)
+				d.put(EventConstants.EVENT_FILTER, filter);
+			EventHandler wrappedHandler = new RAPUIEventHandler(eventHandler, headless ? null : uiSync);
+			ServiceRegistration<?> registration = bundleContext.registerService(
+					EventHandler.class.getName(), wrappedHandler, d);
+			Collection<ServiceRegistration<?>> handled = registrations
+					.get(eventHandler);
+			if (handled == null) {
+				registrations.put(eventHandler,
+						handled = new ArrayList<ServiceRegistration<?>>());
+			}
+			handled.add(registration);
+			return true;
+		}
+
+		public boolean unsubscribe(EventHandler eventHandler) {
+			Collection<ServiceRegistration<?>> handled = registrations
+					.remove(eventHandler);
+			if (handled == null || handled.isEmpty())
+				return false;
+			for (ServiceRegistration<?> r : handled) {
+				r.unregister();
+			}
+			return true;
+		}
+
+		@PreDestroy
+		void dispose() {
+			Collection<Collection<ServiceRegistration<?>>> values = new ArrayList<Collection<ServiceRegistration<?>>>(
+					registrations.values());
+			registrations.clear();
+			for (Collection<ServiceRegistration<?>> handled : values) {
+				for (ServiceRegistration<?> registration : handled) {
+					// System.out.println("EventBroker dispose:" + registration[i] +
+					// ")");
+					registration.unregister();
+				}
+			}
+		}
+
+		public static String rapifyTopic(String instanceId, String topic) {
+			String rv = instanceId + "/" + topic;
+//			System.err.println("Original: " + topic + ", RAPified: " + rv);
+			return rv;
+		}
+
+		public static boolean isAsyncEvent(Event event) {
+			return Boolean.TRUE.equals(event.getProperty(ASYNC_EVENT));
+		}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBrokerContextFunction.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBrokerContextFunction.java
new file mode 100644
index 0000000..66eb04f
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBrokerContextFunction.java
@@ -0,0 +1,17 @@
+package org.eclipse.rap.e4.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+public class RAPEventBrokerContextFunction extends ContextFunction {
+	@Override
+	public Object compute(IEclipseContext context) {
+		RAPEventBroker broker = context.getLocal(RAPEventBroker.class);
+		if (broker == null) {
+            broker = ContextInjectionFactory.make(RAPEventBroker.class, context);
+            context.set(RAPEventBroker.class, broker);
+		}
+		return broker;
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplier.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplier.java
new file mode 100644
index 0000000..590a59b
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplier.java
@@ -0,0 +1,250 @@
+package org.eclipse.rap.e4.internal;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.IInjector;
+import org.eclipse.e4.core.di.InjectionException;
+import org.eclipse.e4.core.di.extensions.EventTopic;
+import org.eclipse.e4.core.di.extensions.EventUtils;
+import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
+import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
+import org.eclipse.e4.core.di.suppliers.IRequestor;
+import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+
+@SuppressWarnings("restriction")
+public class RAPEventObjectSupplier extends ExtendedObjectSupplier {
+
+	// This is a temporary code to ensure that bundle containing
+	// EventAdmin implementation is started. This code it to be removed once
+	// the proper method to start EventAdmin is added.
+	static {
+		if (getEventAdmin() == null) {
+			Bundle[] bundles = Activator.getDefault().getBundleContext().getBundles();
+			for (Bundle bundle : bundles) {
+				if (!"org.eclipse.equinox.event".equals(bundle.getSymbolicName())) //$NON-NLS-1$
+					continue;
+				try {
+					bundle.start(Bundle.START_TRANSIENT);
+				} catch (BundleException e) {
+					e.printStackTrace();
+				}
+				break;
+			}
+		}
+	}
+
+	protected Map<String, Event> currentEvents = new HashMap<String, Event>();
+
+	class DIEventHandler implements EventHandler {
+
+		final private IRequestor requestor;
+		final private String topic;
+
+		public DIEventHandler(String topic, IRequestor requestor) {
+			this.topic = topic;
+			this.requestor = requestor;
+		}
+
+		public void handleEvent(Event event) {
+			if (!requestor.isValid()) {
+				unsubscribe(requestor);
+				return;
+			}
+
+			addCurrentEvent(topic, event);
+			requestor.resolveArguments(false);
+			removeCurrentEvent(topic);
+
+			requestor.execute();
+		}
+	}
+
+	// A combo of { IRequestor + topic } used in Map lookups
+	static private class Subscriber {
+		private IRequestor requestor;
+		private String topic;
+
+		public Subscriber(IRequestor requestor, String topic) {
+			super();
+			this.requestor = requestor;
+			this.topic = topic;
+		}
+
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + ((requestor == null) ? 0 : requestor.hashCode());
+			result = prime * result + ((topic == null) ? 0 : topic.hashCode());
+			return result;
+		}
+
+		public IRequestor getRequestor() {
+			return requestor;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			Subscriber other = (Subscriber) obj;
+			if (requestor == null) {
+				if (other.requestor != null)
+					return false;
+			} else if (!requestor.equals(other.requestor))
+				return false;
+			if (topic == null) {
+				if (other.topic != null)
+					return false;
+			} else if (!topic.equals(other.topic))
+				return false;
+			return true;
+		}
+
+	}
+
+	private Map<Subscriber, ServiceRegistration> registrations = new HashMap<Subscriber, ServiceRegistration>();
+
+	@Inject
+	@Named(E4Application.INSTANCEID)
+	protected String instanceId;
+
+	protected void addCurrentEvent(String topic, Event event) {
+		synchronized (currentEvents) {
+			currentEvents.put(topic, event);
+		}
+	}
+
+	protected void removeCurrentEvent(String topic) {
+		synchronized (currentEvents) {
+			currentEvents.remove(topic);
+		}
+	}
+
+	@Override
+	public Object get(IObjectDescriptor descriptor, IRequestor requestor, boolean track, boolean group) {
+		if (descriptor == null)
+			return null;
+		String topic = getTopic(descriptor);
+		EventAdmin eventAdmin = getEventAdmin();
+		if (topic == null || eventAdmin == null || topic.length() == 0)
+			return IInjector.NOT_A_VALUE;
+
+		if (track)
+			subscribe(topic, eventAdmin, requestor);
+		else
+			unsubscribe(requestor);
+
+		if (!currentEvents.containsKey(topic))
+			return IInjector.NOT_A_VALUE;
+
+		// convert to fit destination
+		Class<?> descriptorsClass = getDesiredClass(descriptor.getDesiredType());
+		if (descriptorsClass.equals(Event.class))
+			return currentEvents.get(topic);
+		return currentEvents.get(topic).getProperty(EventUtils.DATA);
+	}
+
+	private void subscribe(String topic, EventAdmin eventAdmin, IRequestor requestor) {
+		Subscriber subscriber = new Subscriber(requestor, topic);
+		synchronized (registrations) {
+			if (registrations.containsKey(subscriber))
+				return;
+		}
+		BundleContext bundleContext = Activator.getDefault().getBundleContext();
+		if (bundleContext == null)
+			throw new InjectionException("Unable to subscribe to events: org.eclipse.e4.core.di.extensions bundle is not activated"); //$NON-NLS-1$
+
+		String[] topics = new String[] {topic};
+		Dictionary<String, Object> d = new Hashtable<String, Object>();
+		d.put(EventConstants.EVENT_TOPIC, topics);
+		EventHandler wrappedHandler = makeHandler(topic, requestor);
+		ServiceRegistration registration = bundleContext.registerService(EventHandler.class.getName(), wrappedHandler, d);
+		// due to the way requestors are constructed this limited synch should be OK
+		synchronized (registrations) {
+			registrations.put(subscriber, registration);
+		}
+	}
+
+	protected EventHandler makeHandler(String topic, IRequestor requestor) {
+		return new DIEventHandler(topic, requestor);
+	}
+
+	protected String getTopic(IObjectDescriptor descriptor) {
+		if (descriptor == null)
+			return null;
+		EventTopic qualifier = descriptor.getQualifier(EventTopic.class);
+		String topic = qualifier.value();
+		topic = RAPEventBroker.rapifyTopic(instanceId, topic);
+		return topic;
+	}
+
+	static private EventAdmin getEventAdmin() {
+		return Activator.getDefault().getEventAdmin();
+	}
+
+	protected void unsubscribe(IRequestor requestor) {
+		if (requestor == null)
+			return;
+		synchronized (registrations) {
+			Iterator<Entry<Subscriber, ServiceRegistration>> i = registrations.entrySet().iterator();
+			while (i.hasNext()) {
+				Entry<Subscriber, ServiceRegistration> entry = i.next();
+				Subscriber key = entry.getKey();
+				if (!requestor.equals(key.getRequestor()))
+					continue;
+				ServiceRegistration registration = entry.getValue();
+				registration.unregister();
+				i.remove();
+			}
+		}
+	}
+
+	@PreDestroy
+	public void dispose() {
+		ServiceRegistration[] array;
+		synchronized (registrations) {
+			Collection<ServiceRegistration> values = registrations.values();
+			array = values.toArray(new ServiceRegistration[values.size()]);
+			registrations.clear();
+		}
+		for (int i = 0; i < array.length; i++) {
+			array[i].unregister();
+		}
+	}
+
+	private Class<?> getDesiredClass(Type desiredType) {
+		if (desiredType instanceof Class<?>)
+			return (Class<?>) desiredType;
+		if (desiredType instanceof ParameterizedType) {
+			Type rawType = ((ParameterizedType) desiredType).getRawType();
+			if (rawType instanceof Class<?>)
+				return (Class<?>) rawType;
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplierDispatcher.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplierDispatcher.java
new file mode 100644
index 0000000..6d760e3
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventObjectSupplierDispatcher.java
@@ -0,0 +1,8 @@
+package org.eclipse.rap.e4.internal;
+
+public class RAPEventObjectSupplierDispatcher extends RAPAbstractObjectSupplierDispatcher<RAPEventObjectSupplier> {
+
+	public RAPEventObjectSupplierDispatcher() {
+		super(RAPEventObjectSupplier.class);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplier.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplier.java
new file mode 100644
index 0000000..b3a911a
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplier.java
@@ -0,0 +1,394 @@
+package org.eclipse.rap.e4.internal;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferenceNodeVisitor;
+import org.eclipse.e4.core.di.IInjector;
+import org.eclipse.e4.core.di.extensions.Preference;
+import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
+import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
+import org.eclipse.e4.core.di.suppliers.IRequestor;
+import org.eclipse.rap.e4.preferences.EPreference;
+import org.eclipse.rap.e4.preferences.EPreferenceListener;
+import org.eclipse.rap.e4.preferences.EPreferenceService;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+@SuppressWarnings("restriction")
+public class RAPPreferencesObjectSupplier extends ExtendedObjectSupplier {
+
+	static private class PrefInjectionListener implements EPreferenceListener {
+
+		final private IRequestor requestor;
+		final private EPreference node;
+
+		public PrefInjectionListener(EPreference node, IRequestor requestor) {
+			this.node = node;
+			this.requestor = requestor;
+		}
+
+		@Override
+		public void preferenceChange() {
+			if (!requestor.isValid()) {
+				node.removeChangeListener(this);
+				return;
+			}
+			requestor.resolveArguments(false);
+			requestor.execute();
+		}
+
+		public IRequestor getRequestor() {
+			return requestor;
+		}
+
+		public void stopListening() {
+			node.removeChangeListener(this);
+		}
+	}
+
+	private Map<String, List<PrefInjectionListener>> listenerCache = new HashMap<String, List<PrefInjectionListener>>();
+
+	@Inject
+	EPreferenceService preferenceService;
+	
+	public RAPPreferencesObjectSupplier() {
+//		DIEActivator.getDefault().registerPreferencesSupplier(this);
+	}
+
+	@Override
+	public Object get(IObjectDescriptor descriptor, IRequestor requestor, boolean track, boolean group) {
+		if (descriptor == null)
+			return null;
+		Class<?> descriptorsClass = getDesiredClass(descriptor.getDesiredType());
+		String nodePath = getNodePath(descriptor, requestor.getRequestingObjectClass());
+		if (IEclipsePreferences.class.equals(descriptorsClass)) {
+			return new WrappedPreference(getPreferencesService().getNode(nodePath));
+//			return getPreferencesService().getNode(nodePath);
+		} else if( EPreference.class.equals(descriptorsClass) ) {
+			return getPreferencesService().getNode(nodePath);
+		}
+
+		String key = getKey(descriptor);
+		if (key == null || nodePath == null || key.length() == 0 || nodePath.length() == 0)
+			return IInjector.NOT_A_VALUE;
+		if (track)
+			addListener(nodePath, requestor);
+
+		if (descriptorsClass.isPrimitive()) {
+			if (descriptorsClass.equals(boolean.class))
+				return getPreferencesService().getBoolean(nodePath, key, false);
+			else if (descriptorsClass.equals(int.class))
+				return getPreferencesService().getInt(nodePath, key, 0);
+			else if (descriptorsClass.equals(double.class))
+				return getPreferencesService().getDouble(nodePath, key, 0.0d);
+			else if (descriptorsClass.equals(float.class))
+				return getPreferencesService().getFloat(nodePath, key, 0.0f);
+			else if (descriptorsClass.equals(long.class))
+				return getPreferencesService().getLong(nodePath, key, 0L);
+		}
+
+		if (String.class.equals(descriptorsClass))
+			return getPreferencesService().getString(nodePath, key);
+		else if (Boolean.class.equals(descriptorsClass))
+			return getPreferencesService().getBoolean(nodePath, key, false);
+		else if (Integer.class.equals(descriptorsClass))
+			return getPreferencesService().getInt(nodePath, key, 0);
+		else if (Double.class.equals(descriptorsClass))
+			return getPreferencesService().getDouble(nodePath, key, 0.0d);
+		else if (Float.class.equals(descriptorsClass))
+			return getPreferencesService().getFloat(nodePath, key, 0.0f);
+		else if (Long.class.equals(descriptorsClass))
+			return getPreferencesService().getLong(nodePath, key, 0L);
+
+		return getPreferencesService().getString(nodePath, key);
+	}
+
+	private Class<?> getDesiredClass(Type desiredType) {
+		if (desiredType instanceof Class<?>)
+			return (Class<?>) desiredType;
+		if (desiredType instanceof ParameterizedType) {
+			Type rawType = ((ParameterizedType) desiredType).getRawType();
+			if (rawType instanceof Class<?>)
+				return (Class<?>) rawType;
+		}
+		return null;
+	}
+
+	private String getKey(IObjectDescriptor descriptor) {
+		if (descriptor == null)
+			return null;
+		Preference qualifier = descriptor.getQualifier(Preference.class);
+		return qualifier.value();
+	}
+
+	private String getNodePath(IObjectDescriptor descriptor, Class<?> requestingObject) {
+		if (descriptor == null)
+			return null;
+		Preference qualifier = descriptor.getQualifier(Preference.class);
+		String nodePath = qualifier.nodePath();
+
+		if (nodePath == null || nodePath.length() == 0) {
+			if (requestingObject == null)
+				return null;
+			nodePath = FrameworkUtil.getBundle(requestingObject).getSymbolicName();
+		}
+		return nodePath;
+	}
+
+	private EPreferenceService getPreferencesService() {
+//		return DIEActivator.getDefault().getPreferencesService();
+		return preferenceService;
+	}
+
+	private void addListener(String nodePath, final IRequestor requestor) {
+		if (requestor == null)
+			return;
+		synchronized (listenerCache) {
+			if (listenerCache.containsKey(nodePath)) {
+				for (PrefInjectionListener listener : listenerCache.get(nodePath)) {
+					IRequestor previousRequestor = listener.getRequestor();
+					if (previousRequestor.equals(requestor))
+						return; // avoid adding duplicate listeners
+				}
+			}
+		}
+		final EPreference node = getPreferencesService().getNode(nodePath);
+		PrefInjectionListener listener = new PrefInjectionListener(node, requestor);
+		node.addChangeListener(listener);
+
+		synchronized (listenerCache) {
+			if (listenerCache.containsKey(nodePath))
+				listenerCache.get(nodePath).add(listener);
+			else {
+				List<PrefInjectionListener> listeningRequestors = new ArrayList<PrefInjectionListener>();
+				listeningRequestors.add(listener);
+				listenerCache.put(nodePath, listeningRequestors);
+			}
+		}
+	}
+
+	public void removeAllListeners() {
+		synchronized (listenerCache) {
+			for (List<PrefInjectionListener> listeners : listenerCache.values()) {
+				if (listeners == null)
+					continue;
+				for (PrefInjectionListener listener : listeners) {
+					listener.stopListening();
+				}
+			}
+			listenerCache.clear();
+		}
+	}
+	
+	@PreDestroy
+	void shutdown() {
+		removeAllListeners();
+	}
+	
+	public static class WrappedPreference implements IEclipsePreferences {
+		private EPreference node;
+		
+		public WrappedPreference(EPreference node) {
+			this.node = node;
+		}
+
+		@Override
+		public String absolutePath() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String[] childrenNames() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public void clear() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void flush() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public String get(String arg0, String arg1) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public boolean getBoolean(String arg0, boolean arg1) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public byte[] getByteArray(String arg0, byte[] arg1) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public double getDouble(String arg0, double arg1) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public float getFloat(String arg0, float arg1) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public int getInt(String arg0, int arg1) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public long getLong(String arg0, long arg1) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public String[] keys() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String name() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public boolean nodeExists(String arg0) throws BackingStoreException {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public Preferences parent() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public void put(String arg0, String arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putBoolean(String arg0, boolean arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putByteArray(String arg0, byte[] arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putDouble(String arg0, double arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putFloat(String arg0, float arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putInt(String arg0, int arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void putLong(String arg0, long arg1) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void remove(String arg0) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void sync() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void accept(IPreferenceNodeVisitor arg0)
+				throws BackingStoreException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void addNodeChangeListener(INodeChangeListener arg0) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void addPreferenceChangeListener(IPreferenceChangeListener arg0) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public Preferences node(String arg0) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public void removeNode() throws BackingStoreException {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void removeNodeChangeListener(INodeChangeListener arg0) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		public void removePreferenceChangeListener(
+				IPreferenceChangeListener arg0) {
+			// TODO Auto-generated method stub
+			
+		}
+		
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplierDispatcher.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplierDispatcher.java
new file mode 100644
index 0000000..c0f96e8
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPPreferencesObjectSupplierDispatcher.java
@@ -0,0 +1,8 @@
+package org.eclipse.rap.e4.internal;
+
+public class RAPPreferencesObjectSupplierDispatcher extends RAPAbstractObjectSupplierDispatcher<RAPPreferencesObjectSupplier> {
+	public RAPPreferencesObjectSupplierDispatcher() {
+		super(RAPPreferencesObjectSupplier.class);
+	}
+
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPTranslationSupplierDispatcher.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPTranslationSupplierDispatcher.java
new file mode 100644
index 0000000..248082b
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPTranslationSupplierDispatcher.java
@@ -0,0 +1,11 @@
+package org.eclipse.rap.e4.internal;
+
+import org.eclipse.e4.core.internal.services.TranslationObjectSupplier;
+
+@SuppressWarnings("restriction")
+public class RAPTranslationSupplierDispatcher extends RAPAbstractObjectSupplierDispatcher<TranslationObjectSupplier> {
+
+	public RAPTranslationSupplierDispatcher() {
+		super(TranslationObjectSupplier.class);
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java
new file mode 100644
index 0000000..a62d958
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 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.rap.e4.internal;
+
+import org.eclipse.e4.ui.di.UISynchronize;
+
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * The helper will properly place UI-aware consumers on the main thread.
+ */
+public class RAPUIEventHandler implements EventHandler {
+
+	final private EventHandler eventHandler;
+	final private UISynchronize uiSync;
+
+	public RAPUIEventHandler(EventHandler eventHandler, UISynchronize uiSync) {
+		this.eventHandler = eventHandler;
+		this.uiSync = uiSync;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
+	 */
+	public void handleEvent(final Event event) {
+		if (uiSync == null)
+			eventHandler.handleEvent(event);
+		else {
+			if(RAPEventBroker.isAsyncEvent(event)) {
+				uiSync.asyncExec(new Runnable() {
+					public void run() {
+						eventHandler.handleEvent(event);
+					}
+				});
+			} else {
+				uiSync.syncExec(new Runnable() {
+					public void run() {
+						eventHandler.handleEvent(event);
+					}
+				});
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java
new file mode 100644
index 0000000..c1eb2cb
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java
@@ -0,0 +1,71 @@
+package org.eclipse.rap.e4.internal;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
+import org.eclipse.e4.core.di.suppliers.IRequestor;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.osgi.service.event.EventHandler;
+
+@SuppressWarnings("restriction")
+public class RAPUIEventObjectSupplier extends RAPEventObjectSupplier {
+
+	class UIEventHandler implements EventHandler {
+
+		final protected IRequestor requestor;
+		final private String topic;
+
+		public UIEventHandler(String topic, IRequestor requestor) {
+			this.topic = topic;
+			this.requestor = requestor;
+		}
+
+		public void handleEvent(org.osgi.service.event.Event event) {
+			addCurrentEvent(topic, event);
+			requestor.resolveArguments(false);
+			removeCurrentEvent(topic);
+			if( uiSync == null ) {
+				if (logger != null)
+					logger.log(Level.WARNING, "No realm found to process UI event " + event);
+				return;
+			} else {
+				if(RAPEventBroker.isAsyncEvent(event)) {
+					uiSync.asyncExec(new Runnable() {
+						public void run() {
+							requestor.execute();
+						}
+					});
+				} else {
+					uiSync.syncExec(new Runnable() {
+						public void run() {
+							requestor.execute();
+						}
+					});
+				}
+			}
+		}
+	}
+
+	@Inject
+	protected UISynchronize uiSync;
+
+	@Inject @Optional
+	protected Logger logger;
+
+	protected EventHandler makeHandler(String topic, IRequestor requestor) {
+		return new UIEventHandler(topic, requestor);
+	}
+
+	protected String getTopic(IObjectDescriptor descriptor) {
+		if (descriptor == null)
+			return null;
+		UIEventTopic qualifier = descriptor.getQualifier(UIEventTopic.class);
+		return RAPEventBroker.rapifyTopic(instanceId, qualifier.value());
+	}
+
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplierDispatcher.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplierDispatcher.java
new file mode 100644
index 0000000..f706a03
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplierDispatcher.java
@@ -0,0 +1,8 @@
+package org.eclipse.rap.e4.internal;
+
+public class RAPUIEventObjectSupplierDispatcher extends RAPAbstractObjectSupplierDispatcher<RAPUIEventObjectSupplier> {
+
+	public RAPUIEventObjectSupplierDispatcher() {
+		super(RAPUIEventObjectSupplier.class);
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreference.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreference.java
new file mode 100644
index 0000000..1793185
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreference.java
@@ -0,0 +1,23 @@
+package org.eclipse.rap.e4.preferences;
+
+import org.eclipse.core.runtime.IStatus;
+
+public interface EPreference {
+
+	void addChangeListener(EPreferenceListener listener);
+	void removeChangeListener(EPreferenceListener listener);
+	
+	boolean getBoolean(String key, boolean defaultValue);
+	int getInt(String key, int defaultValue);
+	double getDouble(String key, double defaultValue);
+	float getFloat(String key, float defaultValue);
+	long getLong(String key, long defaultValue);
+	String getString(String key);
+	
+	IStatus setBoolean(String key, boolean value);
+	IStatus setInt(String key, int value);
+	IStatus setDouble(String key, double value);
+	IStatus setFloat(String key, float value);
+	IStatus setLong(String key, long value);
+	IStatus setString(String key, String value);
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceListener.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceListener.java
new file mode 100644
index 0000000..d566f35
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceListener.java
@@ -0,0 +1,7 @@
+package org.eclipse.rap.e4.preferences;
+
+public interface EPreferenceListener {
+
+	void preferenceChange();
+
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceService.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceService.java
new file mode 100644
index 0000000..23cfe69
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/EPreferenceService.java
@@ -0,0 +1,32 @@
+package org.eclipse.rap.e4.preferences;
+
+import org.eclipse.core.runtime.IStatus;
+
+
+public interface EPreferenceService {
+	public EPreference getNode(String nodePath);
+
+	public boolean getBoolean(String nodePath, String key, boolean b);
+
+	public int getInt(String nodePath, String key, int i);
+
+	public double getDouble(String nodePath, String key, double d);
+
+	public float getFloat(String nodePath, String key, float f);
+
+	public long getLong(String nodePath, String key, long l);
+
+	public String getString(String nodePath, String key);
+	
+	public IStatus setBoolean(String nodePath, String key, boolean value);
+	
+	public IStatus setDouble(String nodePath, String key, double value);
+	
+	public IStatus setFloat(String nodePath, String key, float value);
+	
+	public IStatus setInt(String nodePath, String key, int value);
+	
+	public IStatus setLong(String nodePath, String key, long value);
+	
+	public IStatus setString(String nodePath, String key, String value);
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/PreferenceServiceContextFunction.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/PreferenceServiceContextFunction.java
new file mode 100644
index 0000000..34670ef
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/PreferenceServiceContextFunction.java
@@ -0,0 +1,13 @@
+package org.eclipse.rap.e4.preferences.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+
+public class PreferenceServiceContextFunction extends ContextFunction {
+	
+	@Override
+	public Object compute(IEclipseContext context) {
+		return ContextInjectionFactory.make(RAPPreferenceService.class, context);
+	}
+}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/RAPPreferenceService.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/RAPPreferenceService.java
new file mode 100644
index 0000000..bf65613
--- /dev/null
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/preferences/internal/RAPPreferenceService.java
@@ -0,0 +1,261 @@
+package org.eclipse.rap.e4.preferences.internal;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.WeakHashMap;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.rap.e4.preferences.EPreference;
+import org.eclipse.rap.e4.preferences.EPreferenceListener;
+import org.eclipse.rap.e4.preferences.EPreferenceService;
+import org.eclipse.rap.rwt.service.SettingStore;
+import org.eclipse.rap.rwt.service.SettingStoreEvent;
+import org.eclipse.rap.rwt.service.SettingStoreListener;
+
+public class RAPPreferenceService implements EPreferenceService {
+	
+	private final SettingStore settingStore;
+	
+	private Map<PreferenceImpl, Boolean> trackedPreferences = Collections.synchronizedMap(new WeakHashMap<RAPPreferenceService.PreferenceImpl, Boolean>());
+	
+	private final SettingStoreListener listener;
+	
+	@Inject
+	public RAPPreferenceService(SettingStore settingStore) {
+		this.settingStore = settingStore;
+		this.listener = new SettingStoreListener() {
+			
+			@Override
+			public void settingChanged(SettingStoreEvent event) {
+				if( event.getAttributeName().contains("#") ) {
+					String nodePath = event.getAttributeName().substring(0,event.getAttributeName().indexOf('#'));
+					PreferenceImpl[] array = new PreferenceImpl[trackedPreferences.size()];
+					synchronized (trackedPreferences) {
+						Iterator<Entry<PreferenceImpl, Boolean>> iterator = trackedPreferences.entrySet().iterator();
+						int index = 0;
+						while( iterator.hasNext() ) {
+							Entry<PreferenceImpl, Boolean> entry = iterator.next();
+							if( entry.getKey() == null ) {
+								iterator.remove();
+							} else if( entry.getKey().nodePath.equals(nodePath) ) {
+								array[index++] = entry.getKey();
+							}
+						}
+					}
+					
+					for( int i = 0; i < array.length; i++ ) {
+						if( array[i] == null ) {
+							break;
+						}
+						array[i].fireChange();
+					}
+				}
+			}
+		};
+		this.settingStore.addSettingStoreListener(listener);
+	}
+	
+	public void track(PreferenceImpl impl) {
+		trackedPreferences.put(impl, Boolean.TRUE);
+	}
+	
+	public void untrack(PreferenceImpl impl) {
+		trackedPreferences.remove(impl);
+	}
+
+	@Override
+	public boolean getBoolean(String nodePath, String key, boolean defaultValue) {
+		String v = settingStore.getAttribute(getAttributeName(nodePath,key));
+		if( v == null ) {
+			return defaultValue;
+		}
+		return Boolean.valueOf(v);
+	}
+
+	@Override
+	public int getInt(String nodePath, String key, int defaultValue) {
+		String v = settingStore.getAttribute(getAttributeName(nodePath,key));
+		if( v == null ) {
+			return defaultValue;
+		}
+		return Integer.parseInt(v);
+	}
+
+	@Override
+	public double getDouble(String nodePath, String key, double defaultValue) {
+		String v = settingStore.getAttribute(getAttributeName(nodePath,key));
+		if( v == null ) {
+			return defaultValue;
+		}
+		return Double.parseDouble(v);
+	}
+
+	@Override
+	public float getFloat(String nodePath, String key, float defaultValue) {
+		String v = settingStore.getAttribute(getAttributeName(nodePath,key));
+		if( v == null ) {
+			return defaultValue;
+		}
+		return Float.parseFloat(v);
+	}
+
+	@Override
+	public long getLong(String nodePath, String key, long defaultValue) {
+		String v = settingStore.getAttribute(getAttributeName(nodePath,key));
+		if( v == null ) {
+			return defaultValue;
+		}
+		return Long.parseLong(v);
+	}
+
+	@Override
+	public String getString(String nodePath, String key) {
+		return settingStore.getAttribute(getAttributeName(nodePath,key));
+	}
+
+	@Override
+	public EPreference getNode(String nodePath) {
+		return new PreferenceImpl(nodePath);
+	}
+	
+	@Override
+	public IStatus setBoolean(String nodePath, String key, boolean value) {
+		return setString(nodePath, key, value+"");
+	}
+	
+	@Override
+	public IStatus setDouble(String nodePath, String key, double value) {
+		return setString(nodePath, key, value+"");
+	}
+	
+	@Override
+	public IStatus setFloat(String nodePath, String key, float value) {
+		return setString(nodePath, key, value+"");
+	}
+	
+	@Override
+	public IStatus setInt(String nodePath, String key, int value) {
+		return setString(nodePath, key, value+"");
+	}
+	
+	@Override
+	public IStatus setLong(String nodePath, String key, long value) {
+		return setString(nodePath, key, value+"");
+	}
+	
+	@Override
+	public IStatus setString(String nodePath, String key, String value) {
+		try {
+			settingStore.setAttribute(getAttributeName(nodePath, key), value);
+			return Status.OK_STATUS;
+		} catch (IOException e) {
+			return new Status(IStatus.ERROR, "org.eclipse.rap.e4", "Unable to store preference", e);
+		}
+	}
+	
+	static String getAttributeName(String nodePath, String key) {
+		return nodePath+"#"+key;
+	}
+	
+	class PreferenceImpl implements EPreference {
+		private String nodePath;
+		private List<EPreferenceListener> listenerList = new ArrayList<EPreferenceListener>();
+		
+		public PreferenceImpl(String nodePath) {
+			this.nodePath = nodePath;
+		}
+		
+		@Override
+		public boolean getBoolean(String key, boolean defaultValue) {
+			return RAPPreferenceService.this.getBoolean(nodePath, key, defaultValue);
+		}
+
+		@Override
+		public int getInt(String key, int defaultValue) {
+			return RAPPreferenceService.this.getInt(nodePath, key, defaultValue);
+		}
+
+		@Override
+		public double getDouble(String key, double defaultValue) {
+			return RAPPreferenceService.this.getDouble(nodePath, key, defaultValue);
+		}
+
+		@Override
+		public float getFloat(String key, float defaultValue) {
+			return RAPPreferenceService.this.getFloat(nodePath, key, defaultValue);
+		}
+
+		@Override
+		public long getLong(String key, long defaultValue) {
+			return RAPPreferenceService.this.getLong(nodePath, key, defaultValue);
+		}
+
+		@Override
+		public String getString(String key) {
+			return RAPPreferenceService.this.getString(nodePath, key);
+		}
+		
+		@Override
+		public IStatus setBoolean(String key, boolean value) {
+			return RAPPreferenceService.this.setBoolean(nodePath, key, value);
+		}
+		
+		@Override
+		public IStatus setDouble(String key, double value) {
+			return RAPPreferenceService.this.setDouble(nodePath, key, value);
+		}
+		
+		@Override
+		public IStatus setFloat(String key, float value) {
+			return RAPPreferenceService.this.setFloat(nodePath, key, value);
+		}
+		
+		@Override
+		public IStatus setInt(String key, int value) {
+			return RAPPreferenceService.this.setInt(nodePath, key, value);
+		}
+		
+		@Override
+		public IStatus setLong(String key, long value) {
+			return RAPPreferenceService.this.setLong(nodePath, key, value);
+		}
+		
+		@Override
+		public IStatus setString(String key, String value) {
+			return RAPPreferenceService.this.setString(nodePath, key, value);
+		}
+
+		@Override
+		public void addChangeListener(EPreferenceListener listener) {
+			listenerList.add(listener);
+			if( listenerList.size() == 1 ) {
+				RAPPreferenceService.this.track(this);
+			}
+		}
+
+		@Override
+		public void removeChangeListener(EPreferenceListener listener) {
+			listenerList.remove(listener);
+			if( listenerList.isEmpty() ) {
+				RAPPreferenceService.this.untrack(this);
+			}
+		}
+		
+		public void fireChange() {
+			if( ! listenerList.isEmpty() ) {
+				EPreferenceListener[] listeners = listenerList.toArray(new EPreferenceListener[listenerList.size()]);
+				for( int i = 0; i < listeners.length; i++ ) {
+					listeners[i].preferenceChange();
+				}
+			}
+		}
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/.classpath b/examples/org.eclipse.rap.e4.demo/.classpath
new file mode 100644
index 0000000..1fa3e68
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/examples/org.eclipse.rap.e4.demo/.project b/examples/org.eclipse.rap.e4.demo/.project
new file mode 100644
index 0000000..9446e49
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.rap.e4.demo</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.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/examples/org.eclipse.rap.e4.demo/Application.e4xmi b/examples/org.eclipse.rap.e4.demo/Application.e4xmi
new file mode 100644
index 0000000..8b595bc
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/Application.e4xmi
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:advanced="http://www.eclipse.org/ui/2010/UIModel/application/ui/advanced" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_-j-GgKBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ide.application" bindingContexts="_-j-tkKBNEeODEs7-bWqIxA">
+  <children xsi:type="basic:TrimmedWindow" xmi:id="_-j-GgaBNEeODEs7-bWqIxA" label="%trimmedwindow.label.1" width="500" height="400">
+    <children xsi:type="advanced:PerspectiveStack" xmi:id="_X6m9cBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.perspectivestack.0">
+      <children xsi:type="advanced:Perspective" xmi:id="_YZLIwBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.perspective.0" label="">
+        <children xsi:type="basic:PartSashContainer" xmi:id="_5fAc0KLgEeSGUftsJTPCBQ" elementId="org.eclipse.rap.e4.demo.partsashcontainer.2">
+          <children xsi:type="basic:PartSashContainer" xmi:id="_FPvvQKCAEeOCJ5u74o02rg" elementId="org.eclipse.rap.e4.demo.partsashcontainer.0" containerData="100" horizontal="true">
+            <children xsi:type="basic:PartStack" xmi:id="_8eKmwKJKEeSZFtDwdo07Rg" elementId="org.eclipse.rap.e4.demo.partstack.1" containerData="100">
+              <children xsi:type="basic:Part" xmi:id="_FzadAKCAEeOCJ5u74o02rg" elementId="org.eclipse.rap.e4.demo.part.0" containerData="100" label="Empty Left" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/folder_user.png"/>
+              <children xsi:type="advanced:Placeholder" xmi:id="_w0yjEBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.placeholder.0" ref="_hixKgBqfEeW5c6mkiizldg"/>
+            </children>
+            <children xsi:type="basic:PartStack" xmi:id="_M-uNIKCAEeOCJ5u74o02rg" elementId="org.eclipse.rap.e4.demo.partstack.0" containerData="300">
+              <children xsi:type="basic:Part" xmi:id="_GwxdIKCAEeOCJ5u74o02rg" elementId="org.eclipse.rap.e4.demo.part.1" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.EventSamplePart" label="%part.label.1" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/user_delete.png">
+                <toolbar xmi:id="_HHjAcOGREeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.toolbar.1">
+                  <children xsi:type="menu:DirectToolItem" xmi:id="_Hh9EgOGREeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.directtoolitem.1" label="%directtoolitem.label.1" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+                </toolbar>
+              </children>
+              <children xsi:type="basic:Part" xmi:id="_rk6l0KhAEeO0Haj3z6o3PQ" elementId="org.eclipse.rap.e4.demo.part.2" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.PreferenceSamplePart" label="%part.label.2" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/user_add.png">
+                <menus xmi:id="_EIg8IOGUEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.menu.2">
+                  <tags>ViewMenu</tags>
+                  <children xsi:type="menu:DirectMenuItem" xmi:id="_HAt4UOGUEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.directmenuitem.1" label="%directmenuitem.label.2" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+                </menus>
+              </children>
+              <children xsi:type="basic:Part" xmi:id="_JBUKsKhHEeO0Haj3z6o3PQ" elementId="org.eclipse.rap.e4.demo.part.3" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.NLSSamplePart" label="%part.label.3" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/report_user.png">
+                <menus xmi:id="_4EurEOGcEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.menu.3">
+                  <tags>ViewMenu</tags>
+                  <children xsi:type="menu:DirectMenuItem" xmi:id="_4nG_YOGcEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.directmenuitem.2" label="%directmenuitem.label.3" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+                </menus>
+                <toolbar xmi:id="_6O4mwOGiEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.toolbar.2">
+                  <tags>ContentArea</tags>
+                  <children xsi:type="menu:DirectToolItem" xmi:id="_7pm4UOGiEeObqJp-_0s5uA" elementId="org.eclipse.rap.e4.demo.directtoolitem.2" label="%directtoolitem.label.2" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+                </toolbar>
+              </children>
+            </children>
+          </children>
+          <children xsi:type="basic:PartSashContainer" xmi:id="_gYBKQKLgEeSGUftsJTPCBQ" elementId="org.eclipse.rap.e4.demo.partsashcontainer.1" containerData="100" horizontal="true">
+            <children xsi:type="basic:Part" xmi:id="_iOPsEKLgEeSGUftsJTPCBQ" elementId="org.eclipse.rap.e4.demo.part.4" containerData="200" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.SimpleTest" label="Simple Lower Part Right" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/door_in.png"/>
+            <children xsi:type="basic:PartStack" xmi:id="_izBNEKLgEeSGUftsJTPCBQ" elementId="org.eclipse.rap.e4.demo.partstack.2" containerData="400">
+              <children xsi:type="basic:Part" xmi:id="_16In4KLgEeSGUftsJTPCBQ" elementId="org.eclipse.rap.e4.demo.part.5" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.SimpleTest" label="Simple Lower Right" iconURI="platform:/plugin/org.eclipse.rap.e4.demo/icons/disk.png"/>
+            </children>
+          </children>
+        </children>
+      </children>
+      <children xsi:type="advanced:Perspective" xmi:id="_ffRowBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.perspective.1">
+        <children xsi:type="basic:PartStack" xmi:id="_vVprkBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.partstack.3">
+          <children xsi:type="advanced:Placeholder" xmi:id="_zhYFIBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.placeholder.1" ref="_hixKgBqfEeW5c6mkiizldg"/>
+        </children>
+      </children>
+    </children>
+    <mainMenu xmi:id="_wk6tQKhGEeO0Haj3z6o3PQ" elementId="org.eclipse.rap.e4.demo.menu.0">
+      <children xsi:type="menu:Menu" xmi:id="_xXHmQKhGEeO0Haj3z6o3PQ" elementId="org.eclipse.rap.e4.demo.menu.1" label="%menu.label.1">
+        <children xsi:type="menu:DirectMenuItem" xmi:id="_y5diwKhGEeO0Haj3z6o3PQ" elementId="org.eclipse.rap.e4.demo.directmenuitem.0" label="%directmenuitem.label.1" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+        <children xsi:type="menu:HandledMenuItem" xmi:id="_gD30kKJDEeSqSpaGLeFO-g" elementId="org.eclipse.rap.e4.demo.handledmenuitem.0" label="%handledmenuitem.label.1" command="_Zs-j8KJDEeSqSpaGLeFO-g"/>
+      </children>
+      <children xsi:type="menu:Menu" xmi:id="_-cK-wBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.menu.perspectives" label="Perspectives">
+        <children xsi:type="menu:DirectMenuItem" xmi:id="_AHvvwBqgEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.directmenuitem.toggleperspectives" label="Toggle Perspectives" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.SwitchPerspectives"/>
+      </children>
+    </mainMenu>
+    <sharedElements xsi:type="basic:Part" xmi:id="_hixKgBqfEeW5c6mkiizldg" elementId="org.eclipse.rap.e4.demo.part.asharedpart" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.parts.SharedPart" label="A shared part"/>
+    <trimBars xmi:id="_svgAANdbEeOAKaBhrzDgEg" elementId="org.eclipse.rap.e4.demo.trimbar.0">
+      <children xsi:type="menu:ToolBar" xmi:id="_uOnCUNdbEeOAKaBhrzDgEg" elementId="org.eclipse.rap.e4.demo.toolbar.0">
+        <children xsi:type="menu:DirectToolItem" xmi:id="_wqJQoNdbEeOAKaBhrzDgEg" elementId="org.eclipse.rap.e4.demo.directtoolitem.0" label="%directmenuitem.label.1" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler"/>
+      </children>
+    </trimBars>
+  </children>
+  <handlers xmi:id="_bbwZ8KJDEeSqSpaGLeFO-g" elementId="org.eclipse.rap.e4.demo.handler.0" contributionURI="bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.handlers.HelloWorldHandler" command="_Zs-j8KJDEeSqSpaGLeFO-g"/>
+  <rootContext xmi:id="_-j-tkKBNEeODEs7-bWqIxA" elementId="org.eclipse.ui.contexts.dialogAndWindow" name="In Dialog and Windows">
+    <children xmi:id="_-j-tkaBNEeODEs7-bWqIxA" elementId="org.eclipse.ui.contexts.window" name="In Windows"/>
+    <children xmi:id="_-j-tkqBNEeODEs7-bWqIxA" elementId="org.eclipse.ui.contexts.dialog" name="In Dialogs"/>
+  </rootContext>
+  <commands xmi:id="_Zs-j8KJDEeSqSpaGLeFO-g" elementId="org.eclipse.rap.e4.demo.command.0" commandName="%command.commandname.1"/>
+  <addons xmi:id="_-j-GgqBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/>
+  <addons xmi:id="_-j-Gg6BNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/>
+  <addons xmi:id="_-j-GhKBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/>
+  <addons xmi:id="_-j-GhaBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.workbench.commands.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.CommandProcessingAddon"/>
+  <addons xmi:id="_-j-GhqBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.workbench.handler.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon"/>
+  <addons xmi:id="_-j-Gh6BNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.workbench.contexts.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.ContextProcessingAddon"/>
+  <addons xmi:id="_-j-GiKBNEeODEs7-bWqIxA" elementId="org.eclipse.e4.ui.workbench.bindings.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench.swt/org.eclipse.e4.ui.workbench.swt.util.BindingProcessingAddon"/>
+</application:Application>
diff --git a/examples/org.eclipse.rap.e4.demo/META-INF/MANIFEST.MF b/examples/org.eclipse.rap.e4.demo/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8570dca
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0

+Bundle-ManifestVersion: 2

+Bundle-Name: Demo

+Bundle-SymbolicName: org.eclipse.rap.e4.demo

+Bundle-Version: 1.0.0.qualifier

+Require-Bundle: org.eclipse.rap.rwt;bundle-version="[3.0.0,4.0.0)",

+ org.eclipse.rap.e4;bundle-version="0.9.0",

+ org.eclipse.e4.core.di,

+ org.eclipse.e4.core.di.extensions,

+ org.eclipse.rap.jface,

+ org.eclipse.e4.core.services,

+ org.eclipse.e4.ui.di,

+ org.eclipse.equinox.common,

+ org.eclipse.e4.ui.workbench;bundle-version="1.1.0",

+ org.eclipse.e4.ui.model.workbench

+Service-Component: OSGI-INF/contribution.xml

+Import-Package: javax.annotation;version="1.2.0",

+ javax.inject;version="1.0.0"

diff --git a/examples/org.eclipse.rap.e4.demo/OSGI-INF/contribution.xml b/examples/org.eclipse.rap.e4.demo/OSGI-INF/contribution.xml
new file mode 100644
index 0000000..b89fdc9
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/OSGI-INF/contribution.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="BasicApplication">
+   <implementation class="org.eclipse.rap.e4.demo.BasicApplication"/>
+   <service>
+      <provide interface="org.eclipse.rap.rwt.application.ApplicationConfiguration"/>
+   </service>
+</scr:component>
diff --git a/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle.properties b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..ab48e42
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,17 @@
+trimmedwindow.label.1 = RAP on Eclipse 4
+part.label.1 = Event Tests
+part.label.2 = Preference Test
+part.label.3 = NLS Test
+menu.label.1 = File
+directmenuitem.label.1 = Hello World
+
+NLSSamplePart_currentLangLabel = Current Language:
+NLSSamplePart_updateLangLabel = New language:
+NLSSamplePart_updateLangButton = Apply
+
+directtoolitem.label.1 = TB-Item
+directmenuitem.label.2 = Hello World
+directmenuitem.label.3 = Hello extra
+directtoolitem.label.2 = Hello World
+handledmenuitem.label.1 = Hello World Command
+command.commandname.1 = Hello World Command
diff --git a/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_de.properties b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_de.properties
new file mode 100644
index 0000000..c729f8b
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_de.properties
@@ -0,0 +1,17 @@
+trimmedwindow.label.1 = RAP auf Eclipse 4
+part.label.1 = Ereignis Tests
+part.label.2 = Präferenzen Test
+part.label.3 = Übersetzungs Test
+menu.label.1 = Datei
+directmenuitem.label.1 = Hallo Welt
+
+NLSSamplePart_currentLangLabel = Aktuelle Sprache:
+NLSSamplePart_updateLangLabel = Neue Sprache:
+NLSSamplePart_updateLangButton = Anwenden
+
+directtoolitem.label.1 = TB-Element
+directmenuitem.label.2 = Hallo Welt
+directmenuitem.label.3 = Hallo Extra
+directtoolitem.label.2 = Hallo Welt
+handledmenuitem.label.1 = Hallo Welt Kommando
+command.commandname.1 = Hallo Welt Kommando
diff --git a/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_en.properties b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_en.properties
new file mode 100644
index 0000000..c5c23cf
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/OSGI-INF/l10n/bundle_en.properties
@@ -0,0 +1,10 @@
+trimmedwindow.label.1 = RAP on Eclipse 4
+part.label.1 = Event Tests
+part.label.2 = Preference Test
+part.label.3 = NLS Test
+menu.label.1 = File
+directmenuitem.label.1 = Hello World
+
+NLSSamplePart_currentLangLabel = Current Language:
+NLSSamplePart_updateLangLabel = New language:
+NLSSamplePart_updateLangButton = Apply
\ No newline at end of file
diff --git a/examples/org.eclipse.rap.e4.demo/build.properties b/examples/org.eclipse.rap.e4.demo/build.properties
new file mode 100644
index 0000000..5857864
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/build.properties
@@ -0,0 +1,6 @@
+source.. = src/

+output.. = bin/

+bin.includes = META-INF/,\

+               OSGI-INF/,\

+               .\

+               Application.e4xmi

diff --git a/examples/org.eclipse.rap.e4.demo/dev_org.eclipse.rap.e4.demo.launch b/examples/org.eclipse.rap.e4.demo/dev_org.eclipse.rap.e4.demo.launch
new file mode 100644
index 0000000..9a99f3c
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/dev_org.eclipse.rap.e4.demo.launch
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.rap.ui.launch.RAPLauncher">
+<booleanAttribute key="append.args" value="true"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="false"/>
+<booleanAttribute key="automaticValidate" value="true"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="false"/>
+<booleanAttribute key="clearws" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/dev_org.eclipse.rap.e4.demo"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="default_auto_start" value="true"/>
+<intAttribute key="default_start_level" value="4"/>
+<booleanAttribute key="includeOptional" value="false"/>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -console -consolelog"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dorg.eclipse.equinox.http.jetty.log.stderr.threshold=info"/>
+<stringAttribute key="org.eclipse.rap.launch.browserMode" value="EXTERNAL"/>
+<stringAttribute key="org.eclipse.rap.launch.contextpath" value="/"/>
+<stringAttribute key="org.eclipse.rap.launch.dataLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.rap.tools.launch/dev_org.eclipse.rap.e4.demo"/>
+<booleanAttribute key="org.eclipse.rap.launch.developmentMode" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.openBrowser" value="true"/>
+<intAttribute key="org.eclipse.rap.launch.port" value="10080"/>
+<stringAttribute key="org.eclipse.rap.launch.servletPath" value="/hello"/>
+<intAttribute key="org.eclipse.rap.launch.sessionTimeout" value="0"/>
+<booleanAttribute key="org.eclipse.rap.launch.terminatePrevious" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.useDefaultDataLocation" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.useManualContextPath" value="false"/>
+<booleanAttribute key="org.eclipse.rap.launch.useManualPort" value="false"/>
+<booleanAttribute key="org.eclipse.rap.launch.useSessionTimeout" value="false"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="target_bundles" value="com.ibm.icu@default:default,javax.annotation@default:default,javax.inject@default:default,javax.servlet@default:default,javax.xml@default:default,org.apache.commons.jxpath@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.e4.core.contexts@default:default,org.eclipse.e4.core.di.annotations@default:default,org.eclipse.e4.core.di.extensions@default:default,org.eclipse.e4.core.di@default:default,org.eclipse.e4.core.services@default:default,org.eclipse.e4.emf.xpath@default:default,org.eclipse.e4.ui.di@default:default,org.eclipse.e4.ui.model.workbench@default:default,org.eclipse.e4.ui.services@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.console@default:default,org.eclipse.equinox.ds@1:true,org.eclipse.equinox.event@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.util@default:default,org.eclipse.jetty.continuation@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.eclipse.rap.jface.databinding@default:default,org.eclipse.rap.jface@default:default,org.eclipse.rap.rwt.osgi@default:default,org.eclipse.rap.rwt@default:default"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfigArea" value="true"/>
+<stringAttribute key="workspace_bundles" value="org.eclipse.e4.core.commands@default:default,org.eclipse.e4.ui.bindings@default:default,org.eclipse.e4.ui.workbench.addons.swt@default:default,org.eclipse.e4.ui.workbench.renderers.swt@default:default,org.eclipse.e4.ui.workbench.swt@default:default,org.eclipse.e4.ui.workbench@default:default,org.eclipse.rap.e4.demo@default:default,org.eclipse.rap.e4@default:default"/>
+</launchConfiguration>
diff --git a/examples/org.eclipse.rap.e4.demo/icons/disk.png b/examples/org.eclipse.rap.e4.demo/icons/disk.png
new file mode 100644
index 0000000..99d532e
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/disk.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/icons/door_in.png b/examples/org.eclipse.rap.e4.demo/icons/door_in.png
new file mode 100644
index 0000000..41676a0
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/door_in.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/icons/folder_user.png b/examples/org.eclipse.rap.e4.demo/icons/folder_user.png
new file mode 100644
index 0000000..f021c3e
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/folder_user.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/icons/report_user.png b/examples/org.eclipse.rap.e4.demo/icons/report_user.png
new file mode 100644
index 0000000..7766edd
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/report_user.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/icons/user_add.png b/examples/org.eclipse.rap.e4.demo/icons/user_add.png
new file mode 100644
index 0000000..deae99b
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/user_add.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/icons/user_delete.png b/examples/org.eclipse.rap.e4.demo/icons/user_delete.png
new file mode 100644
index 0000000..acbb563
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/icons/user_delete.png
Binary files differ
diff --git a/examples/org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.launch b/examples/org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.launch
new file mode 100644
index 0000000..39cd505
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.launch
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.rap.ui.launch.RAPLauncher">
+<booleanAttribute key="append.args" value="true"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="false"/>
+<booleanAttribute key="automaticValidate" value="true"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="false"/>
+<booleanAttribute key="clearws" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/org.eclipse.rap.e4.demo"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="default_auto_start" value="true"/>
+<intAttribute key="default_start_level" value="4"/>
+<booleanAttribute key="includeOptional" value="false"/>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -console -consolelog"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dorg.eclipse.equinox.http.jetty.log.stderr.threshold=info"/>
+<stringAttribute key="org.eclipse.rap.launch.browserMode" value="EXTERNAL"/>
+<stringAttribute key="org.eclipse.rap.launch.contextpath" value="/"/>
+<stringAttribute key="org.eclipse.rap.launch.dataLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.rap.tools.launch/org.eclipse.rap.e4.demo"/>
+<booleanAttribute key="org.eclipse.rap.launch.developmentMode" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.openBrowser" value="true"/>
+<intAttribute key="org.eclipse.rap.launch.port" value="10080"/>
+<stringAttribute key="org.eclipse.rap.launch.servletPath" value="/hello"/>
+<intAttribute key="org.eclipse.rap.launch.sessionTimeout" value="0"/>
+<booleanAttribute key="org.eclipse.rap.launch.terminatePrevious" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.useDefaultDataLocation" value="true"/>
+<booleanAttribute key="org.eclipse.rap.launch.useManualContextPath" value="false"/>
+<booleanAttribute key="org.eclipse.rap.launch.useManualPort" value="false"/>
+<booleanAttribute key="org.eclipse.rap.launch.useSessionTimeout" value="false"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="target_bundles" value="com.ibm.icu@default:default,javax.annotation@default:default,javax.inject@default:default,javax.servlet@default:default,javax.xml@default:default,org.apache.commons.jxpath@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.e4.core.commands@default:default,org.eclipse.e4.core.contexts@default:default,org.eclipse.e4.core.di.annotations@default:default,org.eclipse.e4.core.di.extensions@default:default,org.eclipse.e4.core.di@default:default,org.eclipse.e4.core.services@default:default,org.eclipse.e4.emf.xpath@default:default,org.eclipse.e4.ui.bindings@default:default,org.eclipse.e4.ui.di@default:default,org.eclipse.e4.ui.model.workbench@default:default,org.eclipse.e4.ui.services@default:default,org.eclipse.e4.ui.workbench.addons.swt@default:default,org.eclipse.e4.ui.workbench.renderers.swt@default:default,org.eclipse.e4.ui.workbench.swt@default:default,org.eclipse.e4.ui.workbench@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.console@default:default,org.eclipse.equinox.ds@1:true,org.eclipse.equinox.event@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.util@default:default,org.eclipse.jetty.continuation@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.eclipse.rap.e4@default:default,org.eclipse.rap.jface.databinding@default:default,org.eclipse.rap.jface@default:default,org.eclipse.rap.rwt.osgi@default:default,org.eclipse.rap.rwt@default:default"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfigArea" value="true"/>
+<stringAttribute key="workspace_bundles" value="org.eclipse.rap.e4.demo"/>
+</launchConfiguration>
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/BasicApplication.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/BasicApplication.java
new file mode 100644
index 0000000..65ab492
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/BasicApplication.java
@@ -0,0 +1,28 @@
+package org.eclipse.rap.e4.demo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.rap.e4.E4ApplicationConfig;
+import org.eclipse.rap.e4.E4EntryPointFactory;
+import org.eclipse.rap.rwt.application.Application;
+import org.eclipse.rap.rwt.application.ApplicationConfiguration;
+import org.eclipse.rap.rwt.application.Application.OperationMode;
+import org.eclipse.rap.rwt.client.WebClient;
+
+
+public class BasicApplication implements ApplicationConfiguration {
+
+    public void configure(Application application) {
+        Map<String, String> properties = new HashMap<String, String>();
+        properties.put(WebClient.PAGE_TITLE, "Hello e4 RAP");
+        application.addEntryPoint("/hello", new E4EntryPointFactory(
+        		E4ApplicationConfig.create(
+        				"platform:/plugin/org.eclipse.rap.e4.demo/Application.e4xmi",
+        				"bundleclass://org.eclipse.rap.e4.demo/org.eclipse.rap.e4.demo.lifecycle.LoginLifcecycle"
+        			)
+        		), properties);
+        application.setOperationMode( OperationMode.SWT_COMPATIBILITY );
+    }
+
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/HelloWorldHandler.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/HelloWorldHandler.java
new file mode 100644
index 0000000..8f6ece1
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/HelloWorldHandler.java
@@ -0,0 +1,16 @@
+package org.eclipse.rap.e4.demo.handlers;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+public class HelloWorldHandler {
+	@Execute
+	public void hello(Shell s) {
+		MessageBox b = new MessageBox(s,SWT.ICON_INFORMATION);
+		b.setText("Hello e4");
+		b.setMessage("e4 and RAP are a perfect match!!");
+		b.open();
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/SwitchPerspectives.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/SwitchPerspectives.java
new file mode 100644
index 0000000..65f6673
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/handlers/SwitchPerspectives.java
@@ -0,0 +1,16 @@
+package org.eclipse.rap.e4.demo.handlers;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+
+public class SwitchPerspectives {
+	@Execute
+	void switchPerspective(EPartService partService, MPerspective perspective) {
+		if( perspective.getElementId().equals("org.eclipse.rap.e4.demo.perspective.0") ) {
+			partService.switchPerspective((MPerspective) perspective.getParent().getChildren().get(1));
+		} else {
+			partService.switchPerspective((MPerspective) perspective.getParent().getChildren().get(0));
+		}		
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/lifecycle/LoginLifcecycle.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/lifecycle/LoginLifcecycle.java
new file mode 100644
index 0000000..baa3cbb
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/lifecycle/LoginLifcecycle.java
@@ -0,0 +1,90 @@
+package org.eclipse.rap.e4.demo.lifecycle;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+@SuppressWarnings("restriction")
+public class LoginLifcecycle {
+	@PostContextCreate
+	boolean login(Display d) {
+		final AtomicBoolean rv = new AtomicBoolean(false);
+		final Shell s = new Shell(d);
+		s.setText("Login");
+		s.setLayout(new GridLayout(2, false));
+		
+		{
+			Label l = new Label(s, SWT.NONE);
+			l.setText("Username");
+			
+			Text t = new Text(s, SWT.BORDER);
+			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		}
+		
+		{
+			Label l = new Label(s, SWT.NONE);
+			l.setText("Password");
+			
+			Text t = new Text(s, SWT.BORDER);
+			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		}
+		
+		{
+			Composite buttonContainer = new Composite(s, SWT.NONE);
+			buttonContainer.setLayout(new GridLayout(2, true));
+			buttonContainer.setLayoutData(new GridData(SWT.TRAIL, SWT.CENTER, false, false, 2, 1));
+
+			{
+				Button b = new Button(buttonContainer, SWT.PUSH);
+				b.setText("Abort");
+				b.addSelectionListener(new SelectionAdapter() {
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						rv.set(false);
+						s.dispose();
+					}
+				});
+			}
+
+			{
+				Button b = new Button(buttonContainer, SWT.PUSH);
+				b.setText("Login");
+				b.addSelectionListener(new SelectionAdapter() {
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						rv.set(true);
+						s.dispose();
+					}
+				});
+			}
+		}
+		s.pack();
+		s.setSize(300, s.getSize().y + 10);
+		Rectangle bounds = d.getPrimaryMonitor().getBounds();
+		
+		Point size = s.getSize();
+		s.setLocation(bounds.width / 2 - size.x / 2, bounds.height / 2 - size.y / 2);
+		
+		s.open();
+		while( !s.isDisposed() && ! d.isDisposed() ) {
+			if( ! d.readAndDispatch() ) {
+				d.sleep();
+			}
+		}
+		
+		return rv.get();
+	}
+}
\ No newline at end of file
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/EventSamplePart.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/EventSamplePart.java
new file mode 100644
index 0000000..87f10a3
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/EventSamplePart.java
@@ -0,0 +1,91 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.extensions.EventTopic;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.di.UISynchronize;
+import org.eclipse.jface.viewers.ListViewer;
+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.Composite;
+import org.eclipse.swt.widgets.Group;
+
+@SuppressWarnings("restriction")
+public class EventSamplePart {
+	@Inject
+	IEventBroker broker;
+	
+	@Inject
+	UISynchronize uiSync;
+	
+	private ListViewer listViewer;
+	
+	@PostConstruct
+	void init(Composite parent) {
+		parent.setLayout(new GridLayout());
+
+		listViewer = new ListViewer(parent);
+		listViewer.getControl().setLayoutData(
+				new GridData(GridData.FILL_BOTH));
+		
+		createSendGroup(parent, "EventTopic");
+		createSendGroup(parent, "UIEventTopic");
+	}
+
+	private void createSendGroup(Composite parent, final String topicType) {
+		Group g = new Group(parent, SWT.NONE);
+		g.setText("@" + topicType);
+		g.setLayout(new GridLayout(2, true));
+		g.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		Button b = new Button(g, SWT.PUSH);
+		b.setText("Sync sending");
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				broker.send("rape4/" + topicType, "@"+topicType+" - Event at " + System.currentTimeMillis());
+			}
+		});
+		b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		b = new Button(g, SWT.PUSH);
+		b.setText("Async sending");
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				broker.post("rape4/" + topicType, "@"+topicType+" - Event at " + System.currentTimeMillis());
+			}
+		});
+		b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+	}
+	
+	@Inject
+	@Optional
+	void receiveEvent(@EventTopic("rape4/EventTopic") final String eventData) {
+		if( listViewer.getControl().getDisplay().getThread() == Thread.currentThread() ) {
+			listViewer.add(eventData);
+		} else {
+			uiSync.syncExec(new Runnable() {
+				
+				@Override
+				public void run() {
+					listViewer.add(eventData); 
+				}
+			});
+		}
+	}
+	
+	@Inject
+	@Optional
+	void receiveUIEvent(@UIEventTopic("rape4/UIEventTopic") final String eventData) {
+		listViewer.add(eventData);
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSMessages.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSMessages.java
new file mode 100644
index 0000000..5fcc720
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSMessages.java
@@ -0,0 +1,10 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import org.eclipse.e4.core.services.nls.Message;
+
+@Message
+public class NLSMessages {
+	public String NLSSamplePart_currentLangLabel;
+	public String NLSSamplePart_updateLangLabel;
+	public String NLSSamplePart_updateLangButton;
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSSamplePart.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSSamplePart.java
new file mode 100644
index 0000000..ba96a79
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/NLSSamplePart.java
@@ -0,0 +1,61 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import java.util.Locale;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.services.nls.ILocaleChangeService;
+import org.eclipse.e4.core.services.nls.Translation;
+import org.eclipse.e4.core.services.translation.TranslationService;
+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.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class NLSSamplePart {
+	private Label currentLangLabel;
+	private Label currentLangValue;
+	private Label updateLangLabel;
+	private Text updateLangValue;
+	private Button updateLangButton;
+	
+	@Inject
+	ILocaleChangeService localeService;
+
+	@Inject
+	public NLSSamplePart(Composite parent) {
+		parent.setLayout(new GridLayout(3, false));
+		
+		currentLangLabel = new Label(parent, SWT.NONE);
+		currentLangValue = new Label(parent, SWT.NONE);
+		currentLangValue.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false,2,1));
+		
+		updateLangLabel = new Label(parent, SWT.NONE);
+		updateLangValue = new Text(parent, SWT.BORDER);
+		updateLangButton = new Button(parent, SWT.PUSH);
+		updateLangButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				localeService.changeApplicationLocale(updateLangValue.getText());
+			}
+		});
+	}
+	
+	@Inject
+	public void setMessages(@Translation NLSMessages messages, @Named(TranslationService.LOCALE) Locale locale) {
+		currentLangLabel.setText(messages.NLSSamplePart_currentLangLabel);
+		currentLangValue.setText(locale.toString());
+		
+		updateLangLabel.setText(messages.NLSSamplePart_updateLangLabel);
+		updateLangValue.setText(locale.toString());
+		updateLangButton.setText(messages.NLSSamplePart_updateLangButton);
+		
+		currentLangLabel.getParent().layout(true);
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/PreferenceSamplePart.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/PreferenceSamplePart.java
new file mode 100644
index 0000000..05d0879
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/PreferenceSamplePart.java
@@ -0,0 +1,91 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.di.extensions.Preference;
+import org.eclipse.rap.e4.preferences.EPreference;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+
+@SuppressWarnings({ "restriction", "serial" })
+public class PreferenceSamplePart {
+
+	private Label colorLabel;
+	private Color currentColor;
+
+	@Optional
+	@Inject
+	@Preference
+	EPreference prefs;
+
+	@Inject
+	public PreferenceSamplePart(Composite parent) {
+		parent.setLayout(new GridLayout(2, false));
+
+		Label l1 = new Label(parent, SWT.NONE);
+		l1.setText("Current Value:");
+
+		colorLabel = new Label(parent, SWT.NONE);
+		colorLabel.setText("-");
+
+		Label l2 = new Label(parent, SWT.NONE);
+		l2.setText("Color:");
+
+		final Text t = new Text(parent, SWT.BORDER);
+		Listener listener = new Listener() {
+			@Override
+			public void handleEvent(Event event) {
+				prefs.setString("colorPref", t.getText());
+			}
+		};
+		t.addListener(SWT.DefaultSelection, listener);
+		t.addListener(SWT.FocusOut, listener);
+		t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+	}
+
+	@Inject
+	public void updatePreference(@Optional @Preference("colorPref") String v) {
+		if (v == null) {
+			return;
+		}
+		colorLabel.setText(v);
+		RGB rgb = toRGB(v);
+		Color c = rgb != null ? new Color(colorLabel.getDisplay(), rgb) : null;
+		colorLabel.setBackground(c);
+		if (currentColor != null) {
+			currentColor.dispose();
+		}
+		currentColor = c;
+
+		colorLabel.getParent().layout(true);
+	}
+
+	private static RGB toRGB(String hexcolor) {
+		try {
+			if (hexcolor.length() == 3) {
+				int r = Integer.parseInt(hexcolor.substring(0, 1), 16) * 17;
+				int g = Integer.parseInt(hexcolor.substring(1, 2), 16) * 17;
+				int b = Integer.parseInt(hexcolor.substring(2, 3), 16) * 17;
+				return new RGB(r, g, b);
+			}
+			if (hexcolor.length() == 6) {
+				int r = Integer.parseInt(hexcolor.substring(0, 2), 16);
+				int g = Integer.parseInt(hexcolor.substring(2, 4), 16);
+				int b = Integer.parseInt(hexcolor.substring(4, 6), 16);
+				return new RGB(r, g, b);
+			}
+		} catch (NumberFormatException e) {
+			// return fall back
+		}
+		return null;
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SharedPart.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SharedPart.java
new file mode 100644
index 0000000..49e7758
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SharedPart.java
@@ -0,0 +1,24 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import javax.annotation.PostConstruct;
+
+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.Text;
+
+public class SharedPart {
+	@PostConstruct
+	void init(Composite parent) {
+		parent.setLayout(new GridLayout(2, false));
+		
+		Label label = new Label(parent, SWT.NONE);
+		label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
+		label.setText("A sample");
+		
+		Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+	}
+}
diff --git a/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SimpleTest.java b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SimpleTest.java
new file mode 100644
index 0000000..08949af
--- /dev/null
+++ b/examples/org.eclipse.rap.e4.demo/src/org/eclipse/rap/e4/demo/parts/SimpleTest.java
@@ -0,0 +1,18 @@
+package org.eclipse.rap.e4.demo.parts;
+
+import javax.annotation.PostConstruct;
+
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+public class SimpleTest {
+	@PostConstruct
+	void init(MPart part, Composite parent) {
+		parent.setLayout(new GridLayout());
+		Label l = new Label(parent,SWT.NONE);
+		l.setText(part.getLabel());
+	}
+}
diff --git a/features/org.eclipse.rap.e4.base.feature/.project b/features/org.eclipse.rap.e4.base.feature/.project
new file mode 100644
index 0000000..c18fbeb
--- /dev/null
+++ b/features/org.eclipse.rap.e4.base.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.rap.e4.base.feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.rap.e4.base.feature/build.properties b/features/org.eclipse.rap.e4.base.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/features/org.eclipse.rap.e4.base.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.eclipse.rap.e4.base.feature/feature.xml b/features/org.eclipse.rap.e4.base.feature/feature.xml
new file mode 100644
index 0000000..b683392
--- /dev/null
+++ b/features/org.eclipse.rap.e4.base.feature/feature.xml
@@ -0,0 +1,390 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.rap.e4.base.feature"
+      label="Feature"
+      version="0.9.0.qualifier">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <plugin
+         id="org.eclipse.e4.core.di"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+         
+   <plugin
+         id="org.eclipse.e4.core.di.annotations"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.contexts"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.extensions"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.services"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.services"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.jface.databinding"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.jface"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.rwt.osgi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.rwt"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.di"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.ibm.icu"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.annotation"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.inject"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.servlet"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.xml"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.felix.gogo.command"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.felix.gogo.runtime"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.felix.gogo.shell"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.commands"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.contenttype"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.databinding.observable"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.databinding.property"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.databinding"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.expressions"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.jobs"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.core.runtime"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.model.workbench"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.common"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.change"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.xmi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.app"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.common"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.console"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.ds"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.event"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.http.jetty"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.http.servlet"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.preferences"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.registry"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.equinox.util"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.continuation"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.http"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.io"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.security"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.server"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.servlet"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.jetty.util"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.osgi.services"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.osgi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+         
+	<plugin
+         id="org.eclipse.e4.emf.xpath"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+	<plugin
+         id="org.apache.commons.jxpath"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+         
+</feature>
diff --git a/features/org.eclipse.rap.e4.base.feature/pom.xml b/features/org.eclipse.rap.e4.base.feature/pom.xml
new file mode 100644
index 0000000..33a83e0
--- /dev/null
+++ b/features/org.eclipse.rap.e4.base.feature/pom.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.rap.e4.base.feature</artifactId>
+  <version>0.9.0-SNAPSHOT</version>
+  <packaging>eclipse-feature</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.base-releng</artifactId>
+    <relativePath>../../releng/releng-base/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+</project>
diff --git a/features/org.eclipse.rap.e4.target.feature/.project b/features/org.eclipse.rap.e4.target.feature/.project
new file mode 100644
index 0000000..d11edd3
--- /dev/null
+++ b/features/org.eclipse.rap.e4.target.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.rap.e4.target.feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.rap.e4.target.feature/build.properties b/features/org.eclipse.rap.e4.target.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/features/org.eclipse.rap.e4.target.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.eclipse.rap.e4.target.feature/feature.xml b/features/org.eclipse.rap.e4.target.feature/feature.xml
new file mode 100644
index 0000000..251ced7
--- /dev/null
+++ b/features/org.eclipse.rap.e4.target.feature/feature.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.rap.e4.target.feature"
+      label="Feature"
+      version="0.9.0.qualifier">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <requires>
+      <import feature="org.eclipse.rap.equinox.target.feature" version="3.0.0" match="compatible"/>
+   </requires>
+
+   <plugin
+         id="org.eclipse.e4.core.contexts"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.contexts.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.extensions"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.extensions.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.annotations"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.di.annotations.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.services"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.services.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.services"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.services.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.di"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.di.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.annotation"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.annotation.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.inject"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="javax.inject.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.commands"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.core.commands.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.model.workbench"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.model.workbench.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.common"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.common.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.change"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.change.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.xmi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.xmi.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.emf.ecore.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.bindings"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.bindings.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.renderers.swt"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.renderers.swt.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.swt"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.swt.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.addons.swt"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.workbench.addons.swt.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.e4"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.rap.e4.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.emf.xpath"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.emf.xpath.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.commons.jxpath"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.apache.commons.jxpath.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.rap.e4.target.feature/pom.xml b/features/org.eclipse.rap.e4.target.feature/pom.xml
new file mode 100644
index 0000000..ddfa9ed
--- /dev/null
+++ b/features/org.eclipse.rap.e4.target.feature/pom.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+
+  <groupId>org.eclipse.rap.e4</groupId>
+  <artifactId>org.eclipse.rap.e4.target.feature</artifactId>
+  <packaging>eclipse-feature</packaging>
+
+  <parent>
+    <groupId>org.eclipse.rap.e4</groupId>
+    <artifactId>org.eclipse.rap.e4.target-releng</artifactId>
+    <relativePath>../../releng/releng-target/pom.xml</relativePath>
+    <version>0.9.0-SNAPSHOT</version>
+  </parent>
+
+</project>