Merge remote-tracking branch 'origin/releases/5.2.x' into releases/6.0.x
diff --git a/org.eclipse.scout.dev.jetty.test.affix/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.dev.jetty.test.affix/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.dev.jetty.test.affix/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.dev.jetty.test.affix/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.dev.jetty.test.affix/pom.xml b/org.eclipse.scout.dev.jetty.test.affix/pom.xml
index 32dc6f0..2e0568c 100644
--- a/org.eclipse.scout.dev.jetty.test.affix/pom.xml
+++ b/org.eclipse.scout.dev.jetty.test.affix/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.dev.jetty.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.dev.jetty.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.dev.jetty.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.dev.jetty.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.dev.jetty.test/pom.xml b/org.eclipse.scout.dev.jetty.test/pom.xml
index 52f66bf..745f4d3 100644
--- a/org.eclipse.scout.dev.jetty.test/pom.xml
+++ b/org.eclipse.scout.dev.jetty.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.dev.jetty/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.dev.jetty/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.dev.jetty/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.dev.jetty/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.dev.jetty/pom.xml b/org.eclipse.scout.dev.jetty/pom.xml
index a81b979..3b9ec82 100644
--- a/org.eclipse.scout.dev.jetty/pom.xml
+++ b/org.eclipse.scout.dev.jetty/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.jaxws.apt/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.jaxws.apt/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.jaxws.apt/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.jaxws.apt/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.jaxws.apt/pom.xml b/org.eclipse.scout.jaxws.apt/pom.xml
index 7aeb3eb..42e1ffd 100644
--- a/org.eclipse.scout.jaxws.apt/pom.xml
+++ b/org.eclipse.scout.jaxws.apt/pom.xml
@@ -11,7 +11,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.jaxws.apt/src/main/java/org/eclipse/scout/jaxws/apt/internal/EntryPointDefinition.java b/org.eclipse.scout.jaxws.apt/src/main/java/org/eclipse/scout/jaxws/apt/internal/EntryPointDefinition.java
index 831ce55..db608bd 100644
--- a/org.eclipse.scout.jaxws.apt/src/main/java/org/eclipse/scout/jaxws/apt/internal/EntryPointDefinition.java
+++ b/org.eclipse.scout.jaxws.apt/src/main/java/org/eclipse/scout/jaxws/apt/internal/EntryPointDefinition.java
@@ -30,8 +30,8 @@
 import org.eclipse.scout.jaxws.apt.internal.util.AnnotationUtil;
 import org.eclipse.scout.jaxws.apt.internal.util.AptUtil;
 import org.eclipse.scout.jaxws.apt.internal.util.Assertions;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
 import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
 import org.eclipse.scout.rt.server.jaxws.provider.annotation.Authentication;
 import org.eclipse.scout.rt.server.jaxws.provider.annotation.Authentication.NullAuthenticationMethod;
 import org.eclipse.scout.rt.server.jaxws.provider.annotation.Handler.HandlerType;
diff --git a/org.eclipse.scout.json/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.json/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.json/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.json/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.json/pom.xml b/org.eclipse.scout.json/pom.xml
index 3cb698a..5e80dba 100644
--- a/org.eclipse.scout.json/pom.xml
+++ b/org.eclipse.scout.json/pom.xml
@@ -27,7 +27,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.json/src/main/java/org/json/JSONTokener.java b/org.eclipse.scout.json/src/main/java/org/json/JSONTokener.java
index 5b1f14d..a136996 100644
--- a/org.eclipse.scout.json/src/main/java/org/json/JSONTokener.java
+++ b/org.eclipse.scout.json/src/main/java/org/json/JSONTokener.java
@@ -26,6 +26,7 @@
  * Changes to the original code:
  * -----------------------------
  * - Applied Scout code formatting rules
+ * - Added lenient mode to allow parsing of certain invalid JSON strings (missing null value)
  *
  * Copyright (c) 2015 BSI Business Systems Integration AG.
  */
@@ -70,6 +71,7 @@
 
   /** The input JSON. */
   private final String in;
+  private final boolean lenient;
 
   /**
    * The index of the next character to be returned by {@link #next}. When the input is exhausted, this equals the
@@ -88,6 +90,23 @@
       in = in.substring(1);
     }
     this.in = in;
+    this.lenient = false;
+  }
+
+  /**
+   * @param in
+   *          JSON encoded string. Null is not permitted and will yield a tokener that throws
+   *          {@code NullPointerExceptions} when methods are called.
+   * @param lenient
+   *          allow parsing of invalid JSON strings with missing null values
+   */
+  public JSONTokener(String in, boolean lenient) {
+    // consume an optional byte order mark (BOM) if it exists
+    if (in != null && in.startsWith("\ufeff")) {
+      in = in.substring(1);
+    }
+    this.in = in;
+    this.lenient = lenient;
   }
 
   /**
@@ -287,6 +306,9 @@
     String literal = nextToInternal("{}[]/\\:,=;# \t\f");
 
     if (literal.length() == 0) {
+      if (lenient) {
+        return JSONObject.NULL;
+      }
       throw syntaxError("Expected literal value");
     }
     else if ("null".equalsIgnoreCase(literal)) {
diff --git a/org.eclipse.scout.rt-settings/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt-settings/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt-settings/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt-settings/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt-settings/files/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt-settings/files/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt-settings/files/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt-settings/files/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt-settings/pom.xml b/org.eclipse.scout.rt-settings/pom.xml
index 46779ac..c3c73c9 100644
--- a/org.eclipse.scout.rt-settings/pom.xml
+++ b/org.eclipse.scout.rt-settings/pom.xml
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.client.mobile.test/.classpath b/org.eclipse.scout.rt.client.mobile.test/.classpath
deleted file mode 100644
index b2acffc..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.classpath
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
diff --git a/org.eclipse.scout.rt.client.mobile.test/.project b/org.eclipse.scout.rt.client.mobile.test/.project
deleted file mode 100644
index f7b3706..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>org.eclipse.scout.rt.client.mobile.test</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.m2e.core.maven2Builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.eclipse.m2e.core.maven2Nature</nature>
-	</natures>
-</projectDescription>
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/.jsdtscope b/org.eclipse.scout.rt.client.mobile.test/.settings/.jsdtscope
deleted file mode 100644
index 555a5ca..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/.jsdtscope
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-  <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
-  <classpathentry kind="src" path="src/main/js" excluding="*-module.js"/>
-  <classpathentry kind="lib" path="src/main/resources/WebContent/res" excluding="*-macro.js"/>
-  <classpathentry exported="true" kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
-  <classpathentry kind="output" path=""/>
-</classpath>
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/com.eclipsesource.jshint.ui.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/com.eclipsesource.jshint.ui.prefs
deleted file mode 100644
index 00492d9..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/com.eclipsesource.jshint.ui.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-eclipse.preferences.version=1
-included=src/main/js//*.js\:src/test/js//*.js
-projectSpecificOptions=true
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/de.loskutov.anyedit.AnyEditTools.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/de.loskutov.anyedit.AnyEditTools.prefs
deleted file mode 100644
index 9e00de0..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/de.loskutov.anyedit.AnyEditTools.prefs
+++ /dev/null
@@ -1,18 +0,0 @@
-activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF,.project,*.target
-addNewLine=true
-convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
-eclipse.preferences.version=1
-fixLineDelimiters=true
-ignoreBlankLinesWhenTrimming=false
-inActiveContentFilterList=
-javaTabWidthForJava=true
-org.eclipse.jdt.ui.editor.tab.width=2
-projectPropsEnabled=true
-removeTrailingSpaces=true
-replaceAllSpaces=false
-replaceAllTabs=true
-saveAndAddLine=true
-saveAndConvert=true
-saveAndFixLineDelimiters=true
-saveAndTrim=true
-useModulo4Tabs=true
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.resources.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 13d34f3..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,18 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/client=UTF-8
-encoding//src/main/fixture=UTF-8
-encoding//src/main/java=UTF-8
-encoding//src/main/java-jcl=UTF-8
-encoding//src/main/java-log4j=UTF-8
-encoding//src/main/java-original=UTF-8
-encoding//src/main/js=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/main/shared=UTF-8
-encoding//src/main/webapp=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/js=UTF-8
-encoding//src/test/resources=UTF-8
-encoding//target/generated-sources/annotations=UTF-8
-encoding//target/generated-sources/wsimport=UTF-8
-encoding/<project>=UTF-8
-encoding/files=UTF-8
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.runtime.prefs
deleted file mode 100644
index 5a0ad22..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.core.runtime.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-line.separator=\n
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 7a93103..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,395 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.codeComplete.argumentPrefixes=
-org.eclipse.jdt.core.codeComplete.argumentSuffixes=
-org.eclipse.jdt.core.codeComplete.fieldPrefixes=m_
-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.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=enabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
-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=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-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=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-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=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
-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=enabled
-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=ignore
-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.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=disabled
-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.processAnnotations=disabled
-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=16
-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=16
-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=16
-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=true
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
-org.eclipse.jdt.core.formatter.comment.format_block_comments=false
-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=false
-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=120
-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=true
-org.eclipse.jdt.core.formatter.indentation.size=2
-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=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=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=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=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=do not 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=do not 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=do not 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=do not 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=false
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true
-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=true
-org.eclipse.jdt.core.formatter.lineSplit=240
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
-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=space
-org.eclipse.jdt.core.formatter.tabulation.size=2
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
-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
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index 27aaab4..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,127 +0,0 @@
-cleanup.add_default_serial_version_id=true
-cleanup.add_generated_serial_version_id=false
-cleanup.add_missing_annotations=true
-cleanup.add_missing_deprecated_annotations=false
-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_functional_interfaces=false
-cleanup.convert_to_enhanced_for_loop=false
-cleanup.correct_indentation=true
-cleanup.format_source_code=true
-cleanup.format_source_code_changes_only=false
-cleanup.insert_inferred_type_arguments=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=true
-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=false
-cleanup.qualify_static_member_accesses_with_declaring_class=false
-cleanup.qualify_static_method_accesses_with_declaring_class=false
-cleanup.remove_private_constructors=true
-cleanup.remove_redundant_type_arguments=true
-cleanup.remove_trailing_whitespaces=true
-cleanup.remove_trailing_whitespaces_all=true
-cleanup.remove_trailing_whitespaces_ignore_empty=false
-cleanup.remove_unnecessary_casts=false
-cleanup.remove_unnecessary_nls_tags=false
-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_anonymous_class_creation=false
-cleanup.use_blocks=false
-cleanup.use_blocks_only_for_return_and_throw=false
-cleanup.use_lambda=true
-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.use_type_arguments=false
-cleanup_profile=_Eclipse Scout
-cleanup_settings_version=2
-eclipse.preferences.version=1
-editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
-formatter_profile=_Eclipse Scout
-formatter_settings_version=12
-org.eclipse.jdt.ui.exception.name=e
-org.eclipse.jdt.ui.gettersetter.use.is=true
-org.eclipse.jdt.ui.javadoc=true
-org.eclipse.jdt.ui.keywordthis=false
-org.eclipse.jdt.ui.overrideannotation=true
-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><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 * &lt;h3&gt;{@link ${type_name}}&lt;/h3&gt;\n *\n * @author ${user}\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><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\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><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\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" 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}</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><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * &lt;h3&gt;{@link ${type_name}}&lt;/h3&gt;\n *\n * @author ${user}\n * @since ${date}\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.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.wst.jsdt.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.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.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.wst.jsdt.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=false
-sp_cleanup.add_missing_methods=false
-sp_cleanup.add_missing_nls_tags=false
-sp_cleanup.add_missing_override_annotations=false
-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=false
-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=true
-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/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.core.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.core.prefs
deleted file mode 100644
index 4bab8fd..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.core.prefs
+++ /dev/null
@@ -1,306 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.wst.jsdt.core.compiler.codegen.inlineJsrBytecode=disabled
-org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform=1.2
-org.eclipse.wst.jsdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.wst.jsdt.core.compiler.compliance=1.4
-org.eclipse.wst.jsdt.core.compiler.debug.lineNumber=generate
-org.eclipse.wst.jsdt.core.compiler.debug.localVariable=generate
-org.eclipse.wst.jsdt.core.compiler.debug.sourceFile=generate
-org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier=warning
-org.eclipse.wst.jsdt.core.compiler.problem.deprecation=warning
-org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.wst.jsdt.core.compiler.problem.duplicateLocalVariables=warning
-org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.wst.jsdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.looseVarDecleration=warning
-org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.nullReference=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.optionalSemicolon=warning
-org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.undefinedField=warning
-org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.uninitializedGlobalVariable=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.uninitializedLocalVariable=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedFieldReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedMethodReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedTypeReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.wst.jsdt.core.compiler.source=1.3
-org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment=0
-org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations=0
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_header=false
-org.eclipse.wst.jsdt.core.formatter.comment.format_html=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_source_code=true
-org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.wst.jsdt.core.formatter.comment.line_length=80
-org.eclipse.wst.jsdt.core.formatter.compact_else_if=true
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation=2
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer=1
-org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.wst.jsdt.core.formatter.indent_empty_lines=false
-org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch=true
-org.eclipse.wst.jsdt.core.formatter.indentation.size=2
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_object_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_object_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line=true
-org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line=true
-org.eclipse.wst.jsdt.core.formatter.lineSplit=9999
-org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.wst.jsdt.core.formatter.tabulation.char=space
-org.eclipse.wst.jsdt.core.formatter.tabulation.size=2
-org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true
-semanticValidation=disabled
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.prefs b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.prefs
deleted file mode 100644
index 114189d..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.prefs
+++ /dev/null
@@ -1,100 +0,0 @@
-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_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.format_source_code=false
-cleanup.make_local_variable_final=true
-cleanup.make_parameters_final=false
-cleanup.make_private_fields_final=true
-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=_Eclipse Scout
-cleanup_settings_version=2
-eclipse.preferences.version=1
-editor_save_participant_org.eclipse.wst.jsdt.ui.postsavelistener.cleanup=true
-formatter_profile=_Eclipse Scout
-formatter_settings_version=11
-org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><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_nls_tags=false
-sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_serial_version_id=false
-sp_cleanup.always_use_blocks=true
-sp_cleanup.always_use_parentheses_in_expressions=false
-sp_cleanup.always_use_this_for_non_static_field_access=false
-sp_cleanup.always_use_this_for_non_static_method_access=false
-sp_cleanup.convert_to_enhanced_for_loop=false
-sp_cleanup.format_source_code=false
-sp_cleanup.make_local_variable_final=false
-sp_cleanup.make_parameters_final=false
-sp_cleanup.make_private_fields_final=true
-sp_cleanup.make_variable_declarations_final=true
-sp_cleanup.never_use_blocks=false
-sp_cleanup.never_use_parentheses_in_expressions=true
-sp_cleanup.on_save_use_additional_actions=true
-sp_cleanup.organize_imports=true
-sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
-sp_cleanup.remove_private_constructors=true
-sp_cleanup.remove_trailing_whitespaces=true
-sp_cleanup.remove_trailing_whitespaces_all=true
-sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
-sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
-sp_cleanup.remove_unused_imports=false
-sp_cleanup.remove_unused_local_variables=false
-sp_cleanup.remove_unused_private_fields=true
-sp_cleanup.remove_unused_private_members=false
-sp_cleanup.remove_unused_private_methods=true
-sp_cleanup.remove_unused_private_types=true
-sp_cleanup.sort_members=false
-sp_cleanup.sort_members_all=false
-sp_cleanup.use_blocks=false
-sp_cleanup.use_blocks_only_for_return_and_throw=false
-sp_cleanup.use_parentheses_in_expressions=false
-sp_cleanup.use_this_for_non_static_field_access=false
-sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
-sp_cleanup.use_this_for_non_static_method_access=false
-sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.container b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.container
deleted file mode 100644
index 49c8cd4..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.container
+++ /dev/null
@@ -1 +0,0 @@
-org.eclipse.wst.jsdt.launching.JRE_CONTAINER
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.name b/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.name
deleted file mode 100644
index 11006e2..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/.settings/org.eclipse.wst.jsdt.ui.superType.name
+++ /dev/null
@@ -1 +0,0 @@
-Global
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile.test/about.html b/org.eclipse.scout.rt.client.mobile.test/about.html
deleted file mode 100644
index c258ef5..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
- 
-<p>June 5, 2006</p>	
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
-indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
-at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content.  Check the Redistributor's license that was 
-provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile.test/pom.xml b/org.eclipse.scout.rt.client.mobile.test/pom.xml
deleted file mode 100644
index 40834c3..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/pom.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-    All rights reserved. This program and the accompanying materials
-    are made available under the terms of the Eclipse Public License v1.0
-    which accompanies this distribution, and is available at
-    http://www.eclipse.org/legal/epl-v10.html
-
-    Contributors:
-        BSI Business Systems Integration AG - initial API and implementation
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.eclipse.scout.rt</groupId>
-    <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
-    <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
-  </parent>
-
-  <artifactId>org.eclipse.scout.rt.client.mobile.test</artifactId>
-  <packaging>jar</packaging>
-  <name>${project.groupId}:${project.artifactId}</name>
-
-  <dependencies>
-    <!-- Build Dependencies -->
-    <dependency>
-      <groupId>org.eclipse.scout.rt</groupId>
-      <artifactId>org.eclipse.scout.rt.client.mobile</artifactId>
-    </dependency>
-
-    <!-- Test Dependencies -->
-    <dependency>
-      <groupId>org.eclipse.scout.rt</groupId>
-      <artifactId>org.eclipse.scout.rt.client.test</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormTest.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormTest.java
deleted file mode 100644
index 6daae1b..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormTest.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.AbstractMobileTable;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.ClearTableSelectionFormCloseListener;
-import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
-import org.eclipse.scout.rt.client.ui.basic.table.HeaderCell;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
-import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
-import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(ClientTestRunner.class)
-@RunWithSubject("anna")
-@RunWithClientSession(TestEnvironmentClientSession.class)
-public class TableRowFormTest {
-  private Table m_table;
-  private ITableRowForm m_tableRowForm;
-
-  @Before
-  public void setUp() {
-    m_table = new Table();
-    ITableRow row = m_table.createRow();
-    m_table.getString1EditableColumn().setValue(row, "value 1");
-    m_table.getString2EditableWrapColumn().setValue(row, "value 2");
-    m_table.getString3NotEditableColumn().setValue(row, "value 3");
-    m_table.getString4NotEditableWrapColumn().setValue(row, "value 4");
-    m_table.addRow(row);
-
-    m_table.selectFirstRow();
-  }
-
-  @After
-  public void tearDown() {
-    m_tableRowForm.doClose();
-  }
-
-  @Test
-  public void testLabelSet() {
-    assertLabelsSet();
-  }
-
-  @Test
-  public void testLabelChange() {
-    try {
-      m_table.getString1EditableColumn().m_headerText = "new header text";
-      m_table.getString1EditableColumn().decorateHeaderCell();
-
-      assertLabelsSet();
-
-    }
-    finally {
-      m_table.getString1EditableColumn().m_headerText = m_table.getString1EditableColumn().getConfiguredHeaderText();
-      m_table.getString1EditableColumn().decorateHeaderCell();
-    }
-  }
-
-  @Test
-  public void testLabelLineBreakRemoved() {
-    try {
-      m_table.getString1EditableColumn().m_headerText = "line\nbreak";
-      m_table.getString1EditableColumn().decorateHeaderCell();
-
-      boolean labelFound = false;
-      for (IFormField field : m_tableRowForm.getAllFields()) {
-        if ("line break".equals(field.getLabel())) {
-          labelFound = true;
-        }
-      }
-      Assert.assertTrue("Field label must not contain line breaks.", labelFound);
-
-    }
-    finally {
-      m_table.getString1EditableColumn().m_headerText = m_table.getString1EditableColumn().getConfiguredHeaderText();
-      m_table.getString1EditableColumn().decorateHeaderCell();
-    }
-  }
-
-  @Test
-  public void testMultiline() {
-    for (IFormField field : m_tableRowForm.getAllFields()) {
-      if ("column 2".equals(field.getLabel()) || "column 4".equals(field.getLabel())) {
-        Assert.assertTrue("Field should be bigger in case of multiline", field.getGridDataHints().h > 1);
-      }
-      else if ("column 1".equals(field.getLabel()) || "column 3".equals(field.getLabel())) {
-        Assert.assertTrue("Field should have gridh of 1", field.getGridDataHints().h == 1);
-      }
-    }
-
-  }
-
-  private void assertLabelsSet() {
-    List<String> labels = new ArrayList<String>();
-    for (IColumn<?> column : m_table.getColumns()) {
-      labels.add(column.getHeaderCell().getText());
-    }
-    for (IFormField field : m_tableRowForm.getAllFields()) {
-      labels.remove(field.getLabel());
-    }
-    Assert.assertTrue(labels.isEmpty());
-  }
-
-  private class Table extends AbstractMobileTable {
-
-    public String1EditableColumn getString1EditableColumn() {
-      return getColumnSet().getColumnByClass(String1EditableColumn.class);
-    }
-
-    public String2EditableColumn getString2EditableWrapColumn() {
-      return getColumnSet().getColumnByClass(String2EditableColumn.class);
-    }
-
-    public String3NotEditableColumn getString3NotEditableColumn() {
-      return getColumnSet().getColumnByClass(String3NotEditableColumn.class);
-    }
-
-    public String4NotEditableWrapColumn getString4NotEditableWrapColumn() {
-      return getColumnSet().getColumnByClass(String4NotEditableWrapColumn.class);
-    }
-
-    @Override
-    protected void execRowsSelected(List<? extends ITableRow> rows) {
-      if (CollectionUtility.hasElements(rows)) {
-        startTableRowForm(CollectionUtility.firstElement(rows));
-      }
-    }
-
-    @Override
-    protected ITableRowFormProvider createTableRowFormProvider() {
-      return new DefaultTableRowFormProvider() {
-        @Override
-        public ITableRowForm createTableRowForm(ITableRow row) {
-          ITableRowForm form = super.createTableRowForm(row);
-          form.setShowOnStart(false); // Disable to avoid
-          // ClientJob usage
-          form.addFormListener(new ClearTableSelectionFormCloseListener(
-              Table.this));
-          m_tableRowForm = form;
-          return form;
-        }
-      };
-    }
-
-    @Order(10)
-    public class String1EditableColumn extends AbstractStringColumn {
-      public String m_headerText;
-
-      @Override
-      protected void execDecorateHeaderCell(HeaderCell cell) {
-        if (m_headerText != null) {
-          cell.setText(m_headerText);
-        }
-      }
-
-      @Override
-      protected String getConfiguredHeaderText() {
-        return "column 1";
-      }
-
-      @Override
-      protected boolean getConfiguredEditable() {
-        return true;
-      }
-
-      @Override
-      protected int getConfiguredWidth() {
-        return 100;
-      }
-    }
-
-    @Order(20)
-    public class String2EditableColumn extends AbstractStringColumn {
-
-      @Override
-      protected String getConfiguredHeaderText() {
-        return "column 2";
-      }
-
-      @Override
-      protected boolean getConfiguredEditable() {
-        return true;
-      }
-
-      @Override
-      protected boolean getConfiguredTextWrap() {
-        return true;
-      }
-
-      @Override
-      protected int getConfiguredWidth() {
-        return 200;
-      }
-    }
-
-    @Order(30)
-    public class String3NotEditableColumn extends AbstractStringColumn {
-
-      @Override
-      protected String getConfiguredHeaderText() {
-        return "column 3";
-      }
-
-      @Override
-      protected boolean getConfiguredEditable() {
-        return false;
-      }
-
-      @Override
-      protected int getConfiguredWidth() {
-        return 200;
-      }
-    }
-
-    @Order(40)
-    public class String4NotEditableWrapColumn extends AbstractStringColumn {
-
-      @Override
-      protected String getConfiguredHeaderText() {
-        return "column 4";
-      }
-
-      @Override
-      protected boolean getConfiguredEditable() {
-        return false;
-      }
-
-      @Override
-      protected boolean getConfiguredTextWrap() {
-        return true;
-      }
-
-      @Override
-      protected int getConfiguredWidth() {
-        return 200;
-      }
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabFormTestTest.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabFormTestTest.java
deleted file mode 100644
index 70c489e..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabFormTestTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox;
-
-import static org.junit.Assert.assertEquals;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.AbstractTemplate2GroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.AbstractTemplate3GroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.SimpleGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.TemplateExGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.TemplateGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestFormData;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
-import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
-import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
-import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(ClientTestRunner.class)
-@RunWithSubject("default")
-@RunWithClientSession(TestEnvironmentClientSession.class)
-public class TabFormTestTest {
-
-  @Test
-  public void testSimpleExport() {
-    TestForm f = new TestForm();
-    TabForm tabForm = null;
-    try {
-      //Wrap tabbox
-      TabBoxGroupBox mobileTabBox = new TabBoxGroupBox(f.getTabBox());
-      mobileTabBox.initField();
-
-      //Select first groupBox
-      mobileTabBox.getTableField().getTable().selectFirstRow();
-      tabForm = ClientSessionProvider.currentSession().getDesktop().findForm(TabForm.class);
-
-      tabForm.getRootGroupBox().getFieldByClass(SimpleGroupBox.TextSimpleField.class).setValue("s1");
-
-      //store some values
-      TestFormData formData = new TestFormData();
-      f.exportFormData(formData);
-
-      assertEquals("s1", formData.getTextSimple().getValue());
-    }
-    finally {
-      if (tabForm != null) {
-        tabForm.doClose();
-      }
-      f.doClose();
-    }
-  }
-
-  @Test
-  public void testTemplateExport() {
-    TestForm f = new TestForm();
-    TabForm tabForm = null;
-    try {
-      //Wrap tabbox
-      TabBoxGroupBox mobileTabBox = new TabBoxGroupBox(f.getTabBox());
-      mobileTabBox.initField();
-
-      //Select template groupBox
-      mobileTabBox.getTableField().getTable().selectRow(1);
-
-      tabForm = ClientSessionProvider.currentSession().getDesktop().findForm(TabForm.class);
-      tabForm.getRootGroupBox().getFieldByClass(TemplateGroupBox.Text1Field.class).setValue("s1");
-      tabForm.getRootGroupBox().getFieldByClass(TemplateGroupBox.Text2Field.class).setValue("s2");
-      tabForm.getRootGroupBox().getFieldByClass(AbstractTemplate2GroupBox.T2Text1Field.class).setValue("t1");
-      tabForm.getRootGroupBox().getFieldByClass(AbstractTemplate3GroupBox.T3Text1Field.class).setValue("t2");
-
-      //store some values
-      TestFormData formData = new TestFormData();
-      f.exportFormData(formData);
-
-      assertEquals("s1", formData.getTemplateGroupBox().getText1().getValue());
-      assertEquals("s2", formData.getTemplateGroupBox().getText2().getValue());
-      assertEquals("t2", formData.getTemplateGroupBox().getTabTemplate().getT3Text1().getValue());
-    }
-    finally {
-      if (tabForm != null) {
-        tabForm.doClose();
-      }
-      f.doClose();
-    }
-  }
-
-  @Test
-  public void testTemplateExExport() {
-    TestForm f = new TestForm();
-    TabForm tabForm = null;
-    try {
-      //Wrap tabbox
-      TabBoxGroupBox mobileTabBox = new TabBoxGroupBox(f.getTabBox());
-      mobileTabBox.initField();
-
-      //Select templateEx groupBox
-      mobileTabBox.getTableField().getTable().selectRow(2);
-
-      tabForm = ClientSessionProvider.currentSession().getDesktop().findForm(TabForm.class);
-      tabForm.getRootGroupBox().getFieldByClass(TemplateExGroupBox.Text1Field.class).setValue("s1");
-      tabForm.getRootGroupBox().getFieldByClass(TemplateExGroupBox.Text2Field.class).setValue("s2");
-      tabForm.getRootGroupBox().getFieldByClass(TemplateExGroupBox.Text3Field.class).setValue("s3");
-
-      //store some values
-      TestFormData formData = new TestFormData();
-      f.exportFormData(formData);
-
-      assertEquals("s1", formData.getTemplateExGroupBox().getText1().getValue());
-      assertEquals("s2", formData.getTemplateExGroupBox().getText2().getValue());
-      assertEquals("s3", formData.getTemplateExGroupBox().getText3().getValue());
-    }
-    finally {
-      if (tabForm != null) {
-        tabForm.doClose();
-      }
-      f.doClose();
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBox.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBox.java
deleted file mode 100644
index af7eb25..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBox.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import org.eclipse.scout.rt.client.dto.FormData;
-import org.eclipse.scout.rt.client.dto.FormData.DefaultSubtypeSdkCommand;
-import org.eclipse.scout.rt.client.dto.FormData.SdkCommand;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField;
-import org.eclipse.scout.rt.platform.Order;
-
-/**
- * Group Box with 2 text fields
- */
-@FormData(value = AbstractTemplate3GroupBoxData.class, sdkCommand = SdkCommand.CREATE, defaultSubtypeSdkCommand = DefaultSubtypeSdkCommand.CREATE)
-public abstract class AbstractTemplate2GroupBox extends AbstractGroupBox {
-
-  public T2Text1Field getT2Text1Field() {
-    return getFieldByClass(T2Text1Field.class);
-  }
-
-  @Order(10)
-  public class T2Text1Field extends AbstractStringField {
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBoxData.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBoxData.java
deleted file mode 100644
index f8289b7..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate2GroupBoxData.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import javax.annotation.Generated;
-
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
-
-/**
- * <b>NOTE:</b><br>
- * This class is auto generated by the Scout SDK. No manual modifications recommended.
- */
-@Generated(value = "org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.AbstractTemplate3GroupBox", comments = "This class is auto generated by the Scout SDK. No manual modifications recommended.")
-public abstract class AbstractTemplate2GroupBoxData extends AbstractFormFieldData {
-
-  private static final long serialVersionUID = 1L;
-
-  public T3Text1 getT3Text1() {
-    return getFieldByClass(T3Text1.class);
-  }
-
-  public static class T3Text1 extends AbstractValueFieldData<String> {
-
-    private static final long serialVersionUID = 1L;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBox.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBox.java
deleted file mode 100644
index 8488e83..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBox.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import org.eclipse.scout.rt.client.dto.FormData;
-import org.eclipse.scout.rt.client.dto.FormData.DefaultSubtypeSdkCommand;
-import org.eclipse.scout.rt.client.dto.FormData.SdkCommand;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField;
-import org.eclipse.scout.rt.platform.Order;
-
-/**
- * Group Box with 2 text fields
- */
-@FormData(value = AbstractTemplate2GroupBoxData.class, sdkCommand = SdkCommand.CREATE, defaultSubtypeSdkCommand = DefaultSubtypeSdkCommand.CREATE)
-public abstract class AbstractTemplate3GroupBox extends AbstractGroupBox {
-
-  public T3Text1Field getT3Text1Field() {
-    return getFieldByClass(T3Text1Field.class);
-  }
-
-  @Order(10)
-  public class T3Text1Field extends AbstractStringField {
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBoxData.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBoxData.java
deleted file mode 100644
index b44391e..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplate3GroupBoxData.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import javax.annotation.Generated;
-
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
-
-/**
- * <b>NOTE:</b><br>
- * This class is auto generated by the Scout SDK. No manual modifications recommended.
- */
-@Generated(value = "org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.AbstractTemplate2GroupBox", comments = "This class is auto generated by the Scout SDK. No manual modifications recommended.")
-public abstract class AbstractTemplate3GroupBoxData extends AbstractFormFieldData {
-
-  private static final long serialVersionUID = 1L;
-
-  public T2Text1 getT2Text1() {
-    return getFieldByClass(T2Text1.class);
-  }
-
-  public static class T2Text1 extends AbstractValueFieldData<String> {
-
-    private static final long serialVersionUID = 1L;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBox.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBox.java
deleted file mode 100644
index a4d3b0f..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBox.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import org.eclipse.scout.rt.client.dto.FormData;
-import org.eclipse.scout.rt.client.dto.FormData.DefaultSubtypeSdkCommand;
-import org.eclipse.scout.rt.client.dto.FormData.SdkCommand;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.AbstractTabBox;
-import org.eclipse.scout.rt.platform.Order;
-
-/**
- * Group Box with 2 text fields
- */
-@FormData(value = AbstractTemplateGroupBoxData.class, sdkCommand = SdkCommand.CREATE, defaultSubtypeSdkCommand = DefaultSubtypeSdkCommand.CREATE)
-public abstract class AbstractTemplateGroupBox extends AbstractGroupBox {
-
-  public Text1Field getText1Field() {
-    return getFieldByClass(Text1Field.class);
-  }
-
-  public Text2Field getText2Field() {
-    return getFieldByClass(Text2Field.class);
-  }
-
-  @Order(10)
-  public class Text1Field extends AbstractStringField {
-  }
-
-  @Order(20)
-  public class Text2Field extends AbstractStringField {
-  }
-
-  @Order(30)
-  public class TabGroupBox extends AbstractTabBox {
-
-    @Order(10)
-    public class TabTemplateField extends AbstractTemplate3GroupBox {
-    }
-  }
-
-  @Order(40)
-  public class TemplateField extends AbstractTemplate2GroupBox {
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBoxData.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBoxData.java
deleted file mode 100644
index 2d4c4b1..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/AbstractTemplateGroupBoxData.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import javax.annotation.Generated;
-
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
-
-/**
- * <b>NOTE:</b><br>
- * This class is auto generated by the Scout SDK. No manual modifications recommended.
- */
-@Generated(value = "org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.AbstractTemplateGroupBox", comments = "This class is auto generated by the Scout SDK. No manual modifications recommended.")
-public abstract class AbstractTemplateGroupBoxData extends AbstractFormFieldData {
-
-  private static final long serialVersionUID = 1L;
-
-  public TabTemplate getTabTemplate() {
-    return getFieldByClass(TabTemplate.class);
-  }
-
-  public Template getTemplate() {
-    return getFieldByClass(Template.class);
-  }
-
-  public Text1 getText1() {
-    return getFieldByClass(Text1.class);
-  }
-
-  public Text2 getText2() {
-    return getFieldByClass(Text2.class);
-  }
-
-  public static class TabTemplate extends AbstractTemplate2GroupBoxData {
-
-    private static final long serialVersionUID = 1L;
-  }
-
-  public static class Template extends AbstractTemplate3GroupBoxData {
-
-    private static final long serialVersionUID = 1L;
-  }
-
-  public static class Text1 extends AbstractValueFieldData<String> {
-
-    private static final long serialVersionUID = 1L;
-  }
-
-  public static class Text2 extends AbstractValueFieldData<String> {
-
-    private static final long serialVersionUID = 1L;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestForm.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestForm.java
deleted file mode 100644
index b177372..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestForm.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import org.eclipse.scout.rt.client.dto.FormData;
-import org.eclipse.scout.rt.client.dto.FormData.SdkCommand;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.CancelButton;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.OkButton;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.SimpleGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.SimpleGroupBox.TextSimpleField;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.TemplateExGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.TemplateExGroupBox.Text3Field;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm.MainBox.TabBox.TemplateGroupBox;
-import org.eclipse.scout.rt.client.ui.form.AbstractForm;
-import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler;
-import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractCancelButton;
-import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractOkButton;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.AbstractTabBox;
-import org.eclipse.scout.rt.platform.Order;
-
-@FormData(value = TestFormData.class, sdkCommand = SdkCommand.CREATE)
-public class TestForm extends AbstractForm {
-
-  public TestForm() {
-    super();
-  }
-
-  public CancelButton getCancelButton() {
-    return getFieldByClass(CancelButton.class);
-  }
-
-  public void startNew() {
-    startInternal(new NewHandler());
-  }
-
-  public SimpleGroupBox getSimpleGroupBox() {
-    return getFieldByClass(SimpleGroupBox.class);
-  }
-
-  public TemplateGroupBox getTemplateBox() {
-    return getFieldByClass(TemplateGroupBox.class);
-  }
-
-  public TabBox getTabBox() {
-    return getFieldByClass(TabBox.class);
-  }
-
-  public TemplateExGroupBox getTemplateExGroupBox() {
-    return getFieldByClass(TemplateExGroupBox.class);
-  }
-
-  public MainBox getMainBox() {
-    return getFieldByClass(MainBox.class);
-  }
-
-  public OkButton getOkButton() {
-    return getFieldByClass(OkButton.class);
-  }
-
-  public TextSimpleField getTextSimpleField() {
-    return getFieldByClass(TextSimpleField.class);
-  }
-
-  public Text3Field getText3Field() {
-    return getFieldByClass(Text3Field.class);
-  }
-
-  @Order(10)
-  public class MainBox extends AbstractGroupBox {
-
-    @Order(10)
-    public class TabBox extends AbstractTabBox {
-
-      @Order(10)
-      public class SimpleGroupBox extends AbstractGroupBox {
-
-        @Order(10)
-        public class TextSimpleField extends AbstractStringField {
-        }
-
-      }
-
-      @Order(20)
-      public class TemplateGroupBox extends AbstractTemplateGroupBox {
-      }
-
-      @Order(30)
-      public class TemplateExGroupBox extends AbstractTemplateGroupBox {
-
-        @Order(10)
-        public class Text3Field extends AbstractStringField {
-        }
-      }
-
-    }
-
-    @Order(30)
-    public class OkButton extends AbstractOkButton {
-    }
-
-    @Order(40)
-    public class CancelButton extends AbstractCancelButton {
-    }
-  }
-
-  public class NewHandler extends AbstractFormHandler {
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestFormData.java b/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestFormData.java
deleted file mode 100644
index 7d75e7e..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/fixture/TestFormData.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture;
-
-import javax.annotation.Generated;
-
-import org.eclipse.scout.rt.shared.data.form.AbstractFormData;
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
-
-/**
- * <b>NOTE:</b><br>
- * This class is auto generated by the Scout SDK. No manual modifications recommended.
- */
-@Generated(value = "org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.fixture.TestForm", comments = "This class is auto generated by the Scout SDK. No manual modifications recommended.")
-public class TestFormData extends AbstractFormData {
-
-  private static final long serialVersionUID = 1L;
-
-  public TemplateExGroupBox getTemplateExGroupBox() {
-    return getFieldByClass(TemplateExGroupBox.class);
-  }
-
-  public TemplateGroupBox getTemplateGroupBox() {
-    return getFieldByClass(TemplateGroupBox.class);
-  }
-
-  public TextSimple getTextSimple() {
-    return getFieldByClass(TextSimple.class);
-  }
-
-  public static class TemplateExGroupBox extends AbstractTemplateGroupBoxData {
-
-    private static final long serialVersionUID = 1L;
-
-    public Text3 getText3() {
-      return getFieldByClass(Text3.class);
-    }
-
-    public static class Text3 extends AbstractValueFieldData<String> {
-
-      private static final long serialVersionUID = 1L;
-    }
-  }
-
-  public static class TemplateGroupBox extends AbstractTemplateGroupBoxData {
-
-    private static final long serialVersionUID = 1L;
-  }
-
-  public static class TextSimple extends AbstractValueFieldData<String> {
-
-    private static final long serialVersionUID = 1L;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile.test/src/test/resources/logback-test.xml b/org.eclipse.scout.rt.client.mobile.test/src/test/resources/logback-test.xml
deleted file mode 100644
index 3a28021..0000000
--- a/org.eclipse.scout.rt.client.mobile.test/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-
-    Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-    All rights reserved. This program and the accompanying materials
-    are made available under the terms of the Eclipse Public License v1.0
-    which accompanies this distribution, and is available at
-    http://www.eclipse.org/legal/epl-v10.html
-
-    Contributors:
-        BSI Business Systems Integration AG - initial API and implementation
-
--->
-<configuration>
-  <include resource="logback-test-scout.xml" />
-</configuration>
diff --git a/org.eclipse.scout.rt.client.mobile/.classpath b/org.eclipse.scout.rt.client.mobile/.classpath
deleted file mode 100644
index 698778f..0000000
--- a/org.eclipse.scout.rt.client.mobile/.classpath
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
diff --git a/org.eclipse.scout.rt.client.mobile/.project b/org.eclipse.scout.rt.client.mobile/.project
deleted file mode 100644
index ee9a7f2..0000000
--- a/org.eclipse.scout.rt.client.mobile/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>org.eclipse.scout.rt.client.mobile</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.m2e.core.maven2Builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.eclipse.m2e.core.maven2Nature</nature>
-	</natures>
-</projectDescription>
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/.jsdtscope b/org.eclipse.scout.rt.client.mobile/.settings/.jsdtscope
deleted file mode 100644
index 555a5ca..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/.jsdtscope
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-  <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
-  <classpathentry kind="src" path="src/main/js" excluding="*-module.js"/>
-  <classpathentry kind="lib" path="src/main/resources/WebContent/res" excluding="*-macro.js"/>
-  <classpathentry exported="true" kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
-  <classpathentry kind="output" path=""/>
-</classpath>
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/com.eclipsesource.jshint.ui.prefs b/org.eclipse.scout.rt.client.mobile/.settings/com.eclipsesource.jshint.ui.prefs
deleted file mode 100644
index 00492d9..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/com.eclipsesource.jshint.ui.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-eclipse.preferences.version=1
-included=src/main/js//*.js\:src/test/js//*.js
-projectSpecificOptions=true
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/de.loskutov.anyedit.AnyEditTools.prefs b/org.eclipse.scout.rt.client.mobile/.settings/de.loskutov.anyedit.AnyEditTools.prefs
deleted file mode 100644
index 9e00de0..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/de.loskutov.anyedit.AnyEditTools.prefs
+++ /dev/null
@@ -1,18 +0,0 @@
-activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF,.project,*.target
-addNewLine=true
-convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
-eclipse.preferences.version=1
-fixLineDelimiters=true
-ignoreBlankLinesWhenTrimming=false
-inActiveContentFilterList=
-javaTabWidthForJava=true
-org.eclipse.jdt.ui.editor.tab.width=2
-projectPropsEnabled=true
-removeTrailingSpaces=true
-replaceAllSpaces=false
-replaceAllTabs=true
-saveAndAddLine=true
-saveAndConvert=true
-saveAndFixLineDelimiters=true
-saveAndTrim=true
-useModulo4Tabs=true
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.resources.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 13d34f3..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,18 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/client=UTF-8
-encoding//src/main/fixture=UTF-8
-encoding//src/main/java=UTF-8
-encoding//src/main/java-jcl=UTF-8
-encoding//src/main/java-log4j=UTF-8
-encoding//src/main/java-original=UTF-8
-encoding//src/main/js=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/main/shared=UTF-8
-encoding//src/main/webapp=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/js=UTF-8
-encoding//src/test/resources=UTF-8
-encoding//target/generated-sources/annotations=UTF-8
-encoding//target/generated-sources/wsimport=UTF-8
-encoding/<project>=UTF-8
-encoding/files=UTF-8
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.runtime.prefs
deleted file mode 100644
index 5a0ad22..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.core.runtime.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-line.separator=\n
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 7a93103..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,395 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.codeComplete.argumentPrefixes=
-org.eclipse.jdt.core.codeComplete.argumentSuffixes=
-org.eclipse.jdt.core.codeComplete.fieldPrefixes=m_
-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.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=enabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
-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=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-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=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-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=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
-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=enabled
-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=ignore
-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.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=disabled
-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.processAnnotations=disabled
-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=16
-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=16
-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=16
-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=true
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
-org.eclipse.jdt.core.formatter.comment.format_block_comments=false
-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=false
-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=120
-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=true
-org.eclipse.jdt.core.formatter.indentation.size=2
-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=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=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=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=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=do not 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=do not 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=do not 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=do not 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=false
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true
-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=true
-org.eclipse.jdt.core.formatter.lineSplit=240
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
-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=space
-org.eclipse.jdt.core.formatter.tabulation.size=2
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
-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
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index 27aaab4..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,127 +0,0 @@
-cleanup.add_default_serial_version_id=true
-cleanup.add_generated_serial_version_id=false
-cleanup.add_missing_annotations=true
-cleanup.add_missing_deprecated_annotations=false
-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_functional_interfaces=false
-cleanup.convert_to_enhanced_for_loop=false
-cleanup.correct_indentation=true
-cleanup.format_source_code=true
-cleanup.format_source_code_changes_only=false
-cleanup.insert_inferred_type_arguments=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=true
-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=false
-cleanup.qualify_static_member_accesses_with_declaring_class=false
-cleanup.qualify_static_method_accesses_with_declaring_class=false
-cleanup.remove_private_constructors=true
-cleanup.remove_redundant_type_arguments=true
-cleanup.remove_trailing_whitespaces=true
-cleanup.remove_trailing_whitespaces_all=true
-cleanup.remove_trailing_whitespaces_ignore_empty=false
-cleanup.remove_unnecessary_casts=false
-cleanup.remove_unnecessary_nls_tags=false
-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_anonymous_class_creation=false
-cleanup.use_blocks=false
-cleanup.use_blocks_only_for_return_and_throw=false
-cleanup.use_lambda=true
-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.use_type_arguments=false
-cleanup_profile=_Eclipse Scout
-cleanup_settings_version=2
-eclipse.preferences.version=1
-editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
-formatter_profile=_Eclipse Scout
-formatter_settings_version=12
-org.eclipse.jdt.ui.exception.name=e
-org.eclipse.jdt.ui.gettersetter.use.is=true
-org.eclipse.jdt.ui.javadoc=true
-org.eclipse.jdt.ui.keywordthis=false
-org.eclipse.jdt.ui.overrideannotation=true
-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><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 * &lt;h3&gt;{@link ${type_name}}&lt;/h3&gt;\n *\n * @author ${user}\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><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\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><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\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" 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}</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><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * &lt;h3&gt;{@link ${type_name}}&lt;/h3&gt;\n *\n * @author ${user}\n * @since ${date}\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.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.wst.jsdt.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.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.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.wst.jsdt.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=false
-sp_cleanup.add_missing_methods=false
-sp_cleanup.add_missing_nls_tags=false
-sp_cleanup.add_missing_override_annotations=false
-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=false
-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=true
-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/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.m2e.core.prefs
deleted file mode 100644
index f897a7f..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.m2e.core.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-activeProfiles=
-eclipse.preferences.version=1
-resolveWorkspaceProjects=true
-version=1
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.core.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.core.prefs
deleted file mode 100644
index 4bab8fd..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.core.prefs
+++ /dev/null
@@ -1,306 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.wst.jsdt.core.compiler.codegen.inlineJsrBytecode=disabled
-org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform=1.2
-org.eclipse.wst.jsdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.wst.jsdt.core.compiler.compliance=1.4
-org.eclipse.wst.jsdt.core.compiler.debug.lineNumber=generate
-org.eclipse.wst.jsdt.core.compiler.debug.localVariable=generate
-org.eclipse.wst.jsdt.core.compiler.debug.sourceFile=generate
-org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier=warning
-org.eclipse.wst.jsdt.core.compiler.problem.deprecation=warning
-org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.wst.jsdt.core.compiler.problem.duplicateLocalVariables=warning
-org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.wst.jsdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.looseVarDecleration=warning
-org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.nullReference=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.optionalSemicolon=warning
-org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.undefinedField=warning
-org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.uninitializedGlobalVariable=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.uninitializedLocalVariable=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedFieldReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedMethodReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unresolvedTypeReference=error
-org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.wst.jsdt.core.compiler.source=1.3
-org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment=0
-org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package=0
-org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations=0
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_header=false
-org.eclipse.wst.jsdt.core.formatter.comment.format_html=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments=true
-org.eclipse.wst.jsdt.core.formatter.comment.format_source_code=true
-org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.wst.jsdt.core.formatter.comment.line_length=80
-org.eclipse.wst.jsdt.core.formatter.compact_else_if=true
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation=2
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer=1
-org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.wst.jsdt.core.formatter.indent_empty_lines=false
-org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch=true
-org.eclipse.wst.jsdt.core.formatter.indentation.size=2
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_object_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_object_initializer=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line=true
-org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line=true
-org.eclipse.wst.jsdt.core.formatter.lineSplit=9999
-org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.wst.jsdt.core.formatter.tabulation.char=space
-org.eclipse.wst.jsdt.core.formatter.tabulation.size=2
-org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true
-semanticValidation=disabled
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.prefs b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.prefs
deleted file mode 100644
index 114189d..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.prefs
+++ /dev/null
@@ -1,100 +0,0 @@
-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_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.format_source_code=false
-cleanup.make_local_variable_final=true
-cleanup.make_parameters_final=false
-cleanup.make_private_fields_final=true
-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=_Eclipse Scout
-cleanup_settings_version=2
-eclipse.preferences.version=1
-editor_save_participant_org.eclipse.wst.jsdt.ui.postsavelistener.cleanup=true
-formatter_profile=_Eclipse Scout
-formatter_settings_version=11
-org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><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_nls_tags=false
-sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_serial_version_id=false
-sp_cleanup.always_use_blocks=true
-sp_cleanup.always_use_parentheses_in_expressions=false
-sp_cleanup.always_use_this_for_non_static_field_access=false
-sp_cleanup.always_use_this_for_non_static_method_access=false
-sp_cleanup.convert_to_enhanced_for_loop=false
-sp_cleanup.format_source_code=false
-sp_cleanup.make_local_variable_final=false
-sp_cleanup.make_parameters_final=false
-sp_cleanup.make_private_fields_final=true
-sp_cleanup.make_variable_declarations_final=true
-sp_cleanup.never_use_blocks=false
-sp_cleanup.never_use_parentheses_in_expressions=true
-sp_cleanup.on_save_use_additional_actions=true
-sp_cleanup.organize_imports=true
-sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
-sp_cleanup.remove_private_constructors=true
-sp_cleanup.remove_trailing_whitespaces=true
-sp_cleanup.remove_trailing_whitespaces_all=true
-sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
-sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
-sp_cleanup.remove_unused_imports=false
-sp_cleanup.remove_unused_local_variables=false
-sp_cleanup.remove_unused_private_fields=true
-sp_cleanup.remove_unused_private_members=false
-sp_cleanup.remove_unused_private_methods=true
-sp_cleanup.remove_unused_private_types=true
-sp_cleanup.sort_members=false
-sp_cleanup.sort_members_all=false
-sp_cleanup.use_blocks=false
-sp_cleanup.use_blocks_only_for_return_and_throw=false
-sp_cleanup.use_parentheses_in_expressions=false
-sp_cleanup.use_this_for_non_static_field_access=false
-sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
-sp_cleanup.use_this_for_non_static_method_access=false
-sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.container b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.container
deleted file mode 100644
index 49c8cd4..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.container
+++ /dev/null
@@ -1 +0,0 @@
-org.eclipse.wst.jsdt.launching.JRE_CONTAINER
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.name b/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.name
deleted file mode 100644
index 11006e2..0000000
--- a/org.eclipse.scout.rt.client.mobile/.settings/org.eclipse.wst.jsdt.ui.superType.name
+++ /dev/null
@@ -1 +0,0 @@
-Global
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile/about.html b/org.eclipse.scout.rt.client.mobile/about.html
deleted file mode 100644
index c258ef5..0000000
--- a/org.eclipse.scout.rt.client.mobile/about.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
- 
-<p>June 5, 2006</p>	
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
-indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
-at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
-For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
-being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
-apply to your use of any object code in the Content.  Check the Redistributor's license that was 
-provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/org.eclipse.scout.rt.client.mobile/pom.xml b/org.eclipse.scout.rt.client.mobile/pom.xml
deleted file mode 100644
index fc8552e..0000000
--- a/org.eclipse.scout.rt.client.mobile/pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-    All rights reserved. This program and the accompanying materials
-    are made available under the terms of the Eclipse Public License v1.0
-    which accompanies this distribution, and is available at
-    http://www.eclipse.org/legal/epl-v10.html
-
-    Contributors:
-        BSI Business Systems Integration AG - initial API and implementation
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.eclipse.scout.rt</groupId>
-    <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
-    <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
-  </parent>
-
-  <artifactId>org.eclipse.scout.rt.client.mobile</artifactId>
-  <packaging>jar</packaging>
-  <name>${project.groupId}:${project.artifactId}</name>
-
-  <dependencies>
-    <!-- Build Dependencies -->
-    <dependency>
-      <groupId>org.eclipse.scout.rt</groupId>
-      <artifactId>org.eclipse.scout.rt.client</artifactId>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/Icons.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/Icons.java
deleted file mode 100644
index c5a7fb7..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/Icons.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile;
-
-import org.eclipse.scout.rt.shared.AbstractIcons;
-
-/**
- * @since 3.9.0
- */
-public class Icons extends AbstractIcons {
-
-  private static final long serialVersionUID = 1L;
-
-  public static final String BackAction = "mobile_back_action";
-  public static final String CheckboxYes = "checkbox_yes";
-  public static final String CheckboxNo = "checkbox_no";
-  public static final String DrillDown = "mobile_drill_down";
-  public static final String DrillDownButton = "mobile_drill_down_button";
-  public static final String FormToolsAction = "mobile_tools_menu";
-  public static final String HomeAction = "mobile_home_action";
-  public static final String MoreActionsUp = "mobile_more_actions_up";
-  public static final String MoreActionsDown = "mobile_more_actions_down";
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileBackAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileBackAction.java
deleted file mode 100644
index cde8d6b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileBackAction.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.mobile.Icons;
-import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.util.WeakEventListener;
-
-public abstract class AbstractMobileBackAction extends AbstractMenu {
-  private P_BreadCrumbsListener m_breadCrumbsListener;
-
-  @Override
-  protected String getConfiguredText() {
-    return "";
-  }
-
-  @Override
-  protected void execInitAction() {
-    IBreadCrumbsNavigation breadCrumbsNavigation = BEANS.get(IBreadCrumbsNavigationService.class).getBreadCrumbsNavigation();
-    if (m_breadCrumbsListener == null) {
-      m_breadCrumbsListener = new P_BreadCrumbsListener();
-      breadCrumbsNavigation.addBreadCrumbsListener(m_breadCrumbsListener);
-    }
-    setVisible(breadCrumbsNavigation.isSteppingBackPossible());
-  }
-
-  @Override
-  protected String getConfiguredIconId() {
-    return Icons.BackAction;
-  }
-
-  @Override
-  protected void execAction() {
-    BEANS.get(IBreadCrumbsNavigationService.class).getBreadCrumbsNavigation().stepBack();
-  }
-
-  private class P_BreadCrumbsListener implements BreadCrumbsListener, WeakEventListener {
-
-    @Override
-    public void breadCrumbsChanged(BreadCrumbsEvent e) {
-      setVisible(e.getBreadCrumbsNavigation().isSteppingBackPossible());
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileHomeAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileHomeAction.java
deleted file mode 100644
index e9f2554..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/AbstractMobileHomeAction.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.mobile.Icons;
-import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.util.WeakEventListener;
-
-@Order(20)
-public abstract class AbstractMobileHomeAction extends AbstractMenu {
-  private P_BreadCrumbsListener m_breadCrumbsListener;
-
-  @Override
-  protected String getConfiguredText() {
-    return "";
-  }
-
-  @Override
-  protected boolean getConfiguredVisible() {
-    return false;
-  }
-
-  @Override
-  protected String getConfiguredIconId() {
-    return Icons.HomeAction;
-  }
-
-  @Override
-  protected void execInitAction() {
-    if (m_breadCrumbsListener == null) {
-      m_breadCrumbsListener = new P_BreadCrumbsListener();
-      BEANS.get(IBreadCrumbsNavigationService.class).getBreadCrumbsNavigation().addBreadCrumbsListener(m_breadCrumbsListener);
-    }
-  }
-
-  @Override
-  protected void execAction() {
-    BEANS.get(IBreadCrumbsNavigationService.class).getBreadCrumbsNavigation().goHome();
-  }
-
-  private class P_BreadCrumbsListener implements BreadCrumbsListener, WeakEventListener {
-
-    @Override
-    public void breadCrumbsChanged(BreadCrumbsEvent e) {
-      setVisible(e.getBreadCrumbsNavigation().isGoingHomePossible());
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumb.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumb.java
deleted file mode 100644
index e0d83d2..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumb.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-
-/**
- * @since 3.9.0
- */
-public class BreadCrumb implements IBreadCrumb {
-  private IForm m_form;
-  private IBreadCrumbsNavigation m_breadCrumbsNavigation;
-
-  public BreadCrumb(IBreadCrumbsNavigation breadCrumbsNavigation, IForm form) {
-    m_breadCrumbsNavigation = breadCrumbsNavigation;
-    m_form = form;
-  }
-
-  @Override
-  public void activate() {
-    autoCloseNavigationForms();
-
-    //Add form to desktop if it is open but has been removed
-    if (getForm() != null) {
-      IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
-      if (getForm().isFormStarted() && !desktop.isShowing(getForm())) {
-        if (MobileDesktopUtility.isToolForm(getForm())) {
-          MobileDesktopUtility.openToolForm(getForm());
-        }
-        else {
-          MobileDesktopUtility.addFormToDesktop(getForm());
-        }
-      }
-    }
-  }
-
-  private void autoCloseNavigationForms() {
-    List<IForm> currentNavigationForms = getBreadCrumbsNavigation().getCurrentNavigationForms();
-    for (IForm form : currentNavigationForms) {
-      if (form != getForm() && !getBreadCrumbsNavigation().containsFormInHistory(form)) {
-        MobileDesktopUtility.closeForm(form);
-      }
-    }
-  }
-
-  public IBreadCrumbsNavigation getBreadCrumbsNavigation() {
-    return m_breadCrumbsNavigation;
-  }
-
-  @Override
-  public IForm getForm() {
-    return m_form;
-  }
-
-  @Override
-  public String toString() {
-    String formName = getForm().getTitle();
-    if (StringUtility.isNullOrEmpty(formName)) {
-      formName = getForm().toString();
-    }
-    return "Form: " + formName;
-  }
-
-  @Override
-  public boolean belongsTo(IForm form) {
-    return getForm() == form;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsEvent.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsEvent.java
deleted file mode 100644
index 25c1020..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import java.util.EventObject;
-
-/**
- * @since 3.9.0
- */
-public class BreadCrumbsEvent extends EventObject {
-  private static final long serialVersionUID = 1L;
-
-  private final int m_type;
-  public static final int TYPE_CHANGED = 10;
-
-  public BreadCrumbsEvent(IBreadCrumbsNavigation source, int type) {
-    super(source);
-
-    m_type = type;
-  }
-
-  public IBreadCrumbsNavigation getBreadCrumbsNavigation() {
-    return (IBreadCrumbsNavigation) getSource();
-  }
-
-  public int getType() {
-    return m_type;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsListener.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsListener.java
deleted file mode 100644
index bf7c39b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsListener.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import java.util.EventListener;
-
-/**
- * @since 3.9.0
- */
-public interface BreadCrumbsListener extends EventListener {
-  void breadCrumbsChanged(BreadCrumbsEvent e);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigation.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigation.java
deleted file mode 100644
index 5dd9868..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigation.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import java.util.EventListener;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Stack;
-
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.IOutlineChooserForm;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.form.FormEvent;
-import org.eclipse.scout.rt.client.ui.form.FormListener;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.util.EventListenerList;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @since 3.9.0
- */
-public class BreadCrumbsNavigation implements IBreadCrumbsNavigation {
-  private static final Logger LOG = LoggerFactory.getLogger(BreadCrumbsNavigation.class);
-
-  private final EventListenerList m_listenerList;
-  private Stack<IBreadCrumb> m_breadCrumbs;
-  private P_DesktopListener m_desktopListener;
-  private List<String> m_navigationFormsDisplayViewIds;
-  private P_FormListener m_formListener;
-  private IBreadCrumb m_currentBreadCrumb;
-  private IDesktop m_desktop;
-
-  public BreadCrumbsNavigation() {
-    this(null);
-  }
-
-  public BreadCrumbsNavigation(IDesktop desktop) {
-    if (desktop == null) {
-      desktop = ClientSessionProvider.currentSession().getDesktop();
-    }
-    m_desktop = desktop;
-    if (m_desktop == null) {
-      throw new IllegalArgumentException("No desktop found. Cannot create bread crumbs navigation.");
-    }
-
-    m_breadCrumbs = new Stack<IBreadCrumb>();
-    m_listenerList = new EventListenerList();
-    m_desktopListener = new P_DesktopListener();
-    desktop.addDesktopListener(m_desktopListener);
-  }
-
-  @Override
-  public Stack<IBreadCrumb> getBreadCrumbs() {
-    return m_breadCrumbs;
-  }
-
-  @Override
-  public void trackDisplayViewId(String displayViewId) {
-    if (m_navigationFormsDisplayViewIds == null) {
-      m_navigationFormsDisplayViewIds = new LinkedList<String>();
-    }
-
-    if (!m_navigationFormsDisplayViewIds.contains(displayViewId)) {
-      m_navigationFormsDisplayViewIds.add(displayViewId);
-    }
-  }
-
-  @Override
-  public void stepBack() {
-    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
-    if (desktop == null) {
-      return;
-    }
-
-    Stack<IBreadCrumb> breadCrumbs = getBreadCrumbs();
-    if (breadCrumbs.size() == 0) {
-      LOG.debug("Stepping back not possible because no bread crumbs found.");
-      return;
-    }
-
-    m_currentBreadCrumb = breadCrumbs.pop();
-    m_currentBreadCrumb.activate();
-
-    LOG.debug("Stepped back to: {}", m_currentBreadCrumb);
-    LOG.debug("Current bread crumbs way: {}", toString());
-
-    fireBreadCrumbsChanged();
-  }
-
-  @Override
-  public boolean isSteppingBackPossible() {
-    return getBreadCrumbs().size() > 0;
-  }
-
-  @Override
-  public boolean isGoingHomePossible() {
-    return isSteppingBackPossible();
-  }
-
-  @Override
-  public void goHome() {
-    if (getBreadCrumbs().size() == 0) {
-      return;
-    }
-
-    activate(getBreadCrumbs().get(0));
-  }
-
-  public void activate(IBreadCrumb breadCrumb) {
-    if (!getBreadCrumbs().contains(breadCrumb)) {
-      return;
-    }
-
-    do {
-      m_currentBreadCrumb = getBreadCrumbs().pop();
-    }
-    while (m_currentBreadCrumb != breadCrumb);
-
-    m_currentBreadCrumb.activate();
-    LOG.debug("Activated bread crumb: {}", m_currentBreadCrumb);
-    LOG.debug("Current bread crumbs way: {}", toString());
-
-    fireBreadCrumbsChanged();
-  }
-
-  @Override
-  public List<IForm> getCurrentNavigationForms() {
-    List<IForm> navigationForms = new LinkedList<IForm>();
-
-    navigationForms.addAll(getDesktop().getDialogs());
-
-    for (IForm view : getDesktop().getViews()) {
-      if (m_navigationFormsDisplayViewIds != null && m_navigationFormsDisplayViewIds.contains(view.getDisplayViewId())) {
-        navigationForms.add(view);
-      }
-    }
-
-    return navigationForms;
-  }
-
-  @Override
-  public boolean containsFormInHistory(IForm form) {
-    if (form == null) {
-      return false;
-    }
-
-    for (IBreadCrumb breadCrumb : getBreadCrumbs()) {
-      if (form == breadCrumb.getForm()) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Override
-  public IForm getCurrentNavigationForm() {
-    if (m_currentBreadCrumb != null) {
-      return m_currentBreadCrumb.getForm();
-    }
-
-    return null;
-  }
-
-  @Override
-  public IDesktop getDesktop() {
-    return m_desktop;
-  }
-
-  private void destroy() {
-    if (m_desktopListener != null) {
-      getDesktop().removeDesktopListener(m_desktopListener);
-      m_desktopListener = null;
-    }
-
-    getBreadCrumbs().clear();
-  }
-
-  private void removeExistingBreadCrumb(IForm form) {
-    if (m_currentBreadCrumb == null) {
-      return;
-    }
-
-    if (m_currentBreadCrumb.belongsTo(form)) {
-      LOG.debug("Removing existing bread crumb: {}", m_currentBreadCrumb);
-
-      if (getBreadCrumbs().size() > 0) {
-        m_currentBreadCrumb = getBreadCrumbs().pop();
-      }
-      else {
-        m_currentBreadCrumb = null;
-      }
-
-      LOG.debug("Current bread crumbs way: {}", toString());
-      fireBreadCrumbsChanged();
-    }
-    else {
-      IBreadCrumb[] breadCrumbs = getBreadCrumbs().toArray(new IBreadCrumb[getBreadCrumbs().size()]);
-      int pos = 0;
-      for (IBreadCrumb breadCrumb : breadCrumbs) {
-        if (breadCrumb.belongsTo(form)) {
-          LOG.debug("Removing existing bread crumb: {}", breadCrumb);
-
-          getBreadCrumbs().remove(breadCrumb);
-          mergeDuplicates(pos);
-
-          LOG.debug("Current bread crumbs way: {}", toString());
-          fireBreadCrumbsChanged();
-          return;
-        }
-        pos++;
-      }
-    }
-  }
-
-  /**
-   * Makes sure that the bread crumbs at position pos and pos -1 are not the same.
-   * <p>
-   * Such successive duplicate bread crumbs make no sense because pressing back on such a duplicate would just open the
-   * same form again.
-   */
-  private void mergeDuplicates(int pos) {
-    if (pos <= 0 || pos >= getBreadCrumbs().size()) {
-      return;
-    }
-
-    IBreadCrumb predecessor = getBreadCrumbs().get(pos - 1);
-    IBreadCrumb successor = getBreadCrumbs().get(pos);
-    if (predecessor.getForm() == successor.getForm()) {
-      getBreadCrumbs().remove(successor);
-      LOG.debug("Removing duplicate bread crumb: {}", successor);
-    }
-  }
-
-  private void addNewBreadCrumb(IForm form) {
-    if (m_currentBreadCrumb != null) {
-      //Ignore attempts to insert the same bread crumb again
-      if (m_currentBreadCrumb.belongsTo(form)) {
-        return;
-      }
-
-      getBreadCrumbs().add(m_currentBreadCrumb);
-      LOG.debug("Added new bread crumb: {}", m_currentBreadCrumb);
-    }
-
-    if (form instanceof IOutlineChooserForm) {
-      m_currentBreadCrumb = new OutlineChooserBreadCrumb(this, form);
-    }
-    else {
-      m_currentBreadCrumb = new BreadCrumb(this, form);
-    }
-    LOG.debug("Current bread crumbs way: {}", toString());
-    fireBreadCrumbsChanged();
-  }
-
-  @Override
-  public void addBreadCrumbsListener(BreadCrumbsListener listener) {
-    m_listenerList.add(BreadCrumbsListener.class, listener);
-  }
-
-  @Override
-  public void removeBreadCrumbsListener(BreadCrumbsListener listener) {
-    m_listenerList.remove(BreadCrumbsListener.class, listener);
-  }
-
-  private void fireBreadCrumbsChanged() {
-    BreadCrumbsEvent e = new BreadCrumbsEvent(this, BreadCrumbsEvent.TYPE_CHANGED);
-    fireBreadCrumbsEvent(e);
-  }
-
-  private void fireBreadCrumbsEvent(BreadCrumbsEvent e) {
-    EventListener[] a = m_listenerList.getListeners(BreadCrumbsListener.class);
-    if (a != null) {
-      for (int i = 0; i < a.length; i++) {
-        ((BreadCrumbsListener) a[i]).breadCrumbsChanged(e);
-      }
-    }
-  }
-
-  @Override
-  public String toString() {
-    String breadCrumbsWay = "";
-    for (IBreadCrumb breadCrumb : getBreadCrumbs()) {
-      breadCrumbsWay += "[" + breadCrumb + "] > ";
-    }
-    if (m_currentBreadCrumb != null) {
-      breadCrumbsWay += "[" + m_currentBreadCrumb + "]";
-    }
-    else {
-      breadCrumbsWay = "empty bread crumbs navigation";
-    }
-
-    return breadCrumbsWay;
-  }
-
-  private class P_DesktopListener implements DesktopListener {
-
-    @Override
-    public void desktopChanged(DesktopEvent e) {
-
-      switch (e.getType()) {
-        case DesktopEvent.TYPE_FORM_SHOW: {
-          handleFormAdded(e);
-          break;
-        }
-        case DesktopEvent.TYPE_FORM_HIDE: {
-          handleFormRemoved(e);
-          break;
-        }
-        case DesktopEvent.TYPE_DESKTOP_CLOSED: {
-          destroy();
-          break;
-        }
-        default:
-          break;
-      }
-    }
-
-    private void handleFormAdded(DesktopEvent e) {
-      IForm form = e.getForm();
-      if (IForm.DISPLAY_HINT_VIEW == form.getDisplayHint() && m_navigationFormsDisplayViewIds != null && !m_navigationFormsDisplayViewIds.contains(form.getDisplayViewId())) {
-        return;
-      }
-
-      if (m_currentBreadCrumb == null) {
-        addNewBreadCrumb(form);
-      }
-      else if (m_currentBreadCrumb.getForm() != form) {
-        addNewBreadCrumb(form);
-      }
-
-      attachFormListener(form);
-    }
-
-    private void handleFormRemoved(DesktopEvent e) {
-      if (getBreadCrumbs().size() == 0) {
-        return;
-      }
-
-      IForm form = e.getForm();
-      if (MobileDesktopUtility.isToolForm(form)) {
-        // Stepping back must never open a tool form -> Remove from bread crumbs
-        removeExistingBreadCrumb(form);
-      }
-    }
-
-    private void attachFormListener(IForm form) {
-      if (m_formListener == null) {
-        m_formListener = new P_FormListener();
-      }
-      form.removeFormListener(m_formListener);
-      form.addFormListener(m_formListener);
-    }
-
-  }
-
-  /**
-   * Makes sure closed forms get removed from the bread crumbs.
-   */
-  private class P_FormListener implements FormListener {
-
-    @Override
-    public void formChanged(FormEvent e) {
-      if (FormEvent.TYPE_CLOSED == e.getType()) {
-        IForm form = e.getForm();
-        removeExistingBreadCrumb(form);
-        detachFormListener(form);
-      }
-    }
-
-    private void detachFormListener(IForm form) {
-      form.removeFormListener(this);
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigationService.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigationService.java
deleted file mode 100644
index 11cb4f6..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/BreadCrumbsNavigationService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.IClientSession;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-
-/**
- * @since 3.9.0
- */
-public class BreadCrumbsNavigationService implements IBreadCrumbsNavigationService {
-  private String SESSION_DATA_KEY = "BreadCrumbsNavigationData";
-
-  @Override
-  public void install() {
-    install(null);
-  }
-
-  @Override
-  public void install(IDesktop desktop) {
-    if (getBreadCrumbsNavigation() != null) {
-      return;
-    }
-
-    IClientSession session = ClientSessionProvider.currentSession();
-    IBreadCrumbsNavigation data = createBreadCrumbsNavigation(desktop);
-    session.setData(SESSION_DATA_KEY, data);
-  }
-
-  @Override
-  public void uninstall() {
-    IClientSession session = ClientSessionProvider.currentSession();
-    session.setData(SESSION_DATA_KEY, null);
-  }
-
-  protected IBreadCrumbsNavigation createBreadCrumbsNavigation() {
-    return new BreadCrumbsNavigation();
-  }
-
-  protected IBreadCrumbsNavigation createBreadCrumbsNavigation(IDesktop desktop) {
-    return new BreadCrumbsNavigation(desktop);
-  }
-
-  @Override
-  public IBreadCrumbsNavigation getBreadCrumbsNavigation() {
-    IClientSession session = ClientSessionProvider.currentSession();
-    return (IBreadCrumbsNavigation) session.getData(SESSION_DATA_KEY);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumb.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumb.java
deleted file mode 100644
index 6bd5281..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumb.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public interface IBreadCrumb {
-
-  void activate();
-
-  IForm getForm();
-
-  boolean belongsTo(IForm form);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigation.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigation.java
deleted file mode 100644
index f287757..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigation.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import java.util.List;
-import java.util.Stack;
-
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public interface IBreadCrumbsNavigation {
-  void goHome();
-
-  void stepBack();
-
-  boolean isSteppingBackPossible();
-
-  boolean isGoingHomePossible();
-
-  IForm getCurrentNavigationForm();
-
-  List<IForm> getCurrentNavigationForms();
-
-  Stack<IBreadCrumb> getBreadCrumbs();
-
-  boolean containsFormInHistory(IForm form);
-
-  void addBreadCrumbsListener(BreadCrumbsListener listener);
-
-  void removeBreadCrumbsListener(BreadCrumbsListener listener);
-
-  void trackDisplayViewId(String displayViewId);
-
-  IDesktop getDesktop();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigationService.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigationService.java
deleted file mode 100644
index 93c75e6..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/IBreadCrumbsNavigationService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.platform.service.IService;
-
-/**
- * @since 3.9.0
- */
-public interface IBreadCrumbsNavigationService extends IService {
-
-  void install();
-
-  void install(IDesktop desktop);
-
-  void uninstall();
-
-  IBreadCrumbsNavigation getBreadCrumbsNavigation();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/OutlineChooserBreadCrumb.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/OutlineChooserBreadCrumb.java
deleted file mode 100644
index 2b7f9e8..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/navigation/OutlineChooserBreadCrumb.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.navigation;
-
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public class OutlineChooserBreadCrumb extends BreadCrumb {
-
-  public OutlineChooserBreadCrumb(IBreadCrumbsNavigation breadCrumbsNavigation, IForm form) {
-    super(breadCrumbsNavigation, form);
-  }
-
-  @Override
-  public void activate() {
-    super.activate();
-
-    //Clear any outline selection to make sure drill down works as expected again and again
-    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
-    for (IOutline outline : desktop.getAvailableOutlines()) {
-      outline.selectNode(null);
-    }
-    desktop.activateOutline((IOutline) null);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/services/text/TextProviderService.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/services/text/TextProviderService.java
deleted file mode 100644
index 413bc2e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/services/text/TextProviderService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.services.text;
-
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.shared.services.common.text.AbstractDynamicNlsTextProviderService;
-
-@Order(5025)
-public class TextProviderService extends AbstractDynamicNlsTextProviderService {
-
-  @Override
-  protected String getDynamicNlsBaseName() {
-    return "org.eclipse.scout.rt.client.mobile.texts.Texts";
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/AbstractDeviceTransformationHook.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/AbstractDeviceTransformationHook.java
deleted file mode 100644
index c630f6f..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/AbstractDeviceTransformationHook.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-
-public abstract class AbstractDeviceTransformationHook implements IDeviceTransformationHook {
-
-  @Override
-  public void beforeFormTransformation(IForm form) {
-  }
-
-  @Override
-  public void beforeFormFieldTransformation(IFormField formField) {
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationHooks.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationHooks.java
deleted file mode 100644
index e608b29..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationHooks.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.platform.util.BeanUtility;
-
-/**
- * <b>Warn: The hook concept is experimental and may be removed without notice.</b>
- * <p>
- * The hooks are ordered by following rules:<br>
- * <ul>
- * <li>If multiple hooks are registered for the same class every hook gets called</li>
- * <li>If a hook is registered for a concrete field (f.e. PersonForm.PersonField) and its template field (f.e.
- * AbstractPersonField then the concrete field (PersonField) has higher priority. If the concrete field gets transformed
- * the hooks for the template field are NOT called.</li>
- * </ul>
- * 
- * @since 3.10.0 M3
- */
-public class DeviceTransformationHooks {
-  private static List<TransformationHookRef> s_transformationHooks = new ArrayList<TransformationHookRef>();
-  private static final Object REGISTRY_LOCK = new Object();
-
-  public static void addFormTransformationHook(Class<? extends IForm> formClass, IDeviceTransformationHook formTransformationHook) {
-    addTransformationHook(formClass, formTransformationHook);
-  }
-
-  public static void removeFormTransformationHook(Class<? extends IForm> formClass, IDeviceTransformationHook formTransformationHook) {
-    removeTransformationHook(formClass, formTransformationHook);
-  }
-
-  /**
-   * @return null if no hooks are registered
-   */
-  public static List<IDeviceTransformationHook> getFormTransformationHooks(Class<? extends IForm> formClass) {
-    return getTransformationHooks(formClass);
-  }
-
-  public static void addFormFieldTransformationHook(Class<? extends IFormField> fieldClass, IDeviceTransformationHook transformationHook) {
-    addTransformationHook(fieldClass, transformationHook);
-  }
-
-  public static void removeFormFieldTransformationHook(Class<? extends IFormField> fieldClass, IDeviceTransformationHook formFieldTransformationHook) {
-    removeTransformationHook(fieldClass, formFieldTransformationHook);
-  }
-
-  /**
-   * @return null if no hooks are registered
-   */
-  public static List<IDeviceTransformationHook> getFormFieldTransformationHooks(Class<? extends IFormField> fieldClass) {
-    return getTransformationHooks(fieldClass);
-  }
-
-  private static void addTransformationHook(Class<?> refClass, IDeviceTransformationHook transformationHook) {
-    synchronized (REGISTRY_LOCK) {
-      int index = 0;
-      int insertPos = 0;
-      boolean added = false;
-      for (TransformationHookRef ref : s_transformationHooks) {
-        if (ref.getRefClass().equals(refClass)) {
-          ref.getHooks().add(transformationHook);
-          added = true;
-          break;
-        }
-        if (refClass.isAssignableFrom(ref.getRefClass())) {
-          int typeDistance = BeanUtility.computeTypeDistance(refClass, ref.getRefClass());
-          if (typeDistance > 0) {
-            insertPos = index + 1;
-          }
-        }
-        index++;
-      }
-      if (!added) {
-        s_transformationHooks.add(insertPos, new TransformationHookRef(refClass, transformationHook));
-      }
-    }
-  }
-
-  private static void removeTransformationHook(Class<?> refClass, IDeviceTransformationHook formFieldTransformationHook) {
-    synchronized (REGISTRY_LOCK) {
-      List<IDeviceTransformationHook> hooks = getTransformationHooks(refClass);
-      if (hooks != null) {
-        hooks.remove(formFieldTransformationHook);
-      }
-    }
-  }
-
-  /**
-   * @return null if no hooks are registered
-   */
-  private static List<IDeviceTransformationHook> getTransformationHooks(Class<?> refClass) {
-    synchronized (REGISTRY_LOCK) {
-      for (TransformationHookRef ref : s_transformationHooks) {
-        if (ref.getRefClass().isAssignableFrom(refClass)) {
-          return ref.getHooks();
-        }
-      }
-    }
-    return null;
-  }
-
-  private static class TransformationHookRef {
-    private Class<?> m_refClass;
-    private List<IDeviceTransformationHook> m_hooks;
-
-    public TransformationHookRef(Class<?> refClass, IDeviceTransformationHook hook) {
-      m_refClass = refClass;
-      m_hooks = new LinkedList<IDeviceTransformationHook>();
-      m_hooks.add(hook);
-    }
-
-    public Class<?> getRefClass() {
-      return m_refClass;
-    }
-
-    public List<IDeviceTransformationHook> getHooks() {
-      return m_hooks;
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationService.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationService.java
deleted file mode 100644
index b9c6248..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import org.eclipse.scout.rt.client.IClientSession;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
-
-/**
- * @since 3.9.0
- */
-public class DeviceTransformationService implements IDeviceTransformationService {
-  private String SESSION_DATA_KEY = "DeviceTransformationServiceData";
-
-  @Override
-  public void install() {
-    install(null);
-  }
-
-  @Override
-  public void install(IDesktop desktop) {
-    if (getDeviceTransformer() != null) {
-      return;
-    }
-
-    IClientSession session = ClientSessionProvider.currentSession();
-    IDeviceTransformer data = createDeviceTransformer(desktop);
-    session.setData(SESSION_DATA_KEY, data);
-  }
-
-  @Override
-  public void uninstall() {
-    IClientSession session = ClientSessionProvider.currentSession();
-    session.setData(SESSION_DATA_KEY, null);
-  }
-
-  protected IDeviceTransformer createDeviceTransformer(IDesktop desktop) {
-    if (UserAgentUtility.isTabletDevice()) {
-      return new TabletDeviceTransformer(desktop);
-    }
-    else {
-      return new MobileDeviceTransformer(desktop);
-    }
-  }
-
-  @Override
-  public IDeviceTransformer getDeviceTransformer() {
-    IClientSession session = ClientSessionProvider.currentSession();
-    return (IDeviceTransformer) session.getData(SESSION_DATA_KEY);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationHook.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationHook.java
deleted file mode 100644
index e4aa4c4..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationHook.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-
-/**
- * @since 3.10.0 M3
- */
-public interface IDeviceTransformationHook {
-  void beforeFormTransformation(IForm form);
-
-  void beforeFormFieldTransformation(IFormField formField);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformer.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformer.java
deleted file mode 100644
index 7626940..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.ITabBox;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-
-/**
- * @since 3.9.0
- */
-public interface IDeviceTransformer {
-
-  void transformDesktop();
-
-  void transformForm(IForm form);
-
-  void transformOutline(IOutline outline);
-
-  void transformPageDetailTable(ITable table);
-
-  void adaptFormHeaderLeftActions(IForm form, List<IMenu> menuList);
-
-  void adaptFormHeaderRightActions(IForm form, List<IMenu> menuList);
-
-  void adaptDesktopActions(Collection<IAction> actions);
-
-  void adaptDesktopOutlines(OrderedCollection<IOutline> outlines);
-
-  void notifyDesktopClosing();
-
-  void notifyTablePageLoaded(IPageWithTable<?> tablePage);
-
-  boolean acceptFormAddingToDesktop(IForm form);
-
-  boolean acceptMobileTabBoxTransformation(ITabBox tabBox);
-
-  /**
-   * @return a list of accepted view ids (IForm#VIEW_ID_* or null to accept all.
-   * @see {@link IForm}
-   */
-  List<String> getAcceptedViewIds();
-
-  DeviceTransformationConfig getDeviceTransformationConfig();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformer.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformer.java
deleted file mode 100644
index 9a59b90..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformer.java
+++ /dev/null
@@ -1,488 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.eclipse.scout.rt.client.mobile.navigation.AbstractMobileBackAction;
-import org.eclipse.scout.rt.client.mobile.navigation.IBreadCrumbsNavigation;
-import org.eclipse.scout.rt.client.mobile.navigation.IBreadCrumbsNavigationService;
-import org.eclipse.scout.rt.client.mobile.ui.action.ButtonWrappingAction;
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.button.IMobileButton;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeAdapter;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeEvent;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.OutlineEvent;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.FormUtility;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.IFormFieldVisitor;
-import org.eclipse.scout.rt.client.ui.form.fields.GridData;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.IBooleanField;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.placeholder.IPlaceholderField;
-import org.eclipse.scout.rt.client.ui.form.fields.sequencebox.ISequenceBox;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.ITabBox;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-
-/**
- * @since 3.9.0
- */
-public class MobileDeviceTransformer implements IDeviceTransformer {
-  private final Map<IForm, WeakReference<IForm>> m_modifiedForms = new WeakHashMap<IForm, WeakReference<IForm>>();
-  private IDesktop m_desktop;
-  private P_OutlineListener m_outlineListener;
-  private List<IOutline> m_outlines;
-  private ToolFormHandler m_toolFormHandler;
-  private boolean m_gridDataDirty;
-  private DeviceTransformationConfig m_deviceTransformationConfig;
-
-  public MobileDeviceTransformer(IDesktop desktop) {
-    if (desktop == null) {
-      desktop = ClientSessionProvider.currentSession().getDesktop();
-    }
-    m_desktop = desktop;
-    if (m_desktop == null) {
-      throw new IllegalArgumentException("No desktop found. Cannot create device transformer.");
-    }
-
-    m_deviceTransformationConfig = createDeviceTransformationConfig();
-    initTransformationConfig();
-
-    m_toolFormHandler = createToolFormHandler(desktop);
-
-    IBreadCrumbsNavigation breadCrumbsNavigation = BEANS.get(IBreadCrumbsNavigationService.class).getBreadCrumbsNavigation();
-    if (breadCrumbsNavigation != null) {
-      breadCrumbsNavigation.trackDisplayViewId(IForm.VIEW_ID_CENTER);
-    }
-  }
-
-  public MobileDeviceTransformer() {
-    this(null);
-  }
-
-  protected ToolFormHandler createToolFormHandler(IDesktop desktop) {
-    return new ToolFormHandler(getDesktop());
-  }
-
-  public ToolFormHandler getToolFormHandler() {
-    return m_toolFormHandler;
-  }
-
-  protected DeviceTransformationConfig createDeviceTransformationConfig() {
-    return new DeviceTransformationConfig();
-  }
-
-  @Override
-  public DeviceTransformationConfig getDeviceTransformationConfig() {
-    return m_deviceTransformationConfig;
-  }
-
-  protected void initTransformationConfig() {
-    List<IDeviceTransformation> transformations = new LinkedList<IDeviceTransformation>();
-
-    transformations.add(MobileDeviceTransformation.MOVE_FIELD_LABEL_TO_TOP);
-    transformations.add(MobileDeviceTransformation.MAKE_FIELD_SCALEABLE);
-    transformations.add(MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE);
-    transformations.add(MobileDeviceTransformation.REDUCE_GROUPBOX_COLUMNS_TO_ONE);
-    transformations.add(MobileDeviceTransformation.HIDE_PLACEHOLDER_FIELD);
-    transformations.add(MobileDeviceTransformation.DISABLE_FORM_CANCEL_CONFIRMATION);
-    transformations.add(MobileDeviceTransformation.DISPLAY_FORM_HEADER);
-    transformations.add(MobileDeviceTransformation.ADD_MISSING_BACK_ACTION_TO_FORM_HEADER);
-    transformations.add(MobileDeviceTransformation.DISPLAY_PAGE_TABLE);
-
-    for (IDeviceTransformation transformation : transformations) {
-      getDeviceTransformationConfig().enableTransformation(transformation);
-    }
-  }
-
-  @Override
-  public List<String> getAcceptedViewIds() {
-    List<String> viewIds = new LinkedList<String>();
-    viewIds.add(IForm.VIEW_ID_CENTER);
-
-    return viewIds;
-  }
-
-  @Override
-  public void notifyTablePageLoaded(IPageWithTable<?> tablePage) {
-    if (m_toolFormHandler != null) {
-      m_toolFormHandler.notifyTablePageLoaded(tablePage);
-    }
-  }
-
-  /**
-   * Remove keystrokes
-   */
-  @Override
-  public void adaptDesktopActions(Collection<IAction> actions) {
-    for (Iterator<IAction> iterator = actions.iterator(); iterator.hasNext();) {
-      IAction action = iterator.next();
-      if (action instanceof IKeyStroke) {
-        iterator.remove();
-      }
-    }
-  }
-
-  @Override
-  public void adaptDesktopOutlines(OrderedCollection<IOutline> outlines) {
-    m_outlines = outlines.getOrderedList();
-    m_outlineListener = new P_OutlineListener();
-    for (IOutline outline : m_outlines) {
-      outline.addTreeListener(m_outlineListener);
-    }
-  }
-
-  @Override
-  public void notifyDesktopClosing() {
-    if (m_outlines != null) {
-      for (IOutline outline : m_outlines) {
-        outline.removeTreeListener(m_outlineListener);
-      }
-      m_outlineListener = null;
-      m_outlines.clear();
-    }
-  }
-
-  @Override
-  public void transformDesktop() {
-  }
-
-  @Override
-  public void transformForm(IForm form) {
-    if (getDeviceTransformationConfig().isFormExcluded(form)) {
-      return;
-    }
-    List<IDeviceTransformationHook> hooks = DeviceTransformationHooks.getFormTransformationHooks(form.getClass());
-    if (hooks != null) {
-      for (IDeviceTransformationHook hook : hooks) {
-        hook.beforeFormTransformation(form);
-      }
-    }
-
-    m_gridDataDirty = false;
-
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.DISABLE_FORM_CANCEL_CONFIRMATION)) {
-      form.setAskIfNeedSave(false);
-    }
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.DISPLAY_FORM_HEADER)) {
-      AbstractMobileForm.setHeaderVisible(form, true);
-    }
-    if (form.getDisplayHint() == IForm.DISPLAY_HINT_VIEW) {
-      transformView(form);
-    }
-    transformFormFields(form);
-
-    if (isGridDataDirty()) {
-      FormUtility.rebuildFieldGrid(form, true);
-      m_gridDataDirty = false;
-    }
-  }
-
-  protected void transformView(IForm form) {
-    form.setDisplayViewId(IForm.VIEW_ID_CENTER);
-  }
-
-  @Override
-  public void transformOutline(IOutline outline) {
-    if (outline == null || outline.getRootNode() == null) {
-      return;
-    }
-
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.DISPLAY_OUTLINE_ROOT_NODE)) {
-      // Necessary to enable drilldown from top of the outline
-      outline.setRootNodeVisible(true);
-    }
-    outline.getContextMenu().setVisibleGranted(true);
-  }
-
-  @Override
-  public void transformPageDetailTable(ITable table) {
-    if (table == null) {
-      if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.DISPLAY_PAGE_TABLE)) {
-        // Do not allow closing the outline table because it breaks the navigation
-        makeSurePageDetailTableIsVisible();
-      }
-    }
-  }
-
-  public void transformPageDetailForm(IPage page) {
-    if (page.isDetailFormVisible() && page.getDetailForm() != null) {
-      transformForm(page.getDetailForm());
-    }
-  }
-
-  @Override
-  public boolean acceptFormAddingToDesktop(IForm form) {
-    return true;
-  }
-
-  private void makeSurePageDetailTableIsVisible() {
-    final IOutline outline = getDesktop().getOutline();
-    if (outline == null) {
-      return;
-    }
-    final IPage<?> activePage = outline.getActivePage();
-    if (activePage == null || activePage.isTableVisible() || isPageDetailTableAllowedToBeClosed(activePage)) {
-      return;
-    }
-    activePage.setTableVisible(true);
-    outline.setDetailTable(activePage.getTable());
-  }
-
-  protected boolean isPageDetailTableAllowedToBeClosed(IPage<?> activePage) {
-    return activePage.isLeaf();
-  }
-
-  protected void transformFormFields(IForm form) {
-    WeakReference<IForm> formRef = m_modifiedForms.get(form);
-    if (formRef != null) {
-      return;
-    }
-
-    form.visitFields(new IFormFieldVisitor() {
-      @Override
-      public boolean visitField(IFormField field, int level, int fieldIndex) {
-        if (getDeviceTransformationConfig().isFieldExcluded(field)) {
-          return true;
-        }
-
-        transformFormField(field);
-
-        return true;
-      }
-    });
-
-    if (!getDeviceTransformationConfig().isFieldExcluded(form.getRootGroupBox())) {
-      transformMainBox(form.getRootGroupBox());
-    }
-
-    //mark form as modified
-    m_modifiedForms.put(form, new WeakReference<IForm>(form));
-  }
-
-  protected void transformFormField(IFormField field) {
-    List<IDeviceTransformationHook> hooks = DeviceTransformationHooks.getFormFieldTransformationHooks(field.getClass());
-    if (hooks != null) {
-      for (IDeviceTransformationHook hook : hooks) {
-        hook.beforeFormFieldTransformation(field);
-      }
-    }
-
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MOVE_FIELD_LABEL_TO_TOP, field)) {
-      moveLabelToTop(field);
-    }
-
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MAKE_FIELD_SCALEABLE, field)) {
-      makeFieldScalable(field);
-    }
-
-    if (field instanceof IGroupBox) {
-      transformGroupBox((IGroupBox) field);
-    }
-    else if (field instanceof IPlaceholderField) {
-      transformPlaceholderField((IPlaceholderField) field);
-    }
-  }
-
-  /**
-   * Makes sure weightX is set to 1 which makes the field scalable.
-   * <p>
-   * Reason:<br>
-   * The width of the field should be adjusted according to the display width, otherwise it may be too big to be
-   * displayed. <br>
-   * Additionally, since we use a one column layout, setting weightX to 0 might destroy the layout because it affects
-   * all the fields in the groupBox.
-   */
-  protected void makeFieldScalable(IFormField field) {
-    //Since a sequencebox contains several fields it's very risky to modify the gridData because it could make the fields too big or too small.
-    if (field.getParentField() instanceof ISequenceBox) {
-      return;
-    }
-
-    //Make sure weightX is set to 1 so the field grows and shrinks and does not break the 1 column layout
-    GridData gridDataHints = field.getGridDataHints();
-    if (gridDataHints.weightX == 0) {
-      gridDataHints.weightX = 1;
-      field.setGridDataHints(gridDataHints);
-
-      markGridDataDirty();
-    }
-  }
-
-  protected void moveLabelToTop(IFormField field) {
-    if (field instanceof IGroupBox) {
-      return;
-    }
-
-    if (IFormField.LABEL_POSITION_ON_FIELD == field.getLabelPosition()) {
-      return;
-    }
-
-    //Do not modify the labels inside a sequencebox
-    if (field.getParentField() instanceof ISequenceBox) {
-      return;
-    }
-
-    field.setLabelPosition(IFormField.LABEL_POSITION_TOP);
-
-    // The actual label of the boolean field is on the right side and position=top has no effect.
-    // Removing the label actually removes the place on the left side so that it gets aligned to the other fields.
-    if (field instanceof IBooleanField) {
-      field.setLabelVisible(false);
-    }
-  }
-
-  protected void transformMainBox(IGroupBox groupBox) {
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE, groupBox)) {
-      makeGroupBoxScrollable(groupBox);
-    }
-  }
-
-  protected void makeGroupBoxScrollable(IGroupBox groupBox) {
-    //Detail forms will be displayed as inner forms on page forms.
-    //Make sure these inner forms are not scrollable because the page form already is
-    if (groupBox.getForm() == getDesktop().getPageDetailForm()) {
-      if (groupBox.isScrollable().isTrue()) {
-        groupBox.setScrollable(false);
-        markGridDataDirty();
-      }
-      return;
-    }
-
-    if (!groupBox.isScrollable().isTrue()) {
-      groupBox.setScrollable(true);
-
-      //GridDataHints have been modified by setScrollable. Update the actual gridData with those hints.
-      markGridDataDirty();
-    }
-  }
-
-  protected void transformGroupBox(IGroupBox groupBox) {
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.REDUCE_GROUPBOX_COLUMNS_TO_ONE, groupBox)) {
-      groupBox.setGridColumnCountHint(1);
-    }
-  }
-
-  /**
-   * Makes placeholder fields invisible since they just waste space on 1 column layouts
-   */
-  protected void transformPlaceholderField(IPlaceholderField field) {
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.HIDE_PLACEHOLDER_FIELD, field)) {
-      field.setVisible(false);
-    }
-  }
-
-  protected IDesktop getDesktop() {
-    return m_desktop;
-  }
-
-  @Override
-  public boolean acceptMobileTabBoxTransformation(ITabBox tabBox) {
-    IGroupBox mainBox = tabBox.getForm().getRootGroupBox();
-    if (tabBox.getParentField() == mainBox) {
-      return !(mainBox.getControlFields().get(0) == tabBox);
-    }
-
-    return false;
-  }
-
-  /**
-   * Adds a close button to the tool form.
-   * <p>
-   * Adds a back button if there is no other button on the left side which is able to close the form.
-   */
-  @Override
-  public void adaptFormHeaderLeftActions(IForm form, List<IMenu> menuList) {
-    if (MobileDesktopUtility.isToolForm(form) && !containsCloseAction(menuList)) {
-      menuList.add(new ToolFormCloseAction(form));
-    }
-
-    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.ADD_MISSING_BACK_ACTION_TO_FORM_HEADER, form) && !containsCloseAction(menuList)) {
-      menuList.add(new P_BackAction());
-    }
-  }
-
-  @Override
-  public void adaptFormHeaderRightActions(IForm form, List<IMenu> menuList) {
-  }
-
-  protected boolean containsCloseAction(List<IMenu> menuList) {
-    if (menuList == null) {
-      return false;
-    }
-
-    for (IMenu action : menuList) {
-      if (action instanceof ToolFormCloseAction) {
-        return true;
-      }
-      else if (action instanceof ButtonWrappingAction) {
-        IButton wrappedButton = ((ButtonWrappingAction) action).getWrappedButton();
-        switch (wrappedButton.getSystemType()) {
-          case IButton.SYSTEM_TYPE_CANCEL:
-          case IButton.SYSTEM_TYPE_CLOSE:
-          case IButton.SYSTEM_TYPE_OK:
-          case IMobileButton.SYSTEM_TYPE_BACK:
-            if (wrappedButton.isVisible() && wrappedButton.isEnabled()) {
-              return true;
-            }
-        }
-      }
-    }
-
-    return false;
-  }
-
-  protected boolean isGridDataDirty() {
-    return m_gridDataDirty;
-  }
-
-  protected void markGridDataDirty() {
-    m_gridDataDirty = true;
-  }
-
-  private class P_BackAction extends AbstractMobileBackAction {
-
-  }
-
-  private class P_OutlineListener extends TreeAdapter {
-
-    @Override
-    public void treeChanged(TreeEvent e) {
-      if (OutlineEvent.TYPE_PAGE_CHANGED == e.getType()) {
-        onPageChanged((OutlineEvent) e);
-      }
-    }
-
-    protected void onPageChanged(OutlineEvent e) {
-      IPage page = (IPage) e.getChildNode();
-      transformPageDetailForm(page);
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/TabletDeviceTransformer.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/TabletDeviceTransformer.java
deleted file mode 100644
index 105ffed..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/TabletDeviceTransformer.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.ITabBox;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-
-/**
- * @since 3.9.0
- */
-public class TabletDeviceTransformer implements IDeviceTransformer {
-  private IDesktop m_desktop;
-
-  public TabletDeviceTransformer() {
-    this(null);
-  }
-
-  public TabletDeviceTransformer(IDesktop desktop) {
-    if (desktop == null) {
-      desktop = ClientSessionProvider.currentSession().getDesktop();
-    }
-    m_desktop = desktop;
-    if (m_desktop == null) {
-      throw new IllegalArgumentException("No desktop found. Cannot create device transformer.");
-    }
-  }
-
-  @Override
-  public void transformDesktop() {
-    m_desktop.setCacheSplitterPosition(false);
-  }
-
-  @Override
-  public void transformForm(IForm form) {
-  }
-
-  @Override
-  public void transformOutline(IOutline outline) {
-    outline.setBreadcrumbEnabled(true);
-  }
-
-  @Override
-  public void transformPageDetailTable(ITable table) {
-  }
-
-  @Override
-  public void adaptFormHeaderLeftActions(IForm form, List<IMenu> menuList) {
-  }
-
-  @Override
-  public void adaptFormHeaderRightActions(IForm form, List<IMenu> menuList) {
-  }
-
-  @Override
-  public void adaptDesktopActions(Collection<IAction> actions) {
-  }
-
-  @Override
-  public void adaptDesktopOutlines(OrderedCollection<IOutline> outlines) {
-  }
-
-  @Override
-  public void notifyDesktopClosing() {
-  }
-
-  @Override
-  public void notifyTablePageLoaded(IPageWithTable<?> tablePage) {
-  }
-
-  @Override
-  public boolean acceptFormAddingToDesktop(IForm form) {
-    return true;
-  }
-
-  @Override
-  public boolean acceptMobileTabBoxTransformation(ITabBox tabBox) {
-    return false;
-  }
-
-  @Override
-  public List<String> getAcceptedViewIds() {
-    return null;
-  }
-
-  @Override
-  public DeviceTransformationConfig getDeviceTransformationConfig() {
-    return null;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormCloseAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormCloseAction.java
deleted file mode 100644
index 5027e5a..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormCloseAction.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.shared.TEXTS;
-
-public class ToolFormCloseAction extends AbstractMenu {
-  private IForm m_form;
-
-  public ToolFormCloseAction(IForm form) {
-    m_form = form;
-  }
-
-  @Override
-  protected String getConfiguredText() {
-    return TEXTS.get("CloseButton");
-  }
-
-  @Override
-  protected void execAction() {
-    MobileDesktopUtility.closeToolForm(m_form);
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormHandler.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormHandler.java
deleted file mode 100644
index 37ffd65..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/ToolFormHandler.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.TableRowForm;
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.TabForm;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeAdapter;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public class ToolFormHandler {
-  private P_DesktopListener m_desktopListener;
-  private P_OutlineListener m_outlineListener;
-  private IOutline m_activeOutline;
-  private IDesktop m_desktop;
-  private boolean m_closeToolFormsAfterTablePageLoaded;
-
-  public ToolFormHandler(IDesktop desktop) {
-    m_desktop = desktop;
-    m_desktopListener = new P_DesktopListener();
-    m_desktop.addDesktopListener(m_desktopListener);
-    m_closeToolFormsAfterTablePageLoaded = true;
-  }
-
-  private void destroy() {
-    if (m_desktopListener != null) {
-      getDesktop().removeDesktopListener(m_desktopListener);
-      m_desktopListener = null;
-    }
-  }
-
-  public IDesktop getDesktop() {
-    return m_desktop;
-  }
-
-  protected boolean execCloseToolFormsOnFormOpen(IForm form) {
-    if (IForm.DISPLAY_HINT_VIEW == form.getDisplayHint() && !MobileDesktopUtility.isToolForm(form)) {
-      return !(form instanceof TableRowForm) && !(form instanceof TabForm);
-    }
-
-    return false;
-  }
-
-  public boolean isCloseToolFormsAfterTablePageLoaded() {
-    return m_closeToolFormsAfterTablePageLoaded;
-  }
-
-  /**
-   * Set to true to to close tool forms after a table page has been loaded, which happens after a search or after a
-   * bookmark activation.
-   */
-  public void setCloseToolFormsAfterTablePageLoaded(boolean closeToolFormsAfterTablePageLoaded) {
-    m_closeToolFormsAfterTablePageLoaded = closeToolFormsAfterTablePageLoaded;
-  }
-
-  /**
-   * This is a delegate and needs to be explicitly called.<br>
-   * It's purpose is to close tool forms after a search or after a bookmark activation.
-   */
-  public void notifyTablePageLoaded(IPageWithTable<?> tablePage) {
-    if (isCloseToolFormsAfterTablePageLoaded()) {
-      MobileDesktopUtility.closeAllToolForms();
-    }
-  }
-
-  private class P_DesktopListener implements DesktopListener {
-
-    @Override
-    public void desktopChanged(DesktopEvent e) {
-
-      switch (e.getType()) {
-        case DesktopEvent.TYPE_FORM_SHOW: {
-          handleFormAdded(e);
-          break;
-        }
-        case DesktopEvent.TYPE_DESKTOP_CLOSED: {
-          destroy();
-          break;
-        }
-        case DesktopEvent.TYPE_OUTLINE_CHANGED: {
-          handleOutlineChanged(e);
-        }
-        default:
-          break;
-      }
-    }
-
-    private void handleOutlineChanged(DesktopEvent e) {
-      IOutline outline = e.getOutline();
-
-      if (m_activeOutline != null) {
-        m_activeOutline.removeTreeListener(m_outlineListener);
-      }
-
-      if (outline != null) {
-        if (m_outlineListener == null) {
-          m_outlineListener = new P_OutlineListener();
-        }
-
-        outline.addTreeListener(m_outlineListener);
-      }
-
-      m_activeOutline = outline;
-    }
-
-    private void handleFormAdded(DesktopEvent e) {
-      IForm form = e.getForm();
-      if (execCloseToolFormsOnFormOpen(form)) {
-        //Close tool form if another view is opened
-        MobileDesktopUtility.closeAllToolForms();
-      }
-
-    }
-
-  }
-
-  private class P_OutlineListener extends TreeAdapter {
-
-    @Override
-    public void treeChanged(TreeEvent e) {
-      switch (e.getType()) {
-        case TreeEvent.TYPE_NODES_SELECTED: {
-          handleNodesSelected(e);
-          break;
-        }
-      }
-    }
-
-    private void handleNodesSelected(TreeEvent event) {
-      MobileDesktopUtility.closeAllToolForms();
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ActionButtonBarUtility.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ActionButtonBarUtility.java
deleted file mode 100644
index 7e8b950..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ActionButtonBarUtility.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.action;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.IMobileAction;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.AutoLeafPageWithNodes;
-import org.eclipse.scout.rt.client.ui.action.ActionUtility;
-import org.eclipse.scout.rt.client.ui.action.IActionFilter;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.action.menu.TableMenuType;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-
-/**
- * @since 3.9.0
- */
-public class ActionButtonBarUtility {
-
-  public static List<IMobileAction> convertButtonsToActions(List<IButton> buttons) {
-    List<IMobileAction> menuList = new ArrayList<IMobileAction>(buttons.size());
-    for (IButton button : buttons) {
-      IMobileAction action = convertButtonToAction(button);
-      if (action != null) {
-        menuList.add(action);
-      }
-    }
-
-    return menuList;
-  }
-
-  public static IMobileAction convertButtonToAction(IButton button) {
-    if (button == null) {
-      return null;
-    }
-
-    ButtonWrappingAction mAction = new ButtonWrappingAction(button);
-    mAction.initAction();
-    return mAction;
-  }
-
-  /**
-   * If there are empty space menus distribute the row menus so that the menus alternate and the most important are on
-   * top, starting with a empty space menu
-   */
-  public static void distributeRowActions(List<IMenu> menuList, List<IMenu> emptySpaceMenus, List<IMenu> rowMenuList) {
-    if (emptySpaceMenus == null) {
-      return;
-    }
-
-    for (IMenu emptySpaceMenu : emptySpaceMenus) {
-      if (rowMenuList.size() == 0) {
-        break;
-      }
-
-      int index = menuList.indexOf(emptySpaceMenu) + 1;
-      IMenu rowMenu = rowMenuList.get(0);
-      menuList.add(index, rowMenu);
-      rowMenuList.remove(rowMenu);
-    }
-  }
-
-  /**
-   * Fetches the actions of the given page (tree node and table row menus).
-   */
-  public static List<IMenu> fetchPageActions(IPage<?> page) {
-    List<IMenu> pageActions = new LinkedList<IMenu>();
-    if (page.getTree() != null) {
-      List<IMenu> menusForPage = page.getOutline().getMenusForPage(page);
-      pageActions.addAll(menusForPage);
-      if (page instanceof AutoLeafPageWithNodes) {
-        //AutoLeafPage has no parent so the table row actions are not fetched by the regular way (see AbstractOutline#P_OutlineListener).
-        //Instead we directly fetch the table row actions
-        IActionFilter actionFilter = ActionUtility.createMenuFilterMenuTypes(CollectionUtility.hashSet(TableMenuType.SingleSelection), true);
-        pageActions.addAll(ActionUtility.getActions(((AutoLeafPageWithNodes) page).getTableRow().getTable().getMenus(), actionFilter));
-      }
-    }
-
-    return pageActions;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonToActionPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonToActionPropertyDelegator.java
deleted file mode 100644
index a5f31df..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonToActionPropertyDelegator.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.action;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.PropertyDelegator;
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-
-public class ButtonToActionPropertyDelegator extends PropertyDelegator<IButton, IAction> {
-
-  public ButtonToActionPropertyDelegator(IButton sender, IAction receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setVisible(getSender().isVisible());
-    if (!getSender().isVisible()) {
-      //Since AbstractFormField#calculateVisibleInternal may ignore this property only set it if it hasn't been ignored (to not override those rules)
-      getReceiver().setVisibleGranted(getSender().isVisibleGranted());
-    }
-    getReceiver().setEnabled(getSender().isEnabled());
-    if (!getSender().isEnabled()) {
-      //Since AbstractFormField#calculateEnabled may ignore this property only set it if it hasn't been ignored (to not override those rules)
-      getReceiver().setEnabledGranted(getSender().isEnabledGranted());
-    }
-    getReceiver().setIconId(getSender().getIconId());
-    getReceiver().setText(getSender().getLabel());
-    getReceiver().setTooltipText(getSender().getTooltipText());
-    getReceiver().setToggleAction(getSender().getDisplayStyle() == IButton.DISPLAY_STYLE_TOGGLE);
-    getReceiver().setSelected(getSender().isSelected());
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    if (name.equals(IFormField.PROP_ENABLED)) {
-      getReceiver().setEnabled(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IFormField.PROP_LABEL)) {
-      getReceiver().setText((String) newValue);
-    }
-    else if (name.equals(IFormField.PROP_TOOLTIP_TEXT)) {
-      getReceiver().setTooltipText((String) newValue);
-    }
-    else if (name.equals(IFormField.PROP_VISIBLE)) {
-      getReceiver().setVisible(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IButton.PROP_ICON_ID)) {
-      getReceiver().setIconId((String) newValue);
-    }
-    else if (name.equals(IButton.PROP_SELECTED)) {
-      getReceiver().setSelected(((Boolean) newValue).booleanValue());
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonWrappingAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonWrappingAction.java
deleted file mode 100644
index 7b4440e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/action/ButtonWrappingAction.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.action;
-
-import java.beans.PropertyChangeEvent;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileAction;
-import org.eclipse.scout.rt.client.ui.action.tree.IActionNode;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-
-/**
- * A {@link IActionNode} which wraps a {@link IButton}. <br/>
- * {@link PropertyChangeEvent}s fired by the button are delegated to the action
- * 
- * @since 3.9.0
- */
-public class ButtonWrappingAction extends AbstractMobileAction {
-  private ButtonToActionPropertyDelegator m_propertyDelegator;
-
-  public ButtonWrappingAction(IButton wrappedButton) {
-    super(false);
-
-    m_propertyDelegator = new ButtonToActionPropertyDelegator(wrappedButton, this);
-
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execAction() {
-    getWrappedButton().doClick();
-  }
-
-  @Override
-  protected void execSelectionChanged(boolean selection) {
-    getWrappedButton().setSelected(selection);
-  }
-
-  public IButton getWrappedButton() {
-    return m_propertyDelegator.getSender();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractMobileTable.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractMobileTable.java
deleted file mode 100644
index 7654b18..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractMobileTable.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import org.eclipse.scout.rt.client.context.ClientRunContexts;
-import org.eclipse.scout.rt.client.job.ModelJobs;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.columns.IRowSummaryColumn;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.DefaultTableRowFormProvider;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.ITableRowForm;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.ITableRowFormProvider;
-import org.eclipse.scout.rt.client.ui.basic.table.AbstractTable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableUIFacade;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
-
-/**
- * @since 3.9.0
- */
-public abstract class AbstractMobileTable extends AbstractTable implements IMobileTable {
-  private DrillDownStyleMap m_drillDownStyleMap;
-  private int m_tableRowFormDisplayHint;
-  private String m_tableRowFormDisplayViewId;
-
-  public AbstractMobileTable() {
-    this(true);
-  }
-
-  public AbstractMobileTable(boolean callInitializer) {
-    super(callInitializer);
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_drillDownStyleMap = new DrillDownStyleMap();
-    setPagingEnabled(getConfiguredPagingEnabled());
-    setPageSize(getConfiguredPageSize());
-    setAutoCreateTableRowForm(execIsAutoCreateTableRowForm());
-    setDefaultDrillDownStyle(execComputeDefaultDrillDownStyle());
-    setTableRowFormProvider(createTableRowFormProvider());
-  }
-
-  @Override
-  public boolean isPagingEnabled() {
-    return propertySupport.getPropertyBool(PROP_PAGING_ENABLED);
-  }
-
-  @Override
-  public void setPagingEnabled(boolean enabled) {
-    propertySupport.setPropertyBool(PROP_PAGING_ENABLED, enabled);
-  }
-
-  @Override
-  public int getPageSize() {
-    return propertySupport.getPropertyInt(PROP_PAGE_SIZE);
-  }
-
-  @Override
-  public void setPageSize(int pageSize) {
-    propertySupport.setPropertyInt(PROP_PAGE_SIZE, pageSize);
-  }
-
-  @Override
-  public int getPageIndex() {
-    return propertySupport.getPropertyInt(PROP_PAGE_INDEX);
-  }
-
-  @Override
-  public void setPageIndex(int index) {
-    propertySupport.setPropertyInt(PROP_PAGE_INDEX, index);
-  }
-
-  @Override
-  public int getPageCount() {
-    if (getRowCount() == 0) {
-      return 1;
-    }
-    return new Double(Math.ceil((double) getRowCount() / (double) getPageSize())).intValue();
-  }
-
-  @Override
-  public ITableRowFormProvider getTableRowFormProvider() {
-    return (ITableRowFormProvider) propertySupport.getProperty(PROP_TABLE_ROW_FORM_PROVIDER);
-  }
-
-  @Override
-  public void setTableRowFormProvider(ITableRowFormProvider provider) {
-    propertySupport.setProperty(PROP_TABLE_ROW_FORM_PROVIDER, provider);
-  }
-
-  @Override
-  public boolean isAutoCreateTableRowForm() {
-    return propertySupport.getPropertyBool(PROP_AUTO_CREATE_TABLE_ROW_FORM);
-  }
-
-  @Override
-  public void setAutoCreateTableRowForm(boolean autoCreateTableRowForm) {
-    propertySupport.setPropertyBool(PROP_AUTO_CREATE_TABLE_ROW_FORM, autoCreateTableRowForm);
-  }
-
-  @Override
-  public String getDefaultDrillDownStyle() {
-    return propertySupport.getPropertyString(PROP_DEFAULT_DRILL_DOWN_STYLE);
-  }
-
-  @Override
-  public void setDefaultDrillDownStyle(String defaultDrillDownStyle) {
-    propertySupport.setPropertyString(PROP_DEFAULT_DRILL_DOWN_STYLE, defaultDrillDownStyle);
-  }
-
-  public void putDrillDownStyle(ITableRow row, String drillDownStyle) {
-    m_drillDownStyleMap.put(row, drillDownStyle);
-  }
-
-  public String getDrillDownStyle(ITableRow row) {
-    return m_drillDownStyleMap.get(row);
-  }
-
-  public int getTableRowFormDisplayHint() {
-    return m_tableRowFormDisplayHint;
-  }
-
-  public void setTableRowFormDisplayHint(int tableRowFormDisplayHint) {
-    m_tableRowFormDisplayHint = tableRowFormDisplayHint;
-  }
-
-  public String getTableRowFormDisplayViewId() {
-    return m_tableRowFormDisplayViewId;
-  }
-
-  public void setTableRowFormDisplayViewId(String tableRowFormDisplayViewId) {
-    m_tableRowFormDisplayViewId = tableRowFormDisplayViewId;
-  }
-
-  protected ITableRowFormProvider createTableRowFormProvider() {
-    return new DefaultTableRowFormProvider();
-  }
-
-  @Override
-  public void setDrillDownStyleMap(DrillDownStyleMap drillDownStyleMap) {
-    m_drillDownStyleMap = drillDownStyleMap;
-    if (m_drillDownStyleMap == null) {
-      m_drillDownStyleMap = new DrillDownStyleMap();
-    }
-  }
-
-  @Override
-  public DrillDownStyleMap getDrillDownStyleMap() {
-    return m_drillDownStyleMap;
-  }
-
-  public static void setAutoCreateRowForm(ITable table, boolean autoCreateRowForm) {
-    table.setProperty(IMobileTable.PROP_AUTO_CREATE_TABLE_ROW_FORM, autoCreateRowForm);
-  }
-
-  public static boolean isAutoCreateRowForm(ITable table) {
-    Boolean b = (Boolean) table.getProperty(PROP_AUTO_CREATE_TABLE_ROW_FORM);
-    return b != null ? b.booleanValue() : false;
-  }
-
-  public static void setDrillDownStyleMap(ITable table, DrillDownStyleMap drillDownStyles) {
-    table.setProperty(IMobileTable.PROP_DRILL_DOWN_STYLE_MAP, drillDownStyles);
-  }
-
-  public static DrillDownStyleMap getDrillDownStyleMap(ITable table) {
-    return (DrillDownStyleMap) table.getProperty(IMobileTable.PROP_DRILL_DOWN_STYLE_MAP);
-  }
-
-  public static void setDefaultDrillDownStyle(ITable table, String defaultDrillDownStyle) {
-    table.setProperty(IMobileTable.PROP_DEFAULT_DRILL_DOWN_STYLE, defaultDrillDownStyle);
-  }
-
-  public static String getDefaultDrillDownStyle(ITable table) {
-    return (String) table.getProperty(IMobileTable.PROP_DEFAULT_DRILL_DOWN_STYLE);
-  }
-
-  public static boolean isPagingEnabled(ITable table) {
-    Boolean b = (Boolean) table.getProperty(PROP_PAGING_ENABLED);
-    return b != null ? b.booleanValue() : false;
-  }
-
-  public static void setPagingEnabled(ITable table, boolean enabled) {
-    table.setProperty(IMobileTable.PROP_PAGING_ENABLED, enabled);
-  }
-
-  public static int getPageSize(ITable table) {
-    Number n = (Number) table.getProperty(PROP_PAGE_SIZE);
-    return n != null ? n.intValue() : 0;
-  }
-
-  public static void setPageSize(ITable table, int pageSize) {
-    table.setProperty(IMobileTable.PROP_PAGE_SIZE, pageSize);
-  }
-
-  public static int getPageIndex(ITable table) {
-    Number n = (Number) table.getProperty(PROP_PAGE_INDEX);
-    return n != null ? n.intValue() : 0;
-  }
-
-  public static void setPageIndex(ITable table, int index) {
-    table.setProperty(IMobileTable.PROP_PAGE_INDEX, index);
-  }
-
-  public static ITableRowFormProvider getTableRowFormProvider(ITable table) {
-    return (ITableRowFormProvider) table.getProperty(PROP_TABLE_ROW_FORM_PROVIDER);
-  }
-
-  public static void setTableRowFormProvider(ITable table, ITableRowFormProvider provider) {
-    table.setProperty(PROP_TABLE_ROW_FORM_PROVIDER, provider);
-  }
-
-  protected boolean getConfiguredPagingEnabled() {
-    return true;
-  }
-
-  protected int getConfiguredPageSize() {
-    return 50;
-  }
-
-  protected boolean execIsAutoCreateTableRowForm() {
-    if (isCheckable()) {
-      return false;
-    }
-
-    return true;
-  }
-
-  protected String execComputeDefaultDrillDownStyle() {
-    if (isCheckable()) {
-      return IRowSummaryColumn.DRILL_DOWN_STYLE_NONE;
-    }
-
-    return IRowSummaryColumn.DRILL_DOWN_STYLE_ICON;
-  }
-
-  protected void startTableRowForm(ITableRow row) {
-    ITableRowForm form = getTableRowFormProvider().createTableRowForm(row);
-    form.setDisplayHint(getTableRowFormDisplayHint());
-    form.setDisplayViewId(getTableRowFormDisplayViewId());
-    form.setModal(IForm.DISPLAY_HINT_DIALOG == form.getDisplayHint());
-    form.start();
-    if (IRowSummaryColumn.DRILL_DOWN_STYLE_ICON.equals(getDrillDownStyle(row))) {
-      form.addFormListener(new ClearTableSelectionFormCloseListener(this));
-    }
-  }
-
-  protected void clearSelectionDelayed() {
-    ModelJobs.schedule(new IRunnable() {
-      @Override
-      public void run() throws Exception {
-        clearSelection();
-      }
-    }, ModelJobs.newInput(ClientRunContexts.copyCurrent()));
-  }
-
-  protected void clearSelection() {
-    selectRow(null);
-  }
-
-  @Override
-  protected ITableUIFacade createUIFacade() {
-    return new P_MobileTableUIFacade();
-  }
-
-  @Override
-  public IMobileTableUiFacade getUIFacade() {
-    return (IMobileTableUiFacade) super.getUIFacade();
-  }
-
-  protected class P_MobileTableUIFacade extends P_TableUIFacade implements IMobileTableUiFacade {
-
-    @Override
-    public void setPageIndexFromUi(int pageIndex) {
-      setPageIndex(pageIndex);
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractPagingSupport.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractPagingSupport.java
deleted file mode 100644
index ee5c7fd..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/AbstractPagingSupport.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-
-/**
- * @since 3.9.0
- */
-public abstract class AbstractPagingSupport {
-
-  private int m_pageSize;
-  private int m_pageIndex;
-  private int m_currentPageStartRowIndex;
-  private IMobileTable m_table;
-  private ITableRow m_nextElementsTableRow;
-  private ITableRow m_previousElementsTableRow;
-
-  public AbstractPagingSupport(IMobileTable table) {
-    m_table = table;
-    initProperties();
-  }
-
-  protected void initProperties() {
-    setPageSize(m_table.getPageSize());
-    setPageIndex(m_table.getPageIndex());
-  }
-
-  public List<ITableRow> getElementsOfCurrentPage(List<? extends ITableRow> rows) {
-    initProperties();
-    if (m_pageSize <= 0 || m_currentPageStartRowIndex < 0 || m_currentPageStartRowIndex >= rows.size()) {
-      return CollectionUtility.arrayList(rows);
-    }
-    if (m_currentPageStartRowIndex == 0 && rows.size() < m_pageSize) {
-      return CollectionUtility.arrayList(rows);
-    }
-
-    int currentPageEndRowIndex = Math.min(m_currentPageStartRowIndex + m_pageSize, rows.size()) - 1;
-    int currentPageSize = currentPageEndRowIndex - m_currentPageStartRowIndex + 1;
-    List<ITableRow> currentPage = new ArrayList<ITableRow>();
-    for (int i = m_currentPageStartRowIndex; i <= currentPageEndRowIndex; i++) {
-      currentPage.add(rows.get(i));
-    }
-
-    if (m_currentPageStartRowIndex > 0) {
-      m_previousElementsTableRow = createPreviousElementsTableRow();
-      currentPage.add(0, m_previousElementsTableRow);
-    }
-
-    if (currentPageSize >= m_pageSize && m_currentPageStartRowIndex + m_pageSize < rows.size()) {
-      m_nextElementsTableRow = createNextElementsTableRow();
-      currentPage.add(m_nextElementsTableRow);
-    }
-
-    return currentPage;
-  }
-
-  protected ITableRow createPreviousElementsTableRow() {
-    return new PagingTableRow(m_table.getColumnSet(), PagingTableRow.Type.back);
-  }
-
-  protected ITableRow createNextElementsTableRow() {
-    return new PagingTableRow(m_table.getColumnSet(), PagingTableRow.Type.forward);
-  }
-
-  public int getCurrentPageStartRowIndex() {
-    return m_currentPageStartRowIndex;
-  }
-
-  public int getPageIndex() {
-    return m_pageIndex;
-  }
-
-  protected void setPageSize(int pageSize) {
-    m_pageSize = pageSize;
-    m_currentPageStartRowIndex = m_pageIndex * m_pageSize;
-  }
-
-  protected void setPageIndex(int pageIndex) {
-    m_pageIndex = pageIndex;
-    m_currentPageStartRowIndex = m_pageIndex * m_pageSize;
-  }
-
-  public int getPageSize() {
-    return m_pageSize;
-  }
-
-  public ITableRow getPreviousElementsTableRow() {
-    return m_previousElementsTableRow;
-  }
-
-  public ITableRow getNextElementsTableRow() {
-    return m_nextElementsTableRow;
-  }
-
-  public IMobileTable getTable() {
-    return m_table;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/ClearTableSelectionFormCloseListener.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/ClearTableSelectionFormCloseListener.java
deleted file mode 100644
index c93885d..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/ClearTableSelectionFormCloseListener.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.form.FormEvent;
-import org.eclipse.scout.rt.client.ui.form.FormListener;
-
-/**
- * @since 3.9.0
- */
-public class ClearTableSelectionFormCloseListener implements FormListener {
-  private ITable m_table;
-
-  public ClearTableSelectionFormCloseListener(ITable table) {
-    m_table = table;
-  }
-
-  @Override
-  public void formChanged(FormEvent e) {
-    if (FormEvent.TYPE_CLOSED == e.getType()) {
-      handleFormClosed();
-    }
-  }
-
-  protected void handleFormClosed() {
-    clearSelection();
-  }
-
-  protected void clearSelection() {
-    m_table.selectRow(null);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/DrillDownStyleMap.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/DrillDownStyleMap.java
deleted file mode 100644
index b10fa38..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/DrillDownStyleMap.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-
-public class DrillDownStyleMap {
-  private Map<ITableRow, String> m_drillDownStyleMap;
-
-  public DrillDownStyleMap() {
-    m_drillDownStyleMap = new HashMap<ITableRow, String>();
-  }
-
-  public void put(ITableRow tableRow, String drillDownStyle) {
-    m_drillDownStyleMap.put(tableRow, drillDownStyle);
-  }
-
-  public String get(ITableRow tableRow) {
-    return m_drillDownStyleMap.get(tableRow);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTable.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTable.java
deleted file mode 100644
index 90a73f3..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTable.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.columns.IRowSummaryColumn;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.ITableRowFormProvider;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-
-/**
- * @since 3.9.0
- */
-public interface IMobileTable extends ITable {
-
-  String PROP_DRILL_DOWN_STYLE_MAP = "drillDownStyleMap";
-  String PROP_AUTO_CREATE_TABLE_ROW_FORM = "autoCreateTableRowForm";
-  String PROP_DEFAULT_DRILL_DOWN_STYLE = IRowSummaryColumn.PROP_DEFAULT_DRILL_DOWN_STYLE;
-  String PROP_PAGING_ENABLED = "pagingEnabled";
-  String PROP_PAGE_SIZE = "pageSize";
-  String PROP_PAGE_INDEX = "pageIndex";
-  String PROP_TABLE_ROW_FORM_PROVIDER = "tableRowFormProvider";
-
-  String DRILL_DOWN_STYLE_NONE = IRowSummaryColumn.DRILL_DOWN_STYLE_NONE;
-  String DRILL_DOWN_STYLE_ICON = IRowSummaryColumn.DRILL_DOWN_STYLE_ICON;
-  String DRILL_DOWN_STYLE_BUTTON = IRowSummaryColumn.DRILL_DOWN_STYLE_BUTTON;
-
-  String getDefaultDrillDownStyle();
-
-  void setDefaultDrillDownStyle(String defaultDrillDownStyle);
-
-  DrillDownStyleMap getDrillDownStyleMap();
-
-  void setDrillDownStyleMap(DrillDownStyleMap drillDownStyleMap);
-
-  boolean isAutoCreateTableRowForm();
-
-  void setAutoCreateTableRowForm(boolean autoCreateRowForm);
-
-  boolean isPagingEnabled();
-
-  void setPagingEnabled(boolean enabled);
-
-  void setPageSize(int pageSize);
-
-  int getPageSize();
-
-  void setPageIndex(int index);
-
-  int getPageIndex();
-
-  int getPageCount();
-
-  ITableRowFormProvider getTableRowFormProvider();
-
-  void setTableRowFormProvider(ITableRowFormProvider provider);
-
-  @Override
-  IMobileTableUiFacade getUIFacade();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTableUiFacade.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTableUiFacade.java
deleted file mode 100644
index b7b034e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/IMobileTableUiFacade.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableUIFacade;
-
-/**
- * @since 3.9.0
- */
-public interface IMobileTableUiFacade extends ITableUIFacade {
-  void setPageIndexFromUi(int pageIndex);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTable.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTable.java
deleted file mode 100644
index f4aaaa7..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTable.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.columns.AbstractRowSummaryColumn;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.columns.IRowSummaryColumn;
-import org.eclipse.scout.rt.client.ui.MouseButton;
-import org.eclipse.scout.rt.client.ui.basic.table.AbstractTable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableUIFacade;
-import org.eclipse.scout.rt.client.ui.basic.table.TableAdapter;
-import org.eclipse.scout.rt.client.ui.basic.table.TableEvent;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.dnd.TransferObject;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.reflect.ConfigurationUtility;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.platform.util.concurrent.OptimisticLock;
-
-/**
- * A table optimized for mobile devices which wraps another table.
- * <p>
- * It consists of a content column which displays the relevant information of the original table.
- *
- * @since 3.9.0
- */
-public class MobileTable extends AbstractMobileTable implements IMobileTable {
-  private static final int ROW_HEIGHT = 18;
-  private int m_maxCellDetailColumns;
-  private OptimisticLock m_selectionLock;
-  private MobileTablePropertyDelegator m_propertyDelegator;
-  private P_TableEventListener m_tableListener;
-
-  public MobileTable(ITable originalTable) {
-    super(false);
-    Set<String> filter = new HashSet<String>();
-    filter.add(ITable.PROP_AUTO_RESIZE_COLUMNS);
-    filter.add(ITable.PROP_ROW_HEIGHT_HINT);
-    filter.add(ITable.PROP_DEFAULT_ICON);
-    filter.add(ITable.PROP_HEADER_VISIBLE);
-    m_propertyDelegator = new MobileTablePropertyDelegator(originalTable, this, filter);
-    callInitializer();
-
-    try {
-      m_selectionLock = new OptimisticLock();
-      m_tableListener = new P_TableEventListener();
-      m_tableListener.init();
-
-      //Attach as UI listener to make sure every "business logic" listener comes first
-      getOriginalTable().addUITableListener(m_tableListener);
-    }
-    catch (RuntimeException e) {
-      BEANS.get(ExceptionHandler.class).handle(e);
-    }
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-    setAutoDiscardOnDelete(false);
-    setAutoResizeColumns(true);
-    setDefaultIconId(null);
-    setHeaderVisible(false);
-
-    m_maxCellDetailColumns = 2;
-    if (getOriginalTable().getRowHeightHint() == -1) {
-      //+1 stands for the cell header row
-      setRowHeightHint((m_maxCellDetailColumns + 1) * ROW_HEIGHT);
-    }
-
-    getContentColumn().setDefaultDrillDownStyle(getDefaultDrillDownStyle());
-  }
-
-  @Override
-  protected void execDisposeTable() {
-    super.execDisposeTable();
-    if (m_tableListener != null) {
-      getOriginalTable().removeTableListener(m_tableListener);
-      m_tableListener = null;
-    }
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  protected boolean execIsAutoCreateTableRowForm() {
-    if (getOriginalTable().hasProperty(IMobileTable.PROP_AUTO_CREATE_TABLE_ROW_FORM)) {
-      return isAutoCreateRowForm(getOriginalTable());
-    }
-
-    if (getOriginalTable().isCheckable()) {
-      return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  protected String execComputeDefaultDrillDownStyle() {
-    if (getOriginalTable().hasProperty(PROP_DEFAULT_DRILL_DOWN_STYLE)) {
-      return getDefaultDrillDownStyle(getOriginalTable());
-    }
-
-    if (getOriginalTable().isCheckable()) {
-      return IRowSummaryColumn.DRILL_DOWN_STYLE_NONE;
-    }
-
-    //Check if the original table already has a selection or click behavior implemented. If yes, use the drill down button style to not break the original selection or click behavior.
-    if (!(getOriginalTable() instanceof IMobileTable)) {
-      if (ConfigurationUtility.isMethodOverwrite(AbstractTable.class, "execRowsSelected", new Class[]{List.class}, getOriginalTable().getClass()) ||
-          ConfigurationUtility.isMethodOverwrite(AbstractTable.class, "execRowClick", new Class[]{ITableRow.class}, getOriginalTable().getClass())) {
-        return IRowSummaryColumn.DRILL_DOWN_STYLE_BUTTON;
-      }
-    }
-
-    return IRowSummaryColumn.DRILL_DOWN_STYLE_ICON;
-  }
-
-  /**
-   * Makes sure page index is not greater than page count
-   */
-  private void updatePageIndex() {
-    if (getPageIndex() >= getPageCount()) {
-      setPageIndex(getOriginalTable(), getPageCount() - 1);
-    }
-  }
-
-  public ITable getOriginalTable() {
-    return m_propertyDelegator.getSender();
-  }
-
-  @Override
-  public String getDrillDownStyle(ITableRow tableRow) {
-    String drillDownStyle = super.getDrillDownStyle(tableRow);
-    if (drillDownStyle == null) {
-      drillDownStyle = getContentColumn().getDefaultDrillDownStyle();
-    }
-
-    return drillDownStyle;
-  }
-
-  @Override
-  protected void execRowsSelected(List<? extends ITableRow> rows) {
-    try {
-      if (!m_selectionLock.acquire()) {
-        //Prevent loop which could happen because delegation of selection is done from this to original table and vice versa
-        return;
-      }
-
-      //Delegate to original table
-      getOriginalTable().getUIFacade().setSelectedRowsFromUI(getRowMapColumn().getValues(rows));
-
-      ITableRow originalRow = null;
-      if (CollectionUtility.hasElements(rows)) {
-        originalRow = getRowMapColumn().getValue(rows.get(0));
-      }
-      if (originalRow != null) {
-        if (isAutoCreateTableRowForm() && IRowSummaryColumn.DRILL_DOWN_STYLE_ICON.equals(getDrillDownStyle(originalRow))) {
-          startTableRowForm(originalRow);
-        }
-      }
-    }
-    finally {
-      m_selectionLock.release();
-    }
-  }
-
-  @Override
-  protected void execRowClick(ITableRow row, MouseButton mouseButton) {
-    //Delegate to original table
-    ITableRow originalRow = getRowMapColumn().getValue(row);
-    getOriginalTable().getUIFacade().fireRowClickFromUI(originalRow, mouseButton);
-  }
-
-  @Override
-  protected void execAppLinkAction(String ref) {
-    //Delegate to original table
-    getOriginalTable().getUIFacade().fireAppLinkActionFromUI(ref);
-
-    if (AbstractRowSummaryColumn.isDrillDownButtonUrl(ref)) {
-      execDrillDownButtonAction();
-    }
-  }
-
-  protected void execDrillDownButtonAction() {
-    if (isAutoCreateTableRowForm()) {
-      ITableRow originalRow = null;
-      ITableRow selectedRow = getSelectedRow();
-      if (selectedRow != null) {
-        originalRow = getRowMapColumn().getValue(selectedRow);
-      }
-      startTableRowForm(originalRow);
-    }
-  }
-
-  public ContentColumn getContentColumn() {
-    return getColumnSet().getColumnByClass(ContentColumn.class);
-  }
-
-  public RowMapColumn getRowMapColumn() {
-    return getColumnSet().getColumnByClass(RowMapColumn.class);
-  }
-
-  @Order(10)
-  public class RowMapColumn extends AbstractColumn<ITableRow> {
-
-    @Override
-    protected boolean getConfiguredDisplayable() {
-      return false;
-    }
-
-  }
-
-  @Order(20)
-  public class ContentColumn extends AbstractRowSummaryColumn {
-
-  }
-
-  @Override
-  protected ITableUIFacade createUIFacade() {
-    return new P_DispatchingMobileTableUIFacade();
-  }
-
-  private void reset() {
-    discardAllRows();
-  }
-
-  private void handleWrappedTableRowsDeleted(List<? extends ITableRow> rows) {
-    try {
-      setTableChanging(true);
-      for (ITableRow deletedRow : rows) {
-        ITableRow mobileTableRow = getRowMapColumn().findRow(deletedRow);
-        discardRow(mobileTableRow);
-      }
-    }
-    finally {
-      setTableChanging(false);
-    }
-  }
-
-  private void handleWrappedTableRowsSelected(List<? extends ITableRow> rows) {
-    try {
-      setTableChanging(true);
-      selectRows(getRowMapColumn().findRows(rows));
-    }
-    finally {
-      setTableChanging(false);
-    }
-  }
-
-  private void handleWrappedTableRowsInserted(List<? extends ITableRow> rows) {
-    try {
-      setTableChanging(true);
-      insertWrappedTableRows(rows);
-
-      updatePageIndex();
-    }
-    finally {
-      setTableChanging(false);
-    }
-  }
-
-  private void insertWrappedTableRows(List<? extends ITableRow> rows) {
-    if (!getContentColumn().isDecorationConfigurationInitialized()) {
-      getContentColumn().initializeDecorationConfiguration(getOriginalTable(), m_maxCellDetailColumns);
-    }
-
-    for (ITableRow insertedRow : rows) {
-      if (!insertedRow.isFilterAccepted()) {
-        continue;
-      }
-
-      try {
-        ITableRow row = addRowByArray(new Object[]{insertedRow, "", ""});
-        getContentColumn().updateValue(row, insertedRow, getDrillDownStyleMap());
-      }
-      catch (RuntimeException exception) {
-        BEANS.get(ExceptionHandler.class).handle(exception);
-      }
-    }
-  }
-
-  private void handleWrappedTableRowOrderChanged(List<? extends ITableRow> rows) {
-    sort(getRowMapColumn().findRows(rows));
-  }
-
-  private void handleWrappedTableRowsUpdated(List<? extends ITableRow> originalRows) {
-    if (getOriginalTable() == null || getOriginalTable().getRowCount() == 0) {
-      return;
-    }
-
-    try {
-      setTableChanging(true);
-      for (ITableRow originalRow : originalRows) {
-        ITableRow row = getRowMapColumn().findRow(originalRow);
-        if (row != null) {
-          getContentColumn().updateValue(row, originalRow, getDrillDownStyleMap());
-          if (isCheckable()) {
-            checkRow(row, originalRow.isChecked());
-          }
-        }
-      }
-    }
-    catch (RuntimeException exception) {
-      BEANS.get(ExceptionHandler.class).handle(exception);
-    }
-    finally {
-      setTableChanging(false);
-    }
-  }
-
-  private void syncSelectedRows() {
-    if (getOriginalTable().getSelectedRowCount() == 0) {
-      return;
-    }
-
-    selectRows(getRowMapColumn().findRows(getOriginalTable().getSelectedRows()));
-  }
-
-  private void syncCheckedRows() {
-    if (!isCheckable() || getOriginalTable().getCheckedRows().isEmpty()) {
-      return;
-    }
-
-    checkRows(getRowMapColumn().findRows(getOriginalTable().getCheckedRows()), true);
-  }
-
-  private void syncTableRows() {
-    if (getOriginalTable().getRowCount() == 0) {
-      return;
-    }
-
-    insertWrappedTableRows(getOriginalTable().getRows());
-  }
-
-  private class P_TableEventListener extends TableAdapter {
-
-    protected void init() {
-      try {
-        setTableChanging(true);
-
-        syncTableRows();
-        syncSelectedRows();
-        syncCheckedRows();
-      }
-      finally {
-        setTableChanging(false);
-      }
-    }
-
-    @Override
-    public void tableChanged(TableEvent e) {
-      switch (e.getType()) {
-        case TableEvent.TYPE_ROWS_SELECTED: {
-          handleWrappedTableRowsSelected(e.getRows());
-          break;
-        }
-        case TableEvent.TYPE_ALL_ROWS_DELETED: {
-          reset();
-          break;
-        }
-        case TableEvent.TYPE_ROWS_DELETED: {
-          handleWrappedTableRowsDeleted(e.getRows());
-          break;
-        }
-        case TableEvent.TYPE_ROWS_INSERTED: {
-          handleWrappedTableRowsInserted(e.getRows());
-          break;
-        }
-        case TableEvent.TYPE_ROWS_UPDATED: {
-          handleWrappedTableRowsUpdated(e.getRows());
-          break;
-        }
-        case TableEvent.TYPE_ROW_ORDER_CHANGED: {
-          handleWrappedTableRowOrderChanged(e.getRows());
-          break;
-        }
-      }
-    }
-  }
-
-  /**
-   * Used to directly dispatch ui events to the original table or to completely deny certain events
-   */
-  protected class P_DispatchingMobileTableUIFacade extends P_MobileTableUIFacade {
-
-    //------------- pass events only to original table -------------
-
-    @Override
-    public TransferObject fireRowsDragRequestFromUI() {
-      return getOriginalTable().getUIFacade().fireRowsDragRequestFromUI();
-    }
-
-    @Override
-    public void fireRowDropActionFromUI(ITableRow row, TransferObject dropData) {
-      getOriginalTable().getUIFacade().fireRowDropActionFromUI(getRowMapColumn().getValue(row), dropData);
-    }
-
-    @Override
-    public boolean fireKeyTypedFromUI(String keyStrokeText, char keyChar) {
-      return getOriginalTable().getUIFacade().fireKeyTypedFromUI(keyStrokeText, keyChar);
-    }
-
-    @Override
-    public void setPageIndexFromUi(int pageIndex) {
-      getOriginalTable().setProperty(PROP_PAGE_INDEX, pageIndex);
-    }
-
-    //------------- do not process events --------------------------
-    @Override
-    public void fireRowActionFromUI(ITableRow row) {
-      //nop; not allowed
-    }
-
-    @Override
-    public void fireColumnMovedFromUI(IColumn c, int toViewIndex) {
-      //nop; not allowed
-    }
-
-    @Override
-    public void fireVisibleColumnsChangedFromUI(Collection<IColumn<?>> visibleColumns) {
-      super.fireVisibleColumnsChangedFromUI(visibleColumns);
-    }
-
-    @Override
-    public void setColumnWidthFromUI(IColumn c, int newWidth) {
-      //nop; not allowed
-    }
-
-    @Override
-    public IFormField prepareCellEditFromUI(ITableRow row, IColumn col) {
-      //nop; not allowed
-      return null;
-    }
-
-    @Override
-    public void completeCellEditFromUI() {
-      //nop; not allowed
-    }
-
-    @Override
-    public void cancelCellEditFromUI() {
-      //nop; not allowed
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTablePropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTablePropertyDelegator.java
deleted file mode 100644
index b2aa036..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/MobileTablePropertyDelegator.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.ITableRowFormProvider;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-
-/**
- * Delegates the table properties and also the additional properties of the {@link IMobileTable}.
- * <p>
- * The sender does not necessarily need to be of type {@link IMobileTable}, if the properties are set, they will be
- * delegated.
- * 
- * @since 3.9.0
- */
-public class MobileTablePropertyDelegator extends TablePropertyDelegator<ITable, IMobileTable> {
-
-  public MobileTablePropertyDelegator(ITable sender, IMobileTable receiver) {
-    super(sender, receiver);
-  }
-
-  public MobileTablePropertyDelegator(ITable sender, IMobileTable receiver, Set<String> filteredPropertyNames) {
-    super(sender, receiver, filteredPropertyNames);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    if (getSender().hasProperty(IMobileTable.PROP_AUTO_CREATE_TABLE_ROW_FORM)) {
-      getReceiver().setAutoCreateTableRowForm((Boolean) getSender().getProperty(IMobileTable.PROP_AUTO_CREATE_TABLE_ROW_FORM));
-    }
-    if (getSender().hasProperty(IMobileTable.PROP_DRILL_DOWN_STYLE_MAP)) {
-      getReceiver().setDrillDownStyleMap((DrillDownStyleMap) getSender().getProperty(IMobileTable.PROP_DRILL_DOWN_STYLE_MAP));
-    }
-    if (getSender().hasProperty(IMobileTable.PROP_PAGING_ENABLED)) {
-      getReceiver().setPagingEnabled((Boolean) getSender().getProperty(IMobileTable.PROP_PAGING_ENABLED));
-    }
-    if (getSender().hasProperty(IMobileTable.PROP_PAGE_SIZE)) {
-      getReceiver().setPageSize((Integer) getSender().getProperty(IMobileTable.PROP_PAGE_SIZE));
-    }
-    if (getSender().hasProperty(IMobileTable.PROP_PAGE_INDEX)) {
-      getReceiver().setPageIndex((Integer) getSender().getProperty(IMobileTable.PROP_PAGE_INDEX));
-    }
-    if (getSender().hasProperty(IMobileTable.PROP_TABLE_ROW_FORM_PROVIDER)) {
-      getReceiver().setTableRowFormProvider((ITableRowFormProvider) getSender().getProperty(IMobileTable.PROP_TABLE_ROW_FORM_PROVIDER));
-    }
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    super.handlePropertyChange(name, newValue);
-
-    if (name.equals(IMobileTable.PROP_AUTO_CREATE_TABLE_ROW_FORM)) {
-      getReceiver().setAutoCreateTableRowForm((Boolean) newValue);
-    }
-    else if (name.equals(IMobileTable.PROP_DRILL_DOWN_STYLE_MAP)) {
-      getReceiver().setDrillDownStyleMap((DrillDownStyleMap) newValue);
-    }
-    else if (name.equals(IMobileTable.PROP_PAGING_ENABLED)) {
-      getReceiver().setPagingEnabled((Boolean) newValue);
-    }
-    else if (name.equals(IMobileTable.PROP_PAGE_SIZE)) {
-      getReceiver().setPageSize((Integer) newValue);
-    }
-    else if (name.equals(IMobileTable.PROP_PAGE_INDEX)) {
-      getReceiver().setPageIndex((Integer) newValue);
-    }
-    else if (name.equals(IMobileTable.PROP_TABLE_ROW_FORM_PROVIDER)) {
-      getReceiver().setTableRowFormProvider((ITableRowFormProvider) newValue);
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/PagingTableRow.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/PagingTableRow.java
deleted file mode 100644
index 84dc07d..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/PagingTableRow.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ColumnSet;
-import org.eclipse.scout.rt.client.ui.basic.table.TableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.platform.util.IOUtility;
-import org.eclipse.scout.rt.shared.TEXTS;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PagingTableRow extends TableRow {
-  private static final Logger LOG = LoggerFactory.getLogger(PagingTableRow.class);
-  private static String s_htmlCellTemplate;
-
-  static {
-    try {
-      s_htmlCellTemplate = initHtmlCellTemplate();
-    }
-    catch (IOException e) {
-      LOG.error("Couldn't load html template for page change cell.", e);
-    }
-  }
-
-  private Type m_type;
-
-  public PagingTableRow(ColumnSet columnSet, Type type) {
-    super(columnSet);
-    m_type = type;
-    updateContent(columnSet);
-  }
-
-  private void updateContent(ColumnSet columnSet) {
-    IColumn column = CollectionUtility.firstElement(columnSet.getVisibleColumns());
-    if (column != null) {
-      String content;
-      if (Type.back.equals(m_type)) {
-        content = TEXTS.get("MobilePagingShowPrevious");
-      }
-      else {
-        content = TEXTS.get("MobilePagingShowNext");
-      }
-      content = "<b>" + content + "</b>";
-      String output = s_htmlCellTemplate.replace("#CONTENT#", content);
-      getCellForUpdate(column).setText(output);
-    }
-  }
-
-  private static String initHtmlCellTemplate() throws IOException {
-    return new String(IOUtility.getContent(PagingTableRow.class.getResource("/org/eclipse/scout/rt/client/mobile/html/MobileTableCellMoreElements.html").openStream()), StandardCharsets.ISO_8859_1);
-  }
-
-  public enum Type {
-    back,
-    forward
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/TablePropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/TablePropertyDelegator.java
deleted file mode 100644
index f69294c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/TablePropertyDelegator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table;
-
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.PropertyDelegator;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-
-public class TablePropertyDelegator<SENDER extends ITable, RECEIVER extends ITable> extends PropertyDelegator<SENDER, RECEIVER> {
-
-  public TablePropertyDelegator(SENDER sender, RECEIVER receiver) {
-    super(sender, receiver);
-  }
-
-  public TablePropertyDelegator(SENDER sender, RECEIVER receiver, Set<String> filteredPropertyNames) {
-    super(sender, receiver, filteredPropertyNames);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setAutoDiscardOnDelete(getSender().isAutoDiscardOnDelete());
-    getReceiver().setAutoResizeColumns(getSender().isAutoResizeColumns());
-    getReceiver().setCheckable(getSender().isCheckable());
-    getReceiver().setDefaultIconId(getSender().getDefaultIconId());
-    getReceiver().setEnabled(getSender().isEnabled());
-    getReceiver().setHeaderVisible(getSender().isHeaderVisible());
-    getReceiver().setInitialMultilineText(getSender().isInitialMultilineText());
-    getReceiver().setKeyboardNavigation(getSender().hasKeyboardNavigation());
-    getReceiver().setMultiCheck(getSender().isMultiCheck());
-    getReceiver().setMultilineText(getSender().isMultilineText());
-    getReceiver().setMultiSelect(getSender().isMultiSelect());
-    getReceiver().setRowHeightHint(getSender().getRowHeightHint());
-    getReceiver().setScrollToSelection(getSender().isScrollToSelection());
-    getReceiver().setSortEnabled(getSender().isSortEnabled());
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    super.handlePropertyChange(name, newValue);
-
-    if (name.equals(ITable.PROP_AUTO_RESIZE_COLUMNS)) {
-      getReceiver().setAutoResizeColumns(getSender().isAutoResizeColumns());
-    }
-    else if (name.equals(ITable.PROP_CHECKABLE)) {
-      getReceiver().setCheckable(getSender().isCheckable());
-    }
-    else if (name.equals(ITable.PROP_DEFAULT_ICON)) {
-      getReceiver().setDefaultIconId(getSender().getDefaultIconId());
-    }
-    else if (name.equals(ITable.PROP_ENABLED)) {
-      getReceiver().setEnabled(getSender().isEnabled());
-    }
-    else if (name.equals(ITable.PROP_HEADER_VISIBLE)) {
-      getReceiver().setHeaderVisible(getSender().isHeaderVisible());
-    }
-    else if (name.equals(ITable.PROP_KEYBOARD_NAVIGATION)) {
-      getReceiver().setKeyboardNavigation(getSender().hasKeyboardNavigation());
-    }
-    else if (name.equals(ITable.PROP_MULTI_CHECK)) {
-      getReceiver().setMultiCheck(getSender().isMultiCheck());
-    }
-    else if (name.equals(ITable.PROP_MULTILINE_TEXT)) {
-      getReceiver().setMultilineText(getSender().isMultilineText());
-    }
-    else if (name.equals(ITable.PROP_MULTI_SELECT)) {
-      getReceiver().setMultiSelect(getSender().isMultiSelect());
-    }
-    else if (name.equals(ITable.PROP_ROW_HEIGHT_HINT)) {
-      getReceiver().setRowHeightHint(getSender().getRowHeightHint());
-    }
-    else if (name.equals(ITable.PROP_SCROLL_TO_SELECTION)) {
-      getReceiver().setScrollToSelection(getSender().isScrollToSelection());
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/AbstractRowSummaryColumn.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/AbstractRowSummaryColumn.java
deleted file mode 100644
index 9d472ea..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/AbstractRowSummaryColumn.java
+++ /dev/null
@@ -1,527 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.columns;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.eclipse.scout.rt.client.mobile.Icons;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.DrillDownStyleMap;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBooleanColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ISmartColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IStringColumn;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.classid.ClassId;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.exception.ProcessingException;
-import org.eclipse.scout.rt.platform.html.HtmlHelper;
-import org.eclipse.scout.rt.platform.util.BooleanUtility;
-import org.eclipse.scout.rt.platform.util.IOUtility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-
-/**
- * @since 3.9.0
- */
-@ClassId("349c912d-0e60-42a0-bd8d-b4c6c08ec62a")
-public abstract class AbstractRowSummaryColumn extends AbstractStringColumn implements IRowSummaryColumn {
-  private boolean m_decorationConfigurationInitialized;
-
-  private IColumn<?> m_cellHeaderColumn;
-  private List<IColumn<?>> m_cellDetailColumns;
-  private String m_htmlCellTemplate;
-  private String m_htmlDrillDown;
-  private String m_htmlDrillDownButton;
-  private int m_maxCellDetailColumns;
-
-  public AbstractRowSummaryColumn() {
-    try {
-      m_htmlCellTemplate = initHtmlCellTemplate();
-      m_htmlDrillDown = initHtmlDrillDown();
-      m_htmlDrillDownButton = initHtmlDrillDownButton();
-    }
-    catch (RuntimeException e) {
-      BEANS.get(ExceptionHandler.class).handle(e);
-    }
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    setDefaultDrillDownStyle(getConfiguredDefaultDrillDownStyle());
-  }
-
-  protected String initHtmlCellTemplate() {
-    try {
-      return new String(IOUtility.getContent(getClass().getResource("org/eclipse/scout/rt/client/mobile/html/MobileTableCellContent.html").openStream()), "iso-8859-1");
-    }
-    catch (IOException e) {
-      throw new ProcessingException("Exception while loading html cell template for mobile table", e);
-    }
-  }
-
-  protected String initHtmlDrillDown() {
-    try {
-      return new String(IOUtility.getContent(getClass().getResource("org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDown.html").openStream()), "iso-8859-1");
-    }
-    catch (IOException e) {
-      throw new ProcessingException("Exception while loading html cell template for mobile table", e);
-    }
-  }
-
-  protected String initHtmlDrillDownButton() {
-    try {
-      return new String(IOUtility.getContent(getClass().getResource("org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDownButton.html").openStream()), "iso-8859-1");
-    }
-    catch (IOException e) {
-      throw new ProcessingException("Exception while loading html cell template for mobile table", e);
-    }
-  }
-
-  @Override
-  public String getDefaultDrillDownStyle() {
-    return propertySupport.getPropertyString(PROP_DEFAULT_DRILL_DOWN_STYLE);
-  }
-
-  @Override
-  public void setDefaultDrillDownStyle(String drillDownStyle) {
-    propertySupport.setPropertyString(PROP_DEFAULT_DRILL_DOWN_STYLE, drillDownStyle);
-  }
-
-  protected String getConfiguredDefaultDrillDownStyle() {
-    return null;
-  }
-
-  public boolean isDecorationConfigurationInitialized() {
-    return m_decorationConfigurationInitialized;
-  }
-
-  public static boolean isDrillDownButtonUrl(String ref) {
-    String query = ref;
-    if (query == null) {
-      return false;
-    }
-
-    for (String s : query.split("[\\?\\&]")) {
-      Matcher m = Pattern.compile("action=drill_down").matcher(s);
-      if (m.matches()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public void updateValue(ITableRow row, ITableRow modelRow, DrillDownStyleMap drillDownStyle) {
-    setValue(row, computeContentColumnValue(modelRow, drillDownStyle));
-  }
-
-  public void updateValue(ITableRow row, ITableRow modelRow) {
-    updateValue(row, modelRow, null);
-  }
-
-  /**
-   * Analyzes the content of the table to find optimal columns for the displayed texts.
-   */
-  public void initializeDecorationConfiguration(ITable table, int maxCellDetailColumns) {
-    m_cellHeaderColumn = null;
-    m_cellDetailColumns = new ArrayList<IColumn<?>>(maxCellDetailColumns);
-    m_maxCellDetailColumns = maxCellDetailColumns;
-
-    int columnVisibleIndex = 0;
-    for (IColumn<?> column : table.getColumnSet().getVisibleColumns()) {
-      if (m_cellDetailColumns.size() >= maxCellDetailColumns) {
-        break;
-      }
-
-      if (m_cellHeaderColumn == null && useColumnForCellHeader(table, column)) {
-        m_cellHeaderColumn = column;
-      }
-      else if (useColumnForCellDetail(table, column, columnVisibleIndex)) {
-        m_cellDetailColumns.add(column);
-      }
-      columnVisibleIndex++;
-    }
-
-    m_decorationConfigurationInitialized = true;
-  }
-
-  private boolean useColumnForCellHeader(ITable table, IColumn<?> column) {
-    if (isCheckBoxColumn(column)) {
-      return false;
-    }
-    //Only use the given column if there are no summary columns defined
-    if (table.getColumnSet().getSummaryColumns().size() == 0) {
-      return true;
-    }
-
-    return false;
-  }
-
-  private boolean useColumnForCellDetail(ITable table, IColumn<?> column, int columnVisibleIndex) {
-    boolean columnEmpty = true;
-    int maxRowsToConsider = 10;
-
-    if (isCheckBoxColumn(column)) {
-      return false;
-    }
-
-    //Always use column if there is enough space left in m_cellDetailColumns for every remaining column
-    int freeSlots = m_maxCellDetailColumns - m_cellDetailColumns.size();
-    int remainingColumns = table.getColumnSet().getVisibleColumns().size() - (columnVisibleIndex + 1);
-    if (remainingColumns < freeSlots) {
-      return true;
-    }
-
-    for (int row = 0; row < Math.min(maxRowsToConsider, table.getRowCount()); row++) {
-      ITableRow tableRow = table.getRow(row);
-      final String columnDisplayText = column.getDisplayText(tableRow);
-      if (StringUtility.hasText(columnDisplayText)) {
-        columnEmpty = false;
-
-        //If column contains similar data to the header column, don't use it
-        String cellHeaderText = getCellHeaderText(tableRow);
-        if (cellHeaderText != null && cellHeaderText.contains(columnDisplayText)) {
-          return false;
-        }
-
-      }
-
-    }
-
-    if (columnEmpty) {
-      return false;
-    }
-
-    return true;
-  }
-
-  private String getCellHeaderText(ITableRow row) {
-    if (m_cellHeaderColumn != null) {
-      return m_cellHeaderColumn.getDisplayText(row);
-    }
-    else {
-      return row.getTable().getSummaryCell(row).getText();
-    }
-  }
-
-  private static final Pattern bodyPartPattern = Pattern.compile("(.*<body[^>]*>)(.*)(</body>.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
-  private static final Pattern htmlPartPattern = Pattern.compile("(.*<html[^>]*>)(.*)(</html>.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
-
-  /**
-   * Wraps the existing html with a div having a border on the bottom to visually separate the rows. This would actually
-   * be the job of the GUI, but it seems not to be possible with the list widget of rap.
-   */
-  private String addGridLine(String existingHtml) {
-    String borderDivStart = "<div style=\"width: 100%; height: 100%; border-bottom:1px solid #e1efec\">";
-    String borderDivEnd = "</div>";
-    String prePart = "";
-    String mainPart = "";
-    String postPart = "";
-
-    Matcher m = bodyPartPattern.matcher(existingHtml);
-    boolean found = m.find();
-    if (!found) {
-      m = htmlPartPattern.matcher(existingHtml);
-      found = m.find();
-    }
-    if (found) {
-      prePart = m.group(1);
-      mainPart = m.group(2);
-      postPart = m.group(3);
-    }
-    else {
-      mainPart = existingHtml;
-    }
-
-    return prePart + borderDivStart + mainPart + borderDivEnd + postPart;
-  }
-
-  protected String adaptExistingHtmlInCellHeader(String cellHeaderHtml) {
-    cellHeaderHtml = addGridLine(cellHeaderHtml);
-
-    return cellHeaderHtml;
-  }
-
-  /**
-   * @return true if the text starts with {@code <html>}, false if not. The check is case insensitive.
-   */
-  private boolean containsHtml(String text) {
-    if (text == null || text.length() < 6) {
-      return false;
-    }
-    if (text.charAt(0) == '<' && text.charAt(5) == '>') {
-      String tag = text.substring(1, 5);
-      return tag.equalsIgnoreCase("html");
-    }
-
-    return false;
-  }
-
-  private String computeContentColumnValue(ITableRow row, DrillDownStyleMap drillDownStyles) {
-    if (row == null) {
-      return null;
-    }
-
-    String cellHeaderText = getCellHeaderText(row);
-    if (cellHeaderText == null) {
-      cellHeaderText = "";
-    }
-    //Don't generate cell content if the only column contains html.
-    //It is assumed that such a column is already optimized for mobile devices.
-    if (m_cellDetailColumns.size() == 0 && containsHtml(cellHeaderText)) {
-      cellHeaderText = adaptExistingHtmlInCellHeader(cellHeaderText);
-
-      //Make sure drill down style is set to none
-      if (drillDownStyles != null) {
-        drillDownStyles.put(row, IRowSummaryColumn.DRILL_DOWN_STYLE_NONE);
-      }
-      return cellHeaderText;
-    }
-
-    String content = "";
-    boolean cellHasHeader = false;
-    if (StringUtility.hasText(cellHeaderText)) {
-      content = createCellHeader(cellHeaderText);
-      content += "<br/>";
-      cellHasHeader = true;
-    }
-
-    content += createCellDetail(row, cellHasHeader);
-
-    String drillDownStyle = null;
-    if (drillDownStyles != null) {
-      drillDownStyle = drillDownStyles.get(row);
-    }
-    String icon = createCellIcon(row);
-    String output = m_htmlCellTemplate.replace("#ICON#", icon);
-    output = output.replace("#ICON_COL_WIDTH#", createCellIconColWidth(row, icon));
-    output = output.replace("#CONTENT#", content);
-    output = output.replace("#DRILL_DOWN#", createCellDrillDown(row, drillDownStyle));
-    output = output.replace("#DRILL_DOWN_COL_WIDTH#", createCellDrillDownColWidth(row, drillDownStyle));
-
-    return output;
-  }
-
-  private String createCellIcon(ITableRow row) {
-    if (row == null) {
-      return "";
-    }
-
-    String iconId = null;
-    if (row.getTable().isCheckable()) {
-      iconId = computeCheckboxIconId(row.isChecked());
-    }
-    else {
-      iconId = row.getIconId();
-      IColumn<?> firstVisibleColumn = row.getTable().getColumnSet().getFirstVisibleColumn();
-      if (iconId == null) {
-        iconId = row.getCell(firstVisibleColumn).getIconId();
-      }
-      if (iconId == null) {
-        if (isCheckBoxColumn(firstVisibleColumn)) {
-          IBooleanColumn booleanColumn = (IBooleanColumn) firstVisibleColumn;
-          iconId = computeCheckboxIconId(BooleanUtility.nvl(booleanColumn.getValue(row)));
-        }
-      }
-    }
-
-    if (iconId == null) {
-      return "";
-    }
-    else {
-      return "<img width=\"16\" height=\"16\" src=\"cid:" + iconId + "\"/>";
-    }
-  }
-
-  /**
-   * @return true if the column should display a checkbox icon rather than a text
-   */
-  private boolean isCheckBoxColumn(IColumn<?> column) {
-    return column.getDataType() == Boolean.class && (!(column instanceof ISmartColumn) || ((ISmartColumn) column).getLookupCall() == null);
-  }
-
-  private String computeCheckboxIconId(boolean checked) {
-    if (checked) {
-      return Icons.CheckboxYes;
-    }
-    else {
-      return Icons.CheckboxNo;
-    }
-  }
-
-  private String createCellIconColWidth(ITableRow row, String icon) {
-    if (StringUtility.hasText(icon)) {
-      return "32";
-    }
-    else {
-      //If there is no icon set a small width as left padding for the text.
-      return "6";
-    }
-  }
-
-  private String createCellDrillDown(ITableRow row, String drillDownStyle) {
-    if (drillDownStyle == null) {
-      drillDownStyle = getDefaultDrillDownStyle();
-    }
-
-    if (DRILL_DOWN_STYLE_ICON.equals(drillDownStyle)) {
-      return m_htmlDrillDown;
-    }
-    else if (DRILL_DOWN_STYLE_BUTTON.equals(drillDownStyle)) {
-      return m_htmlDrillDownButton;
-    }
-    else {
-      return "";
-    }
-  }
-
-  private String createCellDrillDownColWidth(ITableRow row, String drillDownStyle) {
-    if (drillDownStyle == null) {
-      drillDownStyle = getDefaultDrillDownStyle();
-    }
-
-    if (DRILL_DOWN_STYLE_ICON.equals(drillDownStyle)) {
-      return "32";
-    }
-    else if (DRILL_DOWN_STYLE_BUTTON.equals(drillDownStyle)) {
-      return "60";
-    }
-    else {
-      return "0";
-    }
-  }
-
-  private String createCellHeader(String cellHeaderText) {
-    String content = "";
-
-    content = cleanupText(cellHeaderText);
-    content = "<b>" + content + "</b>";
-
-    return content;
-  }
-
-  private String createCellDetail(ITableRow row, boolean cellHasHeader) {
-    if (row == null) {
-      return "";
-    }
-
-    String content = "";
-    int col = 0;
-    for (IColumn<?> column : m_cellDetailColumns) {
-      String displayText = extractCellDisplayText(column, row);
-
-      if (StringUtility.hasText(displayText)) {
-        if (isHeaderDescriptionNeeded(row, column)) {
-          content += extractColumnHeader(column);
-          content += ": ";
-        }
-        content += displayText;
-      }
-
-      if (col < m_cellDetailColumns.size() - 1) {
-        content += "<br/>";
-      }
-
-      col++;
-    }
-
-    if (cellHasHeader) {
-      //Make the font a little smaller if there is a cell header
-      content = "<span style=\"font-size:12px\">" + content + "</span>";
-    }
-
-    return content;
-  }
-
-  private String cleanupText(String text) {
-    if (text == null) {
-      return null;
-    }
-
-    boolean containsHtml = text.contains("<html>");
-    if (containsHtml) {
-      //Ignore every html code by removing all the tags to make sure it does not destroy the layout
-      String textWithoutHtml = BEANS.get(HtmlHelper.class).toPlainText(text);
-      if (textWithoutHtml != null) {
-        text = textWithoutHtml;
-      }
-    }
-    text = StringUtility.removeNewLines(text);
-    text = StringUtility.trim(text);
-    if (!containsHtml) {
-      //If the text is not surrounded by <html> the html must not be interpreted but displayed as it is including all the html tags.
-      text = StringUtility.htmlEncode(text);
-    }
-    text = replaceSpaces(text);
-
-    return text;
-  }
-
-  /**
-   * Replace spaces with non breaking spaces. Can't use &nbsp; because of
-   * https://bugs.eclipse.org/bugs/show_bug.cgi?id=379088
-   */
-  private String replaceSpaces(String text) {
-    return text.replaceAll("\\s", "&#160;");
-  }
-
-  private String extractCellDisplayText(IColumn<?> column, ITableRow row) {
-    String displayText = column.getDisplayText(row);
-
-    displayText = cleanupText(displayText);
-
-    return displayText;
-  }
-
-  private String extractColumnHeader(IColumn<?> column) {
-    String header = column.getHeaderCell().getText();
-
-    header = cleanupText(header);
-
-    return header;
-  }
-
-  /**
-   * Columns with a reasonable text don't need the header description.
-   */
-  private boolean isHeaderDescriptionNeeded(ITableRow row, IColumn<?> column) {
-    if (column instanceof ISmartColumn<?>) {
-      return column.getValue(row) instanceof Boolean;
-    }
-
-    if (column instanceof IStringColumn) {
-      return isNumber(((IStringColumn) column).getValue(row));
-    }
-
-    return true;
-  }
-
-  private boolean isNumber(String value) {
-    if (value == null) {
-      return false;
-    }
-
-    try {
-      Double.parseDouble(value);
-    }
-    catch (NumberFormatException e) {
-      return false;
-    }
-    return true;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/IRowSummaryColumn.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/IRowSummaryColumn.java
deleted file mode 100644
index 6fab543..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/columns/IRowSummaryColumn.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.columns;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-
-/**
- * @since 3..9.0
- */
-public interface IRowSummaryColumn extends IColumn<String> {
-
-  String PROP_DEFAULT_DRILL_DOWN_STYLE = "defaultDrillDownStyle";
-
-  String DRILL_DOWN_STYLE_NONE = "none";
-  String DRILL_DOWN_STYLE_ICON = "icon";
-  String DRILL_DOWN_STYLE_BUTTON = "button";
-
-  String getDefaultDrillDownStyle();
-
-  void setDefaultDrillDownStyle(String drillDownStyle);
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/DefaultTableRowFormProvider.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/DefaultTableRowFormProvider.java
deleted file mode 100644
index eb73f08..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/DefaultTableRowFormProvider.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-
-/**
- * @since 3.10.0 M3
- */
-public class DefaultTableRowFormProvider implements ITableRowFormProvider {
-
-  @Override
-  public ITableRowForm createTableRowForm(ITableRow row) {
-    return new TableRowForm(row);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowForm.java
deleted file mode 100644
index f65cd0e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowForm.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.IMobileForm;
-
-/**
- * @since 3.10.0 M3
- */
-public interface ITableRowForm extends IMobileForm {
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowFormProvider.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowFormProvider.java
deleted file mode 100644
index f05dc34..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/ITableRowFormProvider.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-
-/**
- * @since 3.10.0 M3
- */
-public interface ITableRowFormProvider {
-
-  ITableRowForm createTableRowForm(ITableRow row);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowForm.java
deleted file mode 100644
index 58360b7..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowForm.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields.ColumnFieldBuilder;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.IActionFetcher;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.button.AbstractBackButton;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.TableAdapter;
-import org.eclipse.scout.rt.client.ui.basic.table.TableEvent;
-import org.eclipse.scout.rt.client.ui.basic.table.TableRowMapper;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.IValueField;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-
-/**
- * Form which displays a {@link ITableRow} as fields. Only the fields belonging to editable columns are enabled.
- *
- * @since 3.9.0
- */
-public class TableRowForm extends AbstractMobileForm implements ITableRowForm {
-  private ITable m_table;
-  private ITableRow m_row;
-  private IFormField m_rowField;
-  private ColumnFieldBuilder m_columnFieldBuilder;
-  private Map<IColumn<?>, IFormField> m_columnFields;
-  private P_TableListener m_tableListener;
-  private TableRowMapper m_rowMapper;
-
-  public TableRowForm(ITableRow row) {
-    this(row, null);
-  }
-
-  /**
-   * @param rowField
-   *          if set this field will be displayed instead of the auto generated column fields.
-   */
-  public TableRowForm(ITableRow row, IFormField rowField) {
-    super(false);
-    m_row = row;
-    m_rowField = rowField;
-    m_table = row.getTable();
-    m_columnFields = new HashMap<IColumn<?>, IFormField>();
-    if (m_rowField == null) {
-      m_columnFieldBuilder = createColumnFieldBuilder();
-      m_columnFields = m_columnFieldBuilder.build(getTable().getColumns(), row);
-    }
-    callInitializer();
-
-    m_tableListener = new P_TableListener();
-    getTable().addTableListener(m_tableListener);
-  }
-
-  @Override
-  protected void execDisposeForm() {
-    getTable().removeTableListener(m_tableListener);
-    if (m_columnFields != null) {
-      for (IFormField formField : m_columnFields.values()) {
-        m_columnFieldBuilder.fieldDisposed(formField);
-      }
-    }
-  }
-
-  protected ColumnFieldBuilder createColumnFieldBuilder() {
-    return new ColumnFieldBuilder();
-  }
-
-  public ITable getTable() {
-    return m_table;
-  }
-
-  public ITableRow getRow() {
-    return m_row;
-  }
-
-  @Override
-  protected int getConfiguredDisplayHint() {
-    return DISPLAY_HINT_VIEW;
-  }
-
-  @Override
-  protected String getConfiguredDisplayViewId() {
-    return VIEW_ID_PAGE_DETAIL;
-  }
-
-  @Override
-  protected IActionFetcher createHeaderActionFetcher() {
-    return new TableRowFormHeaderActionFetcher(this, getTable());
-  }
-
-  @Order(10)
-  public class MainBox extends AbstractGroupBox {
-
-    @Override
-    protected void injectFieldsInternal(OrderedCollection<IFormField> fields) {
-      if (m_rowField != null) {
-        fields.addOrdered(m_rowField);
-      }
-      else {
-        fields.addLast(new P_ColumnFieldsGroupBox());
-      }
-      super.injectFieldsInternal(fields);
-    }
-
-    @Order(5)
-    public class BackButton extends AbstractBackButton {
-
-    }
-
-  }
-
-  @Override
-  public void start() {
-    startInternal(new FormHandler());
-  }
-
-  public class FormHandler extends AbstractFormHandler {
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected void execLoad() {
-      m_rowMapper = new TableRowMapper(getRow());
-      for (IColumn column : m_columnFields.keySet()) {
-        IFormField field = m_columnFields.get(column);
-        if (field instanceof IValueField) {
-          IValueField<?> valueField = (IValueField<?>) field;
-          m_rowMapper.addMapping(column, valueField);
-          valueField.addPropertyChangeListener(new P_ValueFieldListener(column));
-        }
-      }
-      m_rowMapper.exportRowData();
-    }
-
-  }
-
-  private void handleRowDeleted() {
-    try {
-      doClose();
-    }
-    catch (RuntimeException e) {
-      BEANS.get(ExceptionHandler.class).handle(e);
-    }
-  }
-
-  private void handleRowUpdated() {
-    m_rowMapper.exportRowData();
-  }
-
-  /**
-   * Listener to inform the column about the completion of an edit.
-   */
-  private class P_ValueFieldListener implements PropertyChangeListener {
-    private IColumn<?> m_column;
-
-    public P_ValueFieldListener(IColumn<?> column) {
-      m_column = column;
-    }
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-      try {
-        if (!m_column.isEditable()) {
-          return;
-        }
-
-        IValueField<?> field = (IValueField) evt.getSource();
-        if (IValueField.PROP_VALUE.equals(evt.getPropertyName())) {
-          m_column.completeEdit(getRow(), field);
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-    }
-
-  }
-
-  private class P_TableListener extends TableAdapter {
-
-    @Override
-    public void tableChanged(TableEvent e) {
-      List<ITableRow> rows = e.getRows();
-      if (rows == null) {
-        return;
-      }
-
-      for (ITableRow row : rows) {
-        if (!getRow().equals(row)) {
-          continue;
-        }
-
-        switch (e.getType()) {
-          case TableEvent.TYPE_ALL_ROWS_DELETED:
-          case TableEvent.TYPE_ROWS_DELETED:
-            handleRowDeleted();
-            break;
-          case TableEvent.TYPE_ROWS_UPDATED:
-            handleRowUpdated();
-            break;
-        }
-      }
-    }
-
-  }
-
-  private class P_ColumnFieldsGroupBox extends AbstractGroupBox {
-
-    @Override
-    protected void injectFieldsInternal(OrderedCollection<IFormField> fields) {
-      for (IColumn column : getTable().getColumns()) {
-        IFormField field = m_columnFields.get(column);
-        if (field != null) {
-          fields.addLast(field);
-        }
-      }
-
-      super.injectFieldsInternal(fields);
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormHeaderActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormHeaderActionFetcher.java
deleted file mode 100644
index 8bd96af..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/TableRowFormHeaderActionFetcher.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form;
-
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileAction;
-import org.eclipse.scout.rt.client.mobile.ui.form.FormHeaderActionFetcher;
-import org.eclipse.scout.rt.client.mobile.ui.form.IMobileAction;
-import org.eclipse.scout.rt.client.ui.action.ActionUtility;
-import org.eclipse.scout.rt.client.ui.action.IActionFilter;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenuType;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * Additionally fetches the actions of the table row and places them on the right side.
- */
-public class TableRowFormHeaderActionFetcher extends FormHeaderActionFetcher {
-
-  private ITable m_table;
-
-  public TableRowFormHeaderActionFetcher(IForm form, ITable table) {
-    super(form);
-
-    m_table = table;
-  }
-
-  public ITable getTable() {
-    return m_table;
-  }
-
-  @Override
-  public List<IMenu> fetch() {
-    List<IMenu> headerActions = super.fetch();
-    Set<? extends IMenuType> currentMenuTypes = getTable().getContextMenu().getCurrentMenuTypes();
-    IActionFilter actionFilter = ActionUtility.createMenuFilterMenuTypes(currentMenuTypes, true);
-    List<IMenu> tableRowActions = ActionUtility.getActions(getTable().getMenus(), actionFilter);
-    for (IMenu action : tableRowActions) {
-      AbstractMobileAction.setHorizontalAlignment(action, IMobileAction.HORIZONTAL_ALIGNMENT_RIGHT);
-    }
-    headerActions.addAll(0, tableRowActions);
-
-    return headerActions;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnField.java
deleted file mode 100644
index 20d224f..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigDecimalColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.bigdecimalfield.AbstractBigDecimalField;
-
-/**
- * @since 3.9.0
- */
-public class BigDecimalColumnField extends AbstractBigDecimalField implements IColumnWrapper<IBigDecimalColumn> {
-  private BigDecimalColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public BigDecimalColumnField(IBigDecimalColumn column) {
-    super(false);
-    m_propertyDelegator = new BigDecimalColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IBigDecimalColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnFieldPropertyDelegator.java
deleted file mode 100644
index 45a23fc..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigDecimalColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigDecimalColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.bigdecimalfield.IBigDecimalField;
-
-/**
- * @since 3.9.0
- */
-public class BigDecimalColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<IBigDecimalColumn, IBigDecimalField> {
-
-  public BigDecimalColumnFieldPropertyDelegator(IBigDecimalColumn sender, IBigDecimalField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-    getReceiver().setFormat(getSender().getFormat());
-    getReceiver().setMinFractionDigits(getSender().getMinFractionDigits());
-    getReceiver().setMaxFractionDigits(getSender().getMaxFractionDigits());
-    getReceiver().setGroupingUsed(getSender().isGroupingUsed());
-    getReceiver().setPercent(getSender().isPercent());
-    getReceiver().setMultiplier(getSender().getMultiplier());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnField.java
deleted file mode 100644
index 6d29add..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigIntegerColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.bigintegerfield.AbstractBigIntegerField;
-
-/**
- * @since 3.9.0
- */
-public class BigIntegerColumnField extends AbstractBigIntegerField implements IColumnWrapper<IBigIntegerColumn> {
-  private BigIntegerColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public BigIntegerColumnField(IBigIntegerColumn column) {
-    super(false);
-    m_propertyDelegator = new BigIntegerColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IBigIntegerColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnFieldPropertyDelegator.java
deleted file mode 100644
index 507f29a..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BigIntegerColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigIntegerColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.bigintegerfield.IBigIntegerField;
-
-/**
- * @since 3.9.0
- */
-public class BigIntegerColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<IBigIntegerColumn, IBigIntegerField> {
-
-  public BigIntegerColumnFieldPropertyDelegator(IBigIntegerColumn sender, IBigIntegerField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-    getReceiver().setFormat(getSender().getFormat());
-    getReceiver().setGroupingUsed(getSender().isGroupingUsed());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BooleanColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BooleanColumnField.java
deleted file mode 100644
index c102487..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/BooleanColumnField.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBooleanColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.AbstractBooleanField;
-import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.IBooleanField;
-
-/**
- * @since 3.9.0
- */
-public class BooleanColumnField extends AbstractBooleanField implements IColumnWrapper<IBooleanColumn> {
-  private ColumnFieldPropertyDelegator<IBooleanColumn, IBooleanField> m_propertyDelegator;
-
-  public BooleanColumnField(IBooleanColumn column) {
-    super(false);
-    m_propertyDelegator = new ColumnFieldPropertyDelegator<IBooleanColumn, IBooleanField>(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IBooleanColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldBuilder.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldBuilder.java
deleted file mode 100644
index 19453d1..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldBuilder.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigDecimalColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBigIntegerColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IBooleanColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IDateColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IIntegerColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ILongColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IProposalColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ISmartColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IStringColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.GridData;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.IValueField;
-import org.eclipse.scout.rt.client.ui.form.fields.bigdecimalfield.IBigDecimalField;
-import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.IBooleanField;
-import org.eclipse.scout.rt.client.ui.form.fields.datefield.IDateField;
-import org.eclipse.scout.rt.client.ui.form.fields.integerfield.IIntegerField;
-import org.eclipse.scout.rt.client.ui.form.fields.longfield.ILongField;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.IProposalField;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.ISmartField;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.IStringField;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @since 3.9.0
- */
-public class ColumnFieldBuilder {
-
-  private static final String PROP_PROPERTY_DELEGATOR = "propertyDelegator";
-  private static final Logger LOG = LoggerFactory.getLogger(ColumnFieldBuilder.class);
-
-  public Map<IColumn<?>, IFormField> build(List<IColumn<?>> columns, ITableRow row) {
-    Map<IColumn<?>, IFormField> fields = new HashMap<IColumn<?>, IFormField>();
-    if (columns == null) {
-      return fields;
-    }
-
-    for (IColumn<?> column : columns) {
-      IFormField field = createValueField(column, row);
-      if (field != null) {
-        fields.put(column, field);
-      }
-      else {
-        LOG.warn("No field mapping found for column [{}]", column.getClass().getName());
-      }
-    }
-
-    return fields;
-  }
-
-  @SuppressWarnings("unchecked")
-  protected IFormField createValueField(IColumn<?> column, ITableRow row) {
-    if (column.isEditable()) {
-      IFormField field = createEditableField(column, row);
-      if (field != null) {
-        return field;
-      }
-    }
-
-    if (column instanceof IStringColumn) {
-      return new StringColumnField((IStringColumn) column);
-    }
-    if (column instanceof ISmartColumn) {
-      return new SmartColumnField((ISmartColumn<?>) column);
-    }
-    if (column instanceof IDateColumn) {
-      return new DateColumnField((IDateColumn) column);
-    }
-    if (column instanceof IBooleanColumn) {
-      return new BooleanColumnField((IBooleanColumn) column);
-    }
-    if (column instanceof ILongColumn) {
-      return new LongColumnField((ILongColumn) column);
-    }
-    if (column instanceof IIntegerColumn) {
-      return new IntegerColumnField((IIntegerColumn) column);
-    }
-    if (column instanceof IBigDecimalColumn) {
-      return new BigDecimalColumnField((IBigDecimalColumn) column);
-    }
-    if (column instanceof IBigIntegerColumn) {
-      return new BigIntegerColumnField((IBigIntegerColumn) column);
-    }
-
-    return null;
-  }
-
-  @SuppressWarnings("unchecked")
-  protected ColumnFieldPropertyDelegator<? extends IColumn<?>, ? extends IFormField> createColumnFieldPropertyDelegator(IColumn<?> column, IFormField formField) {
-    if (column instanceof IStringColumn && formField instanceof IStringField) {
-      return new StringColumnFieldPropertyDelegator((IStringColumn) column, (IStringField) formField);
-    }
-    else if (column instanceof ISmartColumn && formField instanceof ISmartField) {
-      return new SmartColumnFieldPropertyDelegator((ISmartColumn) column, (ISmartField) formField);
-    }
-    else if (column instanceof IProposalColumn && formField instanceof IProposalField) {
-      return new ProposalColumnFieldPropertyDelegator((IProposalColumn) column, (IProposalField) formField);
-    }
-    else if (column instanceof IDateColumn && formField instanceof IDateField) {
-      return new DateColumnFieldPropertyDelegator((IDateColumn) column, (IDateField) formField);
-    }
-    else if (column instanceof IBooleanColumn && formField instanceof IBooleanField) {
-      return new ColumnFieldPropertyDelegator(column, formField);
-    }
-    else if (column instanceof ILongColumn && formField instanceof ILongField) {
-      return new LongColumnFieldPropertyDelegator((ILongColumn) column, (ILongField) formField);
-    }
-    else if (column instanceof IIntegerColumn && formField instanceof IIntegerField) {
-      return new IntegerColumnFieldPropertyDelegator((IIntegerColumn) column, (IIntegerField) formField);
-    }
-    else if (column instanceof IBigDecimalColumn && formField instanceof IBigDecimalField) {
-      return new BigDecimalColumnFieldPropertyDelegator((IBigDecimalColumn) column, (IBigDecimalField) formField);
-    }
-
-    return new ColumnFieldPropertyDelegator(column, formField);
-  }
-
-  protected IFormField createEditableField(IColumn<?> column, ITableRow row) {
-    IFormField field = column.prepareEdit(row);
-    if (field != null) {
-      //Revert changes which are done in AbstractColumn#prepareEdit
-      field.setLabelVisible(true);
-      GridData gd = field.getGridDataHints();
-      gd.weightY = 0;
-      field.setGridDataHints(gd);
-
-      //Set missing properties
-      ColumnFieldPropertyDelegator<? extends IColumn<?>, ? extends IFormField> propertyDelegator = createColumnFieldPropertyDelegator(column, field);
-      if (propertyDelegator != null) {
-        propertyDelegator.init();
-        field.setProperty(PROP_PROPERTY_DELEGATOR, propertyDelegator);
-      }
-
-      field.addPropertyChangeListener(new PropertyChangeListener() {
-
-        @Override
-        public void propertyChange(PropertyChangeEvent evt) {
-          if (IValueField.PROP_VALUE.equals(evt.getPropertyName())) {
-            //Enforce setting cell value even if the value has been changed back to initial value (see AbstractColumn#execCompleteEdit
-            ((IValueField<?>) evt.getSource()).touch();
-          }
-        }
-      });
-    }
-
-    return field;
-  }
-
-  public void fieldDisposed(IFormField field) {
-    Object value = field.getProperty(PROP_PROPERTY_DELEGATOR);
-    if (value instanceof ColumnFieldPropertyDelegator) {
-      ((ColumnFieldPropertyDelegator) value).dispose();
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldPropertyDelegator.java
deleted file mode 100644
index a9457eb..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.PropertyDelegator;
-import org.eclipse.scout.rt.client.ui.basic.table.TableAdapter;
-import org.eclipse.scout.rt.client.ui.basic.table.TableEvent;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-
-/**
- * @since 3.9.0
- */
-public class ColumnFieldPropertyDelegator<SENDER extends IColumn<?>, RECEIVER extends IFormField> extends PropertyDelegator<SENDER, RECEIVER> {
-  private P_TableListener m_tableListener;
-
-  public ColumnFieldPropertyDelegator(SENDER sender, RECEIVER receiver) {
-    super(sender, receiver);
-
-    m_tableListener = new P_TableListener();
-    getSender().getTable().addTableListener(m_tableListener);
-  }
-
-  @Override
-  public void dispose() {
-    super.dispose();
-    getSender().getTable().removeTableListener(m_tableListener);
-    m_tableListener = null;
-  }
-
-  @Override
-  public void init() {
-    getReceiver().setVisible(getSender().isVisible());
-    if (!getSender().isVisible()) {
-      getReceiver().setVisibleGranted(getSender().isVisibleGranted());
-    }
-
-    String label = getSender().getHeaderCell().getText();
-    if (isRemoveLabelLineBreaksEnabled()) {
-      label = StringUtility.removeNewLines(label);
-    }
-    getReceiver().setLabel(label);
-    getReceiver().setTooltipText(getSender().getHeaderCell().getTooltipText());
-    getReceiver().setEnabled(getSender().isCellEditable(getSender().getTable().getSelectedRow()));
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    if (name.equals(IColumn.PROP_VISIBLE)) {
-      getReceiver().setVisible(((Boolean) newValue).booleanValue());
-    }
-    if (name.equals(IColumn.PROP_EDITABLE)) {
-      getReceiver().setEnabled(((Boolean) newValue).booleanValue());
-    }
-  }
-
-  protected boolean isRemoveLabelLineBreaksEnabled() {
-    return true;
-  }
-
-  protected void handleColumnHeaderChanged(IColumn<?> column) {
-    String label = getSender().getHeaderCell().getText();
-    if (isRemoveLabelLineBreaksEnabled()) {
-      label = StringUtility.removeNewLines(label);
-    }
-    getReceiver().setLabel(label);
-    getReceiver().setTooltipText(column.getHeaderCell().getTooltipText());
-  }
-
-  protected void handleTableEvent(TableEvent event) {
-    if (TableEvent.TYPE_COLUMN_HEADERS_UPDATED == event.getType()) {
-      for (IColumn column : event.getColumns()) {
-        if (column.equals(getSender())) {
-          handleColumnHeaderChanged(column);
-        }
-      }
-    }
-  }
-
-  private class P_TableListener extends TableAdapter {
-
-    @Override
-    public void tableChanged(TableEvent e) {
-      handleTableEvent(e);
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnField.java
deleted file mode 100644
index 67d7f70..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IDateColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.datefield.AbstractDateField;
-
-/**
- * @since 3.9.0
- */
-public class DateColumnField extends AbstractDateField implements IColumnWrapper<IDateColumn> {
-  private DateColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public DateColumnField(IDateColumn column) {
-    super(false);
-    m_propertyDelegator = new DateColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IDateColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnFieldPropertyDelegator.java
deleted file mode 100644
index d0a7ab1..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/DateColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IDateColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.datefield.IDateField;
-
-/**
- * @since 3.9.0
- */
-public class DateColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<IDateColumn, IDateField> {
-
-  public DateColumnFieldPropertyDelegator(IDateColumn sender, IDateField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setFormat(getSender().getFormat());
-    getReceiver().setHasDate(getSender().isHasDate());
-    getReceiver().setHasTime(getSender().isHasTime());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IColumnWrapper.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IColumnWrapper.java
deleted file mode 100644
index fe1bab1..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IColumnWrapper.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.IWrapper;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-
-/**
- * @since 3.9.0
- */
-public interface IColumnWrapper<WRAPPABLE extends IColumn<?>> extends IWrapper<WRAPPABLE> {
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnField.java
deleted file mode 100644
index d1fc38a..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IIntegerColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.integerfield.AbstractIntegerField;
-
-/**
- * @since 3.9.0
- */
-public class IntegerColumnField extends AbstractIntegerField implements IColumnWrapper<IIntegerColumn> {
-  private IntegerColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public IntegerColumnField(IIntegerColumn column) {
-    super(false);
-    m_propertyDelegator = new IntegerColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IIntegerColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnFieldPropertyDelegator.java
deleted file mode 100644
index cf0fc9e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/IntegerColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IIntegerColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.integerfield.IIntegerField;
-
-/**
- * @since 3.9.0
- */
-public class IntegerColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<IIntegerColumn, IIntegerField> {
-
-  public IntegerColumnFieldPropertyDelegator(IIntegerColumn sender, IIntegerField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setFormat(getSender().getFormat());
-    getReceiver().setGroupingUsed(getSender().isGroupingUsed());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnField.java
deleted file mode 100644
index fb5b825..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ILongColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.longfield.AbstractLongField;
-
-/**
- * @since 3.9.0
- */
-public class LongColumnField extends AbstractLongField implements IColumnWrapper<ILongColumn> {
-  private LongColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public LongColumnField(ILongColumn column) {
-    super(false);
-    m_propertyDelegator = new LongColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public ILongColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnFieldPropertyDelegator.java
deleted file mode 100644
index 51c098c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/LongColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ILongColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.longfield.ILongField;
-
-/**
- * @since 3.9.0
- */
-public class LongColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<ILongColumn, ILongField> {
-
-  public LongColumnFieldPropertyDelegator(ILongColumn sender, ILongField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setFormat(getSender().getFormat());
-    getReceiver().setGroupingUsed(getSender().isGroupingUsed());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnField.java
deleted file mode 100644
index a72d693..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnField.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IProposalColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.AbstractProposalField;
-
-/**
- * @since 3.9.0
- */
-public class ProposalColumnField<T> extends AbstractProposalField<T> implements IColumnWrapper<IProposalColumn<T>> {
-  private ProposalColumnFieldPropertyDelegator<T> m_propertyDelegator;
-
-  public ProposalColumnField(IProposalColumn<T> column) {
-    super(false);
-    m_propertyDelegator = new ProposalColumnFieldPropertyDelegator<T>(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IProposalColumn<T> getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-
-  @Override
-  public Class<String> getHolderType() {
-    return getWrappedObject().getDataType();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnFieldPropertyDelegator.java
deleted file mode 100644
index 5a60b6c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/ProposalColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IProposalColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.IProposalField;
-
-/**
- * @since 3.9.0
- */
-public class ProposalColumnFieldPropertyDelegator<T> extends ColumnFieldPropertyDelegator<IProposalColumn<T>, IProposalField<T>> {
-
-  public ProposalColumnFieldPropertyDelegator(IProposalColumn<T> sender, IProposalField<T> receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setCodeTypeClass(getSender().getCodeTypeClass());
-    getReceiver().setLookupCall(getSender().getLookupCall());
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnField.java
deleted file mode 100644
index 9f9d309..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnField.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ISmartColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.AbstractSmartField;
-
-/**
- * @since 3.9.0
- */
-public class SmartColumnField<T> extends AbstractSmartField<T> implements IColumnWrapper<ISmartColumn<T>> {
-  private SmartColumnFieldPropertyDelegator<T> m_propertyDelegator;
-
-  public SmartColumnField(ISmartColumn<T> column) {
-    super(false);
-    m_propertyDelegator = new SmartColumnFieldPropertyDelegator<T>(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public ISmartColumn<T> getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-
-  @Override
-  public Class<T> getHolderType() {
-    return getWrappedObject().getDataType();
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnFieldPropertyDelegator.java
deleted file mode 100644
index d14d65a..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/SmartColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.ISmartColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.smartfield.ISmartField;
-
-/**
- * @since 3.9.0
- */
-public class SmartColumnFieldPropertyDelegator<T> extends ColumnFieldPropertyDelegator<ISmartColumn<T>, ISmartField<T>> {
-
-  public SmartColumnFieldPropertyDelegator(ISmartColumn<T> sender, ISmartField<T> receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-    // Existing lookup call of receiver has higher priority. Don't overwrite it.
-    if (getReceiver().getLookupCall() == null) {
-      getReceiver().setCodeTypeClass(getSender().getCodeTypeClass());
-      getReceiver().setLookupCall(getSender().getLookupCall());
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnField.java
deleted file mode 100644
index dc6a827..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnField.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IStringColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField;
-
-/**
- * @since 3.9.0
- */
-public class StringColumnField extends AbstractStringField implements IColumnWrapper<IStringColumn> {
-  private StringColumnFieldPropertyDelegator m_propertyDelegator;
-
-  public StringColumnField(IStringColumn column) {
-    super(false);
-    m_propertyDelegator = new StringColumnFieldPropertyDelegator(column, this);
-    callInitializer();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    m_propertyDelegator.dispose();
-  }
-
-  @Override
-  public IStringColumn getWrappedObject() {
-    return m_propertyDelegator.getSender();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnFieldPropertyDelegator.java
deleted file mode 100644
index ddd1c9f..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/basic/table/form/fields/StringColumnFieldPropertyDelegator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.basic.table.form.fields;
-
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IStringColumn;
-import org.eclipse.scout.rt.client.ui.form.fields.GridData;
-import org.eclipse.scout.rt.client.ui.form.fields.stringfield.IStringField;
-
-/**
- * @since 3.9.0
- */
-public class StringColumnFieldPropertyDelegator extends ColumnFieldPropertyDelegator<IStringColumn, IStringField> {
-
-  public StringColumnFieldPropertyDelegator(IStringColumn sender, IStringField receiver) {
-    super(sender, receiver);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setInputMasked(getSender().isInputMasked());
-    getReceiver().setFormat(getSender().getDisplayFormat());
-    getReceiver().setWrapText(getSender().isTextWrap());
-    if (getSender().isTextWrap()) {
-      //Text wrap typically only works if multiline is enabled
-      getReceiver().setMultilineText(true);
-    }
-
-    if (getReceiver().isMultilineText()) {
-      //Make the field bigger in case of multiline text so the user can read / edit the data easier
-      GridData gd = getReceiver().getGridDataHints();
-      gd.h = 2;
-      getReceiver().setGridDataHints(gd);
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/ActiveOutlineObserver.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/ActiveOutlineObserver.java
deleted file mode 100644
index de7fb05..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/ActiveOutlineObserver.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.desktop;
-
-import java.beans.PropertyChangeListener;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeListener;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-
-/**
- * @since 3.9.0
- */
-public class ActiveOutlineObserver {
-  private IOutline m_activeOutline;
-  private IDesktop m_desktop;
-  private P_DesktopListener m_desktopListener;
-  private Set<TreeListener> m_outlineTreeListeners;
-  private Set<TreeListener> m_outlineUITreeListeners;
-  private Set<PropertyChangeListener> m_outlinePropertyChangeListeners;
-
-  public ActiveOutlineObserver() {
-    this(null);
-  }
-
-  public ActiveOutlineObserver(IDesktop desktop) {
-    if (desktop == null) {
-      desktop = ClientSessionProvider.currentSession().getDesktop();
-    }
-    m_desktop = desktop;
-    if (m_desktop == null) {
-      throw new IllegalArgumentException("No desktop found. Cannot create ActiveOutlineObserver.");
-    }
-
-    m_activeOutline = desktop.getOutline();
-    m_outlineTreeListeners = new HashSet<TreeListener>();
-    m_outlineUITreeListeners = new HashSet<TreeListener>();
-    m_outlinePropertyChangeListeners = new HashSet<PropertyChangeListener>();
-    m_desktopListener = new P_DesktopListener();
-    desktop.addDesktopListener(m_desktopListener);
-  }
-
-  public IDesktop getDesktop() {
-    return m_desktop;
-  }
-
-  public IOutline getActiveOutline() {
-    return m_activeOutline;
-  }
-
-  private void destroy() {
-    if (m_desktopListener != null) {
-      getDesktop().removeDesktopListener(m_desktopListener);
-      m_desktopListener = null;
-    }
-
-    removeAllListeners(m_activeOutline);
-    m_outlineTreeListeners.clear();
-    m_outlineUITreeListeners.clear();
-    m_outlinePropertyChangeListeners.clear();
-  }
-
-  public void addOutlineTreeListener(TreeListener treeListener) {
-    if (treeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.addTreeListener(treeListener);
-    }
-    m_outlineTreeListeners.add(treeListener);
-  }
-
-  public void addOutlineUITreeListener(TreeListener treeListener) {
-    if (treeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.addTreeListener(treeListener);
-    }
-    m_outlineUITreeListeners.add(treeListener);
-  }
-
-  public void addOutlinePropertyChangeListener(PropertyChangeListener propertyChangeListener) {
-    if (propertyChangeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.addPropertyChangeListener(propertyChangeListener);
-    }
-    m_outlinePropertyChangeListeners.add(propertyChangeListener);
-  }
-
-  public void removeOutlineTreeListener(TreeListener treeListener) {
-    if (treeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.removeTreeListener(treeListener);
-    }
-    m_outlineTreeListeners.remove(treeListener);
-  }
-
-  public void removeOutlineUITreeListener(TreeListener treeListener) {
-    if (treeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.removeTreeListener(treeListener);
-    }
-    m_outlineUITreeListeners.remove(treeListener);
-  }
-
-  public void removeOutlinePropertyChangeListener(PropertyChangeListener propertyChangeListener) {
-    if (propertyChangeListener == null) {
-      return;
-    }
-
-    if (m_activeOutline != null) {
-      m_activeOutline.removePropertyChangeListener(propertyChangeListener);
-    }
-    m_outlinePropertyChangeListeners.remove(propertyChangeListener);
-  }
-
-  private void removeAllListeners(IOutline outline) {
-    if (outline == null) {
-      return;
-    }
-
-    for (TreeListener treeListener : m_outlineTreeListeners) {
-      outline.removeTreeListener(treeListener);
-    }
-    for (TreeListener treeListener : m_outlineUITreeListeners) {
-      outline.removeTreeListener(treeListener);
-    }
-    for (PropertyChangeListener propertyChangeListener : m_outlinePropertyChangeListeners) {
-      outline.removePropertyChangeListener(propertyChangeListener);
-    }
-  }
-
-  private void addAllListeners(IOutline outline) {
-    if (outline == null) {
-      return;
-    }
-
-    for (TreeListener treeListener : m_outlineTreeListeners) {
-      outline.addTreeListener(treeListener);
-    }
-    for (TreeListener treeListener : m_outlineUITreeListeners) {
-      outline.addUITreeListener(treeListener);
-    }
-    for (PropertyChangeListener propertyChangeListener : m_outlinePropertyChangeListeners) {
-      outline.addPropertyChangeListener(propertyChangeListener);
-    }
-  }
-
-  private class P_DesktopListener implements DesktopListener {
-
-    @Override
-    public void desktopChanged(DesktopEvent e) {
-
-      switch (e.getType()) {
-        case DesktopEvent.TYPE_DESKTOP_CLOSED: {
-          destroy();
-          break;
-        }
-        case DesktopEvent.TYPE_OUTLINE_CHANGED: {
-          handleOutlineChanged(e);
-          break;
-        }
-        default:
-          break;
-      }
-    }
-
-    private void handleOutlineChanged(DesktopEvent e) {
-      IOutline outline = e.getOutline();
-
-      if (m_activeOutline != null) {
-        removeAllListeners(m_activeOutline);
-      }
-
-      if (outline != null) {
-        addAllListeners(outline);
-      }
-
-      m_activeOutline = outline;
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/DeviceTransformationDesktopExtension.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/DeviceTransformationDesktopExtension.java
deleted file mode 100644
index e0a5c7e..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/DeviceTransformationDesktopExtension.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.desktop;
-
-import java.util.Collection;
-
-import org.eclipse.scout.rt.client.mobile.navigation.AbstractMobileBackAction;
-import org.eclipse.scout.rt.client.mobile.navigation.AbstractMobileHomeAction;
-import org.eclipse.scout.rt.client.mobile.navigation.IBreadCrumbsNavigationService;
-import org.eclipse.scout.rt.client.mobile.transformation.IDeviceTransformationService;
-import org.eclipse.scout.rt.client.mobile.transformation.IDeviceTransformer;
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktopExtension;
-import org.eclipse.scout.rt.client.ui.desktop.ContributionCommand;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.holders.IHolder;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
-
-public class DeviceTransformationDesktopExtension extends AbstractDesktopExtension {
-  private boolean m_active;
-  private IDeviceTransformer m_deviceTransformer;
-
-  public DeviceTransformationDesktopExtension() {
-    setActive(UserAgentUtility.isTouchDevice());
-  }
-
-  public boolean isActive() {
-    return m_active;
-  }
-
-  public void setActive(boolean active) {
-    m_active = active;
-  }
-
-  @Override
-  public void setCoreDesktop(IDesktop desktop) {
-    super.setCoreDesktop(desktop);
-
-    if (isActive()) {
-      BEANS.get(IBreadCrumbsNavigationService.class).install(getCoreDesktop());
-      BEANS.get(IDeviceTransformationService.class).install(getCoreDesktop());
-    }
-  }
-
-  public IDeviceTransformer getDeviceTransformer() {
-    if (m_deviceTransformer == null) {
-      m_deviceTransformer = BEANS.get(IDeviceTransformationService.class).getDeviceTransformer();
-    }
-
-    return m_deviceTransformer;
-  }
-
-  @Override
-  protected ContributionCommand execInit() {
-    if (!isActive()) {
-      return super.execInit();
-    }
-
-    getDeviceTransformer().transformDesktop();
-    return ContributionCommand.Continue;
-  }
-
-  @Override
-  protected ContributionCommand execClosing() {
-    if (!isActive()) {
-      return super.execClosing();
-    }
-
-    getDeviceTransformer().notifyDesktopClosing();
-    return ContributionCommand.Continue;
-  }
-
-  @Override
-  public void contributeActions(Collection<IAction> actions) {
-    if (!isActive()) {
-      return;
-    }
-
-    getDeviceTransformer().adaptDesktopActions(actions);
-    super.contributeActions(actions);
-  }
-
-  @Override
-  public void contributeOutlines(OrderedCollection<IOutline> outlines) {
-    if (!isActive()) {
-      return;
-    }
-
-    getDeviceTransformer().adaptDesktopOutlines(outlines);
-    super.contributeOutlines(outlines);
-  }
-
-  @Override
-  protected ContributionCommand execOutlineChanged(IOutline oldOutline, IOutline newOutline) {
-    if (!isActive()) {
-      return super.execOutlineChanged(oldOutline, newOutline);
-    }
-
-    getDeviceTransformer().transformOutline(newOutline);
-
-    return ContributionCommand.Continue;
-  }
-
-  @Override
-  protected ContributionCommand execPageDetailTableChanged(ITable oldTable, ITable newTable) {
-    if (!isActive()) {
-      return super.execPageDetailTableChanged(oldTable, newTable);
-    }
-
-    getDeviceTransformer().transformPageDetailTable(newTable);
-
-    return ContributionCommand.Continue;
-  }
-
-  @Override
-  protected ContributionCommand execFormAboutToShow(IHolder<IForm> formHolder) {
-    if (!isActive()) {
-      return super.execFormAboutToShow(formHolder);
-    }
-
-    IForm form = formHolder.getValue();
-    if (form == null) {
-      return ContributionCommand.Stop;
-    }
-
-    try {
-      getDeviceTransformer().transformForm(form);
-    }
-    catch (RuntimeException e) {
-      BEANS.get(ExceptionHandler.class).handle(e);
-    }
-
-    if (!getDeviceTransformer().acceptFormAddingToDesktop(form)) {
-      formHolder.setValue(null);
-      return ContributionCommand.Stop;
-    }
-
-    return ContributionCommand.Continue;
-  }
-
-  @Override
-  protected ContributionCommand execTablePageLoaded(IPageWithTable<?> tablePage) {
-    if (!isActive()) {
-      return super.execTablePageLoaded(tablePage);
-    }
-
-    getDeviceTransformer().notifyTablePageLoaded(tablePage);
-
-    return ContributionCommand.Continue;
-  }
-
-  @Order(10)
-  public class BackAction extends AbstractMobileBackAction {
-
-    @Override
-    protected boolean getConfiguredVisible() {
-      return false;
-    }
-
-  }
-
-  @Order(20)
-  public class HomeAction extends AbstractMobileHomeAction {
-
-    @Override
-    protected boolean getConfiguredVisible() {
-      return false;
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MobileDesktopUtility.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MobileDesktopUtility.java
deleted file mode 100644
index 84f9a61..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MobileDesktopUtility.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.desktop;
-
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.action.tool.IToolButton;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.GridData;
-
-/**
- * @since 3.9.0
- */
-public class MobileDesktopUtility {
-
-  public static void activateOutline(IOutline outline) {
-    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
-
-    if (desktop.getOutline() != outline) {
-      desktop.activateOutline(outline);
-    }
-
-    if (!outline.isRootNodeVisible()) {
-      throw new IllegalStateException("Root node must be visible for this drill down approach.");
-    }
-
-    if (outline.getSelectedNode() == null) {
-      outline.selectNode(outline.getRootPage());
-    }
-  }
-
-  public static boolean isToolForm(IForm form) {
-    if (getToolButtonFor(form) != null) {
-      return true;
-    }
-
-    return false;
-  }
-
-  public static IToolButton getToolButtonFor(IForm form) {
-    for (IToolButton toolButton : getDesktop().getToolButtons()) {
-      if (toolButton instanceof AbstractFormToolButton) {
-        IForm toolForm = ((AbstractFormToolButton<?>) toolButton).getForm();
-        if (form == toolForm) {
-          return toolButton;
-        }
-      }
-    }
-
-    return null;
-  }
-
-  public static void openToolForm(IForm form) {
-    IToolButton toolButton = getToolButtonFor(form);
-    if (toolButton != null) {
-      toolButton.setSelected(true);
-    }
-    //Double check to make sure it really will be added
-    if (!getDesktop().isShowing(form)) {
-      getDesktop().showForm(form);
-    }
-  }
-
-  public static void closeToolForm(IForm form) {
-    IToolButton toolButton = getToolButtonFor(form);
-    if (toolButton != null) {
-      toolButton.setSelected(false);
-    }
-    //Double check to make sure it really will be removed
-    if (getDesktop().isShowing(form)) {
-      getDesktop().hideForm(form);
-    }
-  }
-
-  public static void closeAllToolForms() {
-    for (IToolButton toolButton : getDesktop().getToolButtons()) {
-      if (toolButton.isVisible()) {
-        toolButton.setSelected(false);
-      }
-    }
-  }
-
-  public static void closeOpenForms() {
-    for (IForm view : getDesktop().getViews()) {
-      closeForm(view);
-    }
-  }
-
-  public static void closeForm(IForm form) {
-    if (form == null) {
-      return;
-    }
-
-    if (MobileDesktopUtility.isToolForm(form)) {
-      MobileDesktopUtility.closeToolForm(form);
-    }
-    else if (form.isShowOnStart()) {
-      form.doClose();
-    }
-    else {
-      removeFormFromDesktop(form);
-    }
-  }
-
-  public static void removeFormFromDesktop(IForm form) {
-    getDesktop().hideForm(form);
-  }
-
-  public static void removeFormsFromDesktop(Class<? extends IForm> formClass, String displayViewId, IForm excludedForm) {
-    if (displayViewId == null) {
-      return;
-    }
-
-    for (IForm view : getDesktop().getViews()) {
-      if (view != excludedForm && formClass.isInstance(view) && displayViewId.equals(view.getDisplayViewId())) {
-        getDesktop().hideForm(view);
-      }
-    }
-  }
-
-  public static void addFormToDesktop(IForm form) {
-    if (isToolForm(form)) {
-      openToolForm(form);
-    }
-    else {
-      getDesktop().showForm(form);
-    }
-  }
-
-  private static IDesktop getDesktop() {
-    return ClientSessionProvider.currentSession().getDesktop();
-  }
-
-  public static boolean isAnyViewVisible(String displayViewId) {
-    if (displayViewId == null) {
-      return false;
-    }
-
-    for (IForm view : getDesktop().getViews()) {
-      if (displayViewId.equals(view.getDisplayViewId())) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  public static boolean setFormWidthHint(IForm form, int widthHint) {
-    GridData gridDataHints = form.getRootGroupBox().getGridDataHints();
-    if (gridDataHints.widthInPixel == widthHint) {
-      return false;
-    }
-
-    gridDataHints.widthInPixel = widthHint;
-    form.getRootGroupBox().setGridDataHints(gridDataHints);
-    return true;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MultiPageChangeStrategy.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MultiPageChangeStrategy.java
deleted file mode 100644
index 5815ba4..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/desktop/MultiPageChangeStrategy.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.desktop;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.PageFormManager;
-import org.eclipse.scout.rt.client.ui.desktop.outline.DefaultPageChangeStrategy;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IPageChangeStrategy;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @since 3.9.0
- */
-public class MultiPageChangeStrategy implements IPageChangeStrategy {
-  private static final Logger LOG = LoggerFactory.getLogger(MultiPageChangeStrategy.class);
-
-  private IOutline m_outline;
-  private IPage<?> m_mainPage;
-  private IPage<?> m_subPage;
-  private PageFormManager m_pageFormManager;
-  private DefaultPageChangeStrategy m_defaultPageChangeStrategy;
-
-  public MultiPageChangeStrategy(PageFormManager pageFormManager) {
-    m_defaultPageChangeStrategy = new DefaultPageChangeStrategy();
-    m_pageFormManager = pageFormManager;
-  }
-
-  @Override
-  public void pageChanged(IOutline outline, IPage<?> deselectedPage, IPage<?> selectedPage) {
-    if (outline == null) {
-      return;
-    }
-
-    if (outline != m_outline) {
-      m_mainPage = null;
-      m_subPage = null;
-      m_outline = outline;
-    }
-
-    if (selectedPage == null) {
-      activateMainPage(deselectedPage, selectedPage);
-    }
-    else {
-      String pageFormSlot = m_pageFormManager.computePageFormSlot(selectedPage);
-      if (m_pageFormManager.getLeftPageSlotViewId().equals(pageFormSlot)) {
-        activateMainPage(deselectedPage, selectedPage);
-      }
-      else {
-        activateMainPage(deselectedPage, selectedPage.getParentPage());
-        activateSubPage(selectedPage);
-      }
-    }
-  }
-
-  private void activateMainPage(IPage<?> deselectedPage, IPage<?> selectedPage) {
-    if (m_mainPage == selectedPage) {
-      return;
-    }
-    deactivateSubPage();
-
-    m_defaultPageChangeStrategy.pageChanged(m_outline, deselectedPage, selectedPage);
-    m_mainPage = selectedPage;
-
-    LOG.debug("Main page activated: {}", selectedPage);
-  }
-
-  private void activateSubPage(IPage<?> selectedPage) {
-    if (m_subPage == selectedPage) {
-      return;
-    }
-    deactivateSubPage();
-
-    m_subPage = selectedPage;
-    if (m_subPage != null) {
-      m_subPage.pageActivatedNotify();
-
-      try {
-        m_subPage.ensureChildrenLoaded();
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-
-      LOG.debug("Sub page activated: {}", selectedPage);
-    }
-  }
-
-  private void deactivateSubPage() {
-    if (m_subPage == null) {
-      return;
-    }
-
-    m_subPage.pageDeactivatedNotify();
-    m_subPage = null;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractFormActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractFormActionFetcher.java
deleted file mode 100644
index 9af740b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractFormActionFetcher.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.action.ActionButtonBarUtility;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-
-public abstract class AbstractFormActionFetcher implements IActionFetcher {
-  private IForm m_form;
-
-  public AbstractFormActionFetcher(IForm form) {
-    m_form = form;
-  }
-
-  public IForm getForm() {
-    return m_form;
-  }
-
-  protected List<IMobileAction> convertCustomProcessButtons() {
-    List<IButton> customProcessButtons = getForm().getRootGroupBox().getCustomProcessButtons();
-
-    if (CollectionUtility.hasElements(customProcessButtons)) {
-      return ActionButtonBarUtility.convertButtonsToActions(getForm().getRootGroupBox().getCustomProcessButtons());
-    }
-    else {
-      return CollectionUtility.emptyArrayList();
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileAction.java
deleted file mode 100644
index 64b7db1..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileAction.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
-
-/**
- * @since 3.9.0
- */
-public abstract class AbstractMobileAction extends AbstractMenu implements IMobileAction {
-
-  public AbstractMobileAction() {
-    super();
-  }
-
-  public AbstractMobileAction(boolean callInitializer) {
-    super(callInitializer);
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    setHorizontalAlignment(getConfiguredHorizontalAlignment());
-  }
-
-  @Override
-  public int getHorizontalAlignment() {
-    return getHorizontalAlignment(this);
-  }
-
-  @Override
-  public void setHorizontalAlignment(int alignment) {
-    setHorizontalAlignment(this, alignment);
-  }
-
-  public static int getHorizontalAlignment(IAction action) {
-    Number n = (Number) action.getProperty(PROP_HORIZONTAL_ALIGNMENT);
-    return n != null ? n.intValue() : 0;
-  }
-
-  public static void setHorizontalAlignment(IAction action, int alignment) {
-    action.setProperty(PROP_HORIZONTAL_ALIGNMENT, alignment);
-  }
-
-  @Override
-  protected int getConfiguredHorizontalAlignment() {
-    return HORIZONTAL_ALIGNMENT_RIGHT;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileForm.java
deleted file mode 100644
index fdfaf8c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/AbstractMobileForm.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import org.eclipse.scout.rt.client.ui.form.AbstractForm;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public abstract class AbstractMobileForm extends AbstractForm implements IMobileForm {
-
-  public AbstractMobileForm() {
-    this(true);
-  }
-
-  public AbstractMobileForm(boolean callInitializer) {
-    super(callInitializer);
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    setHeaderVisible(getConfiguredHeaderVisible());
-    setFooterVisible(getConfiguredFooterVisible());
-    setHeaderActionFetcher(createHeaderActionFetcher());
-    setFooterActionFetcher(createFooterActionFetcher());
-  }
-
-  protected boolean getConfiguredHeaderVisible() {
-    return false;
-  }
-
-  protected boolean getConfiguredFooterVisible() {
-    return false;
-  }
-
-  @Override
-  public boolean isHeaderVisible() {
-    return isHeaderVisible(this);
-  }
-
-  @Override
-  public void setHeaderVisible(boolean visible) {
-    setHeaderVisible(this, visible);
-  }
-
-  public static void setHeaderVisible(IForm form, boolean visible) {
-    form.setProperty(PROP_HEADER_VISIBLE, visible);
-  }
-
-  public static boolean isHeaderVisible(IForm form) {
-    Boolean b = (Boolean) form.getProperty(PROP_HEADER_VISIBLE);
-    return b != null ? b.booleanValue() : false;
-  }
-
-  @Override
-  public boolean isFooterVisible() {
-    return isFooterVisible(this);
-  }
-
-  @Override
-  public void setFooterVisible(boolean visible) {
-    setFooterVisible(this, visible);
-  }
-
-  public static boolean isFooterVisible(IForm form) {
-    Boolean b = (Boolean) form.getProperty(PROP_FOOTER_VISIBLE);
-    return b != null ? b.booleanValue() : false;
-  }
-
-  public static void setFooterVisible(IForm form, boolean visible) {
-    form.setProperty(PROP_FOOTER_VISIBLE, visible);
-  }
-
-  protected IActionFetcher createHeaderActionFetcher() {
-    return new FormHeaderActionFetcher(this);
-  }
-
-  protected IActionFetcher createFooterActionFetcher() {
-    return new FormFooterActionFetcher(this);
-  }
-
-  public static IActionFetcher getHeaderActionFetcher(IForm form) {
-    return (IActionFetcher) form.getProperty(IMobileForm.PROP_HEADER_ACTION_FETCHER);
-  }
-
-  public static void setHeaderActionFetcher(IForm form, IActionFetcher headerActionFetcher) {
-    form.setProperty(IMobileForm.PROP_HEADER_ACTION_FETCHER, headerActionFetcher);
-  }
-
-  @Override
-  public IActionFetcher getHeaderActionFetcher() {
-    return getHeaderActionFetcher(this);
-  }
-
-  @Override
-  public void setHeaderActionFetcher(IActionFetcher headerActionFetcher) {
-    setHeaderActionFetcher(this, headerActionFetcher);
-  }
-
-  @Override
-  public IActionFetcher getFooterActionFetcher() {
-    return getFooterActionFetcher(this);
-  }
-
-  @Override
-  public void setFooterActionFetcher(IActionFetcher footerActionFetcher) {
-    setFooterActionFetcher(this, footerActionFetcher);
-  }
-
-  public static IActionFetcher getFooterActionFetcher(IForm form) {
-    return (IActionFetcher) form.getProperty(IMobileForm.PROP_FOOTER_ACTION_FETCHER);
-  }
-
-  public static void setFooterActionFetcher(IForm form, IActionFetcher footerActionFetcher) {
-    form.setProperty(IMobileForm.PROP_FOOTER_ACTION_FETCHER, footerActionFetcher);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormFooterActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormFooterActionFetcher.java
deleted file mode 100644
index fcb90dc..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormFooterActionFetcher.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * Converts the custom process buttons of the main box to actions.
- * <p>
- * The custom process buttons will be placed on the left side.
- */
-public class FormFooterActionFetcher extends AbstractFormActionFetcher {
-
-  public FormFooterActionFetcher(IForm form) {
-    super(form);
-  }
-
-  @Override
-  public List<IMenu> fetch() {
-    List<IMenu> formActions = new LinkedList<IMenu>();
-    if (getForm().getRootGroupBox().getCustomProcessButtonCount() > 0) {
-      List<IMobileAction> leftActions = createLeftFooterActions();
-      for (IMobileAction action : leftActions) {
-        action.setHorizontalAlignment(IMobileAction.HORIZONTAL_ALIGNMENT_LEFT);
-      }
-      formActions.addAll(leftActions);
-    }
-    return formActions;
-  }
-
-  protected List<IMobileAction> createLeftFooterActions() {
-    return convertCustomProcessButtons();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormHeaderActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormHeaderActionFetcher.java
deleted file mode 100644
index 515d7c0..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/FormHeaderActionFetcher.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.action.ActionButtonBarUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.button.IMobileButton;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Converts the system and custom process buttons of the main box to actions.
- * <p>
- * The custom process buttons will be placed on the right side, the placement of the system process buttons depend on
- * the system type (see {@link #getRelevantSystemTypesForLeftHeader()} and
- * {@link #getRelevantSystemTypesForRightHeader()})
- */
-public class FormHeaderActionFetcher extends AbstractFormActionFetcher {
-  private static final Logger LOG = LoggerFactory.getLogger(FormHeaderActionFetcher.class);
-
-  public FormHeaderActionFetcher(IForm form) {
-    super(form);
-  }
-
-  @Override
-  public List<IMenu> fetch() {
-    List<IMenu> formActions = new LinkedList<IMenu>();
-
-    if (getForm().getRootGroupBox().getSystemProcessButtonCount() > 0) {
-      List<IMobileAction> leftActions = createLeftActions();
-      if (leftActions != null) {
-        for (IMobileAction action : leftActions) {
-          action.setHorizontalAlignment(IMobileAction.HORIZONTAL_ALIGNMENT_LEFT);
-        }
-        formActions.addAll(leftActions);
-      }
-    }
-    if (getForm().getRootGroupBox().getSystemProcessButtonCount() > 0 || getForm().getRootGroupBox().getCustomProcessButtonCount() > 0) {
-      List<IMobileAction> rightActions = createRightActions();
-      if (rightActions != null) {
-        for (IMobileAction action : rightActions) {
-          action.setHorizontalAlignment(IMobileAction.HORIZONTAL_ALIGNMENT_RIGHT);
-        }
-      }
-      formActions.addAll(rightActions);
-    }
-
-    return formActions;
-  }
-
-  /**
-   * If there are multiple buttons with a matching system types the order given in the list is used to sort the buttons.
-   */
-  protected List<IMobileAction> convertSystemProcessButtons(final List<Integer> relevantSystemTypes) {
-    if (relevantSystemTypes == null || relevantSystemTypes.size() == 0) {
-      return null;
-    }
-
-    List<IButton> systemProcessButtons = getForm().getRootGroupBox().getSystemProcessButtons();
-    if (!CollectionUtility.hasElements(systemProcessButtons)) {
-      return null;
-    }
-
-    IButton[] array = systemProcessButtons.toArray(new IButton[systemProcessButtons.size()]);
-    // sort
-    Comparator<IButton> comparator = new Comparator<IButton>() {
-      @Override
-      public int compare(IButton button1, IButton button2) {
-        int index1 = relevantSystemTypes.indexOf(button1.getSystemType());
-        int index2 = relevantSystemTypes.indexOf(button2.getSystemType());
-        if (index1 >= index2) {
-          return 1;
-        }
-        else {
-          return -1;
-        }
-      }
-    };
-    Arrays.sort(array, comparator);
-
-    List<IMobileAction> sortedActions = new ArrayList<IMobileAction>(array.length);
-    for (IButton scoutButton : array) {
-      if (relevantSystemTypes.contains(scoutButton.getSystemType())) {
-        try {
-          sortedActions.add(ActionButtonBarUtility.convertButtonToAction(scoutButton));
-        }
-        catch (RuntimeException e) {
-          LOG.error("could not initialize actions.", e);
-        }
-      }
-    }
-    return sortedActions;
-  }
-
-  protected List<IMobileAction> createLeftActions() {
-    return convertSystemProcessButtons(getRelevantSystemTypesForLeftSide());
-  }
-
-  protected List<IMobileAction> createRightActions() {
-    List<IMobileAction> actions = new LinkedList<IMobileAction>();
-
-    List<IMobileAction> systemActions = convertSystemProcessButtons(getRelevantSystemTypesForRightSide());
-    if (systemActions != null) {
-      actions.addAll(systemActions);
-    }
-
-    try {
-      actions.addAll(convertCustomProcessButtons());
-    }
-    catch (RuntimeException e) {
-      LOG.error("could not initialze actions.", e);
-    }
-
-    return actions;
-  }
-
-  protected List<Integer> getRelevantSystemTypesForLeftSide() {
-    List<Integer> systemTypesToConsider = new LinkedList<Integer>();
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_CANCEL);
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_CLOSE);
-    systemTypesToConsider.add(IMobileButton.SYSTEM_TYPE_BACK);
-    return systemTypesToConsider;
-  }
-
-  /**
-   * Returns the system types which are relevant for the right button bar. The order of the list is taken into account
-   * too.
-   */
-  protected List<Integer> getRelevantSystemTypesForRightSide() {
-    List<Integer> systemTypesToConsider = new LinkedList<Integer>();
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_OK);
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_SAVE);
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_SAVE_WITHOUT_MARKER_CHANGE);
-    systemTypesToConsider.add(IButton.SYSTEM_TYPE_RESET);
-
-    return systemTypesToConsider;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IActionFetcher.java
deleted file mode 100644
index 416be15..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IActionFetcher.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-
-/**
- * @since 3.9.0
- */
-public interface IActionFetcher {
-  List<IMenu> fetch();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileAction.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileAction.java
deleted file mode 100644
index 1e59fdc..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileAction.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-
-/**
- * @since 3.9.0
- */
-public interface IMobileAction extends IMenu {
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileForm.java
deleted file mode 100644
index 08d58db..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/IMobileForm.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public interface IMobileForm extends IForm {
-  String PROP_HEADER_VISIBLE = "headerVisible";
-  String PROP_FOOTER_VISIBLE = "footerVisible";
-  String PROP_HEADER_ACTION_FETCHER = "headerActionFetcher";
-  String PROP_FOOTER_ACTION_FETCHER = "footerActionFetcher";
-
-  boolean isHeaderVisible();
-
-  void setHeaderVisible(boolean visible);
-
-  boolean isFooterVisible();
-
-  void setFooterVisible(boolean visible);
-
-  IActionFetcher getHeaderActionFetcher();
-
-  void setHeaderActionFetcher(IActionFetcher headerActionFetcher);
-
-  IActionFetcher getFooterActionFetcher();
-
-  void setFooterActionFetcher(IActionFetcher footerActionFetcher);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/FormFieldPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/FormFieldPropertyDelegator.java
deleted file mode 100644
index eb8c14b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/FormFieldPropertyDelegator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields;
-
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-
-public class FormFieldPropertyDelegator<SENDER extends IFormField, RECEIVER extends IFormField> extends PropertyDelegator<SENDER, RECEIVER> {
-
-  public FormFieldPropertyDelegator(SENDER sendingField, RECEIVER receivingField) {
-    super(sendingField, receivingField);
-  }
-
-  @Override
-  public void init() {
-    getReceiver().setVisible(getSender().isVisible());
-    if (!getSender().isVisible()) {
-      //Since AbstractFormField#calculateVisibleInternal may ignore this property only set it if it hasn't been ignored (to not override those rules)
-      getReceiver().setVisibleGranted(getSender().isVisibleGranted());
-    }
-    getReceiver().setEnabled(getSender().isEnabled());
-    if (!getSender().isEnabled()) {
-      //Since AbstractFormField#calculateEnabled may ignore this property only set it if it hasn't been ignored (to not override those rules)
-      getReceiver().setEnabledGranted(getSender().isEnabledGranted());
-    }
-    getReceiver().setLabel(getSender().getLabel());
-    getReceiver().setTooltipText(getSender().getTooltipText());
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    if (name.equals(IFormField.PROP_VISIBLE)) {
-      getReceiver().setVisible(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IFormField.PROP_ENABLED)) {
-      getReceiver().setEnabled(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IFormField.PROP_LABEL)) {
-      getReceiver().setLabel(((String) newValue));
-    }
-    else if (name.equals(IFormField.PROP_TOOLTIP_TEXT)) {
-      getReceiver().setTooltipText((String) newValue);
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/IWrapper.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/IWrapper.java
deleted file mode 100644
index 07a085a..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/IWrapper.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields;
-
-import org.eclipse.scout.rt.platform.reflect.IPropertyObserver;
-
-/**
- * @since 3.9.0
- */
-public interface IWrapper<WRAPPABLE extends IPropertyObserver> {
-  WRAPPABLE getWrappedObject();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/PropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/PropertyDelegator.java
deleted file mode 100644
index e7430eb..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/PropertyDelegator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.scout.rt.platform.reflect.IPropertyObserver;
-import org.eclipse.scout.rt.platform.util.WeakEventListener;
-
-public class PropertyDelegator<SENDER extends IPropertyObserver, RECEIVER extends IPropertyObserver> {
-  private P_PropertyChangeListener m_propertyChangeListener;
-  private Set<String> m_filter;
-  private SENDER m_sender;
-  private RECEIVER m_receiver;
-
-  public PropertyDelegator(SENDER sender, RECEIVER receiver) {
-    this(sender, receiver, null);
-  }
-
-  public PropertyDelegator(SENDER sender, RECEIVER receiver, Set<String> filteredPropertyNames) {
-    m_sender = sender;
-    m_receiver = receiver;
-
-    m_filter = filteredPropertyNames;
-    if (m_filter == null) {
-      m_filter = new HashSet<String>();
-    }
-    m_propertyChangeListener = new P_PropertyChangeListener();
-    m_sender.addPropertyChangeListener(m_propertyChangeListener);
-  }
-
-  public SENDER getSender() {
-    return m_sender;
-  }
-
-  public RECEIVER getReceiver() {
-    return m_receiver;
-  }
-
-  /**
-   * Fills the properties of the receiver with the values of the sender. Typically used at the initialization of objects
-   * e.g. at initConfig() of a form field.
-   */
-  public void init() {
-  }
-
-  /**
-   * Removes registered listeners.
-   */
-  public void dispose() {
-    m_sender.removePropertyChangeListener(m_propertyChangeListener);
-    m_propertyChangeListener = null;
-  }
-
-  protected void handlePropertyChange(String name, Object newValue) {
-  }
-
-  private class P_PropertyChangeListener implements PropertyChangeListener, WeakEventListener {
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-      if (!m_filter.contains(evt.getPropertyName())) {
-        handlePropertyChange(evt.getPropertyName(), evt.getNewValue());
-      }
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/AbstractBackButton.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/AbstractBackButton.java
deleted file mode 100644
index 39f8329..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/AbstractBackButton.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.button;
-
-import org.eclipse.scout.rt.client.mobile.Icons;
-import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractButton;
-import org.eclipse.scout.rt.platform.classid.ClassId;
-
-/**
- * @since 3.9.0
- */
-@ClassId("c4faa795-efda-47d3-9a89-dc249edd002a")
-public abstract class AbstractBackButton extends AbstractButton implements IMobileButton {
-
-  @Override
-  protected String getConfiguredLabel() {
-    return null;
-  }
-
-  @Override
-  protected String getConfiguredIconId() {
-    return Icons.BackAction;
-  }
-
-  @Override
-  protected String getConfiguredTooltipText() {
-    return null;
-  }
-
-  @Override
-  protected int getConfiguredSystemType() {
-    return SYSTEM_TYPE_BACK;
-  }
-
-  @Override
-  protected void execClickAction() {
-    getForm().doOk();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/IMobileButton.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/IMobileButton.java
deleted file mode 100644
index 90f94ec..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/button/IMobileButton.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.button;
-
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-
-public interface IMobileButton extends IButton {
-  int SYSTEM_TYPE_BACK = 100;
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/groupbox/GroupBoxPropertyDelegator.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/groupbox/GroupBoxPropertyDelegator.java
deleted file mode 100644
index 65a055d..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/groupbox/GroupBoxPropertyDelegator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.groupbox;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.FormFieldPropertyDelegator;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
-
-public class GroupBoxPropertyDelegator extends FormFieldPropertyDelegator<IGroupBox, IGroupBox> {
-
-  public GroupBoxPropertyDelegator(IGroupBox sendingField, IGroupBox receivingField) {
-    super(sendingField, receivingField);
-  }
-
-  @Override
-  public void init() {
-    super.init();
-
-    getReceiver().setBorderVisible(getSender().isBorderVisible());
-    getReceiver().setBorderDecoration(getSender().getBorderDecoration());
-    getReceiver().setExpanded(getSender().isExpanded());
-    getReceiver().setBackgroundImageName(getSender().getBackgroundImageName());
-    getReceiver().setBackgroundImageHorizontalAlignment(getSender().getBackgroundImageHorizontalAlignment());
-    getReceiver().setBackgroundImageVerticalAlignment(getSender().getBackgroundImageVerticalAlignment());
-  }
-
-  @Override
-  protected void handlePropertyChange(String name, Object newValue) {
-    super.handlePropertyChange(name, newValue);
-
-    if (name.equals(IGroupBox.PROP_BORDER_VISIBLE)) {
-      getReceiver().setBorderVisible(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IGroupBox.PROP_BORDER_DECORATION)) {
-      getReceiver().setBorderDecoration(((String) newValue));
-    }
-    else if (name.equals(IGroupBox.PROP_EXPANDED)) {
-      getReceiver().setExpanded(((Boolean) newValue).booleanValue());
-    }
-    else if (name.equals(IGroupBox.PROP_BACKGROUND_IMAGE_NAME)) {
-      getReceiver().setBackgroundImageName((String) newValue);
-    }
-    else if (name.equals(IGroupBox.PROP_BACKGROUND_IMAGE_HORIZONTAL_ALIGNMENT)) {
-      getReceiver().setBackgroundImageHorizontalAlignment((Integer) newValue);
-    }
-    else if (name.equals(IGroupBox.PROP_BACKGROUND_IMAGE_VERTICAL_ALIGNMENT)) {
-      getReceiver().setBackgroundImageVerticalAlignment((Integer) newValue);
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/smartfield/CustomTextLookupRow.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/smartfield/CustomTextLookupRow.java
deleted file mode 100644
index 6c12c0c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/smartfield/CustomTextLookupRow.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.smartfield;
-
-import org.eclipse.scout.rt.shared.services.lookup.LookupRow;
-
-public class CustomTextLookupRow<LOOKUP_TYPE> extends LookupRow<LOOKUP_TYPE> {
-
-  private static final long serialVersionUID = 1L;
-
-  public CustomTextLookupRow(String text) {
-    super(null, text);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxGroupBox.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxGroupBox.java
deleted file mode 100644
index 2a05d76..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxGroupBox.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox;
-
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.FormFieldPropertyDelegator;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.ITabBox;
-import org.eclipse.scout.rt.platform.Order;
-
-/**
- * Group box which represents a {@link ITabBox} and contains a {@link TabBoxTableField} to represent the tab items.
- * 
- * @since 3.9.0
- */
-public class TabBoxGroupBox extends AbstractGroupBox {
-  private FormFieldPropertyDelegator<ITabBox, IGroupBox> m_propertyDelegator;
-
-  public TabBoxGroupBox(ITabBox tabBox) {
-    super(false);
-    m_propertyDelegator = new FormFieldPropertyDelegator<ITabBox, IGroupBox>(tabBox, this);
-    callInitializer();
-    setFormInternal(tabBox.getForm());
-    rebuildFieldGrid();
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_propertyDelegator.init();
-  }
-
-  @Override
-  protected void execInitField() {
-    getTableField().initField();
-  }
-
-  @Override
-  protected void execDisposeField() {
-    super.execDisposeField();
-
-    m_propertyDelegator.dispose();
-  }
-
-  public ITabBox getTabBox() {
-    return m_propertyDelegator.getSender();
-  }
-
-  public TableField getTableField() {
-    return getFieldByClass(TableField.class);
-  }
-
-  @Order(10)
-  public class TableField extends TabBoxTableField {
-
-    @Override
-    protected ITabBox getConfiguredTabBox() {
-      return TabBoxGroupBox.this.getTabBox();
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxTableField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxTableField.java
deleted file mode 100644
index ca11fb0..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabBoxTableField.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.AbstractMobileTable;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.ClearTableSelectionFormCloseListener;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox.TabBoxTableField.Table;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.tabbox.ITabBox;
-import org.eclipse.scout.rt.client.ui.form.fields.tablefield.AbstractTableField;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-
-/**
- * @since 3.9.0
- */
-public class TabBoxTableField extends AbstractTableField<Table> {
-  private ITabBox m_tabBox;
-
-  public ITabBox getTabBox() {
-    return m_tabBox;
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    m_tabBox = getConfiguredTabBox();
-  }
-
-  protected ITabBox getConfiguredTabBox() {
-    return null;
-  }
-
-  @Override
-  protected void execInitField() {
-    if (m_tabBox == null) {
-      return;
-    }
-
-    for (IGroupBox groupBox : m_tabBox.getGroupBoxes()) {
-      groupBox.addPropertyChangeListener(new P_TabPropertyChangeListener());
-    }
-
-    rebuildTableRows();
-  }
-
-  public void rebuildTableRows() {
-    if (m_tabBox == null) {
-      return;
-    }
-
-    getTable().discardAllRows();
-
-    for (IGroupBox groupBox : m_tabBox.getGroupBoxes()) {
-      if (groupBox.isVisible()) {
-        getTable().addRowByArray(new Object[]{groupBox, groupBox.getLabel()});
-      }
-    }
-
-    getParentGroupBox().rebuildFieldGrid();
-  }
-
-  @Override
-  protected boolean getConfiguredLabelVisible() {
-    return false;
-  }
-
-  @Override
-  protected boolean getConfiguredGridUseUiHeight() {
-    return true;
-  }
-
-  @Order(10)
-  public class Table extends AbstractMobileTable {
-
-    @Override
-    protected void execRowsSelected(List<? extends ITableRow> rows) {
-      if (getSelectedRow() == null) {
-        return;
-      }
-
-      IGroupBox tab = getTabColumn().getValue(getSelectedRow());
-      TabForm form = new TabForm(tab);
-      form.getRootGroupBox().setFormInternal(getForm()); // set the original form to be the owner-form to have proper model context (Bugzilla 149246).
-      form.setDisplayHint(getForm().getDisplayHint());
-      form.setDisplayViewId(getForm().getDisplayViewId());
-      form.setModal(IForm.DISPLAY_HINT_DIALOG == form.getDisplayHint());
-      form.start();
-      form.addFormListener(new ClearTableSelectionFormCloseListener(this));
-    }
-
-    @Override
-    protected boolean execIsAutoCreateTableRowForm() {
-      return false;
-    }
-
-    @Override
-    protected boolean getConfiguredSortEnabled() {
-      return false;
-    }
-
-    @Override
-    protected boolean getConfiguredAutoResizeColumns() {
-      return true;
-    }
-
-    @Override
-    protected boolean getConfiguredMultiSelect() {
-      return false;
-    }
-
-    public TabColumn getTabColumn() {
-      return getColumnSet().getColumnByClass(TabColumn.class);
-    }
-
-    public LabelColumn getLabelColumn() {
-      return getColumnSet().getColumnByClass(LabelColumn.class);
-    }
-
-    @Order(1)
-    public class TabColumn extends AbstractColumn<IGroupBox> {
-
-      @Override
-      protected boolean getConfiguredDisplayable() {
-        return false;
-      }
-
-    }
-
-    @Order(2)
-    public class LabelColumn extends AbstractStringColumn {
-
-    }
-  }
-
-  private class P_TabPropertyChangeListener implements PropertyChangeListener {
-
-    @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-      try {
-        if (IGroupBox.PROP_VISIBLE.equals(evt.getPropertyName())) {
-          rebuildTableRows();
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabForm.java
deleted file mode 100644
index 75b34c9..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/tabbox/TabForm.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.tabbox;
-
-import org.eclipse.scout.rt.client.mobile.Icons;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.groupbox.GroupBoxPropertyDelegator;
-import org.eclipse.scout.rt.client.ui.form.AbstractForm;
-import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractCloseButton;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-
-public class TabForm extends AbstractForm {
-  private IGroupBox m_tabGroupBox;
-
-  public TabForm(IGroupBox tabGroupBox) {
-    super(false);
-    m_tabGroupBox = tabGroupBox;
-    callInitializer();
-  }
-
-  @Order(10)
-  public class Mainbox extends AbstractGroupBox {
-
-    @Order(10)
-    public class Groupbox extends AbstractGroupBox {
-
-      @Override
-      protected void initConfig() {
-        super.initConfig();
-
-        new GroupBoxPropertyDelegator(m_tabGroupBox, this).init();
-
-        setTitle(m_tabGroupBox.getLabel());
-        setBorderDecoration(BORDER_DECORATION_EMPTY);
-      }
-
-      @Override
-      protected void injectFieldsInternal(OrderedCollection<IFormField> fields) {
-        super.injectFieldsInternal(fields);
-
-        fields.addAllOrdered(m_tabGroupBox.getFields());
-      }
-
-      /**
-       * Returns the field id of the actual tab groupBox.<br>
-       * This is necessary to make the things work properly which rely on the fieldId.<br>
-       * One example is the formData import/export: It uses the fieldId to find the matching formField and also has to
-       * consider group boxes if template fields are used (see FindFieldByFormDataIdVisitor).
-       */
-      @Override
-      public String getFieldId() {
-        return m_tabGroupBox.getFieldId();
-      }
-
-      @Override
-      public String classId() {
-        return m_tabGroupBox.classId();
-      }
-    }
-
-    @Order(10)
-    public class CloseButton extends AbstractCloseButton {
-      @Override
-      protected String getConfiguredLabel() {
-        return null;
-      }
-
-      @Override
-      protected String getConfiguredIconId() {
-        return Icons.BackAction;
-      }
-    }
-
-  }
-
-  @Override
-  public void start() {
-    startInternal(new FormHandler());
-  }
-
-  public class FormHandler extends AbstractFormHandler {
-
-    @Override
-    protected void execLoad() {
-
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/AbstractMobileTableField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/AbstractMobileTableField.java
deleted file mode 100644
index e9acfe1..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/AbstractMobileTableField.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.table;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.form.fields.tablefield.AbstractTableField;
-
-/**
- * @since 3.9.0
- */
-public abstract class AbstractMobileTableField<T extends ITable> extends AbstractTableField<T> implements IMobileTableField<T> {
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    setActionBarVisible(getConfiguredActionBarVisible());
-  }
-
-  protected boolean getConfiguredActionBarVisible() {
-    return true;
-  }
-
-  @Override
-  public boolean isActionBarVisible() {
-    return propertySupport.getPropertyBool(PROP_ACTION_BAR_VISIBLE);
-  }
-
-  @Override
-  public void setActionBarVisible(boolean visible) {
-    propertySupport.setPropertyBool(PROP_ACTION_BAR_VISIBLE, visible);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/IMobileTableField.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/IMobileTableField.java
deleted file mode 100644
index 1c62f2d..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/fields/table/IMobileTableField.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.fields.table;
-
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.form.fields.tablefield.ITableField;
-
-/**
- * @since 3.9.0
- */
-public interface IMobileTableField<T extends ITable> extends ITableField<T> {
-  String PROP_ACTION_BAR_VISIBLE = "actionBarVisible";
-
-  boolean isActionBarVisible();
-
-  void setActionBarVisible(boolean visible);
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoLeafPageWithNodes.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoLeafPageWithNodes.java
deleted file mode 100644
index 210d663..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoLeafPageWithNodes.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.TableRowForm;
-import org.eclipse.scout.rt.client.ui.basic.cell.Cell;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.AbstractPageWithNodes;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-public class AutoLeafPageWithNodes extends AbstractPageWithNodes {
-  private ITableRow m_tableRow;
-  private IPage<?> m_actualParentPage;
-
-  public AutoLeafPageWithNodes(ITableRow row, IPage<?> parentPage) {
-    if (row == null) {
-      throw new IllegalArgumentException("Row must not be null");
-    }
-
-    m_tableRow = row;
-    m_actualParentPage = parentPage;
-  }
-
-  public ITableRow getTableRow() {
-    return m_tableRow;
-  }
-
-  public IPage<?> getActualParentPage() {
-    return m_actualParentPage;
-  }
-
-  @Override
-  protected void execInitPage() {
-    Cell cell = getCellForUpdate();
-    if (cell.getText() == null) {
-      cell.setText(findAppropriateTitle());
-    }
-    if (cell.getIconId() == null) {
-      cell.setIconId(m_tableRow.getIconId());
-    }
-  }
-
-  private String findAppropriateTitle() {
-    for (IColumn<?> column : m_tableRow.getTable().getColumns()) {
-      if (column.isVisible()) {
-        return m_tableRow.getTable().getCell(m_tableRow, column).getText();
-      }
-    }
-
-    return null;
-  }
-
-  @Override
-  protected boolean getConfiguredTableVisible() {
-    return false;
-  }
-
-  @Override
-  protected boolean getConfiguredLeaf() {
-    return true;
-  }
-
-  @Override
-  protected void execPageActivated() {
-    if (getDetailForm() == null) {
-      TableRowForm form = new TableRowForm(m_tableRow);
-      setDetailForm(form);
-      form.start();
-    }
-  }
-
-  @Override
-  protected void execDisposePage() {
-    super.execDisposePage();
-    if (getDetailForm() != null) {
-      getDetailForm().doClose();
-      setDetailForm(null);
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoOutline.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoOutline.java
deleted file mode 100644
index 549135b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/AutoOutline.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-public class AutoOutline extends AbstractOutline {
-  private IPage<?> m_page;
-
-  public AutoOutline(IPage<?> page) {
-    super(false);
-    m_page = page;
-    callInitializer();
-  }
-
-  @Override
-  protected boolean getConfiguredRootNodeVisible() {
-    return false;
-  }
-
-  @Override
-  protected void execCreateChildPages(List<IPage<?>> pageList) {
-    pageList.add(m_page);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/DefaultOutlineChooserForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/DefaultOutlineChooserForm.java
deleted file mode 100644
index fff4744..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/DefaultOutlineChooserForm.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.transformation.DeviceTransformationConfig;
-import org.eclipse.scout.rt.client.mobile.transformation.DeviceTransformationUtility;
-import org.eclipse.scout.rt.client.mobile.transformation.MobileDeviceTransformation;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.AbstractMobileTable;
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.DefaultOutlineChooserForm.MainBox.OutlinesTableField;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractColumn;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.tablefield.AbstractTableField;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.shared.TEXTS;
-
-public class DefaultOutlineChooserForm extends AbstractMobileForm implements IOutlineChooserForm {
-
-  public DefaultOutlineChooserForm() {
-    super();
-  }
-
-  @Override
-  protected boolean getConfiguredAskIfNeedSave() {
-    return false;
-  }
-
-  @Override
-  protected int getConfiguredDisplayHint() {
-    return DISPLAY_HINT_VIEW;
-  }
-
-  @Override
-  protected String getConfiguredDisplayViewId() {
-    return VIEW_ID_CENTER;
-  }
-
-  @Override
-  protected String getConfiguredTitle() {
-    return TEXTS.get("MobileOutlineChooserTitle");
-  }
-
-  public void startView() {
-    startInternal(new ViewHandler());
-  }
-
-  public MainBox getMainBox() {
-    return (MainBox) getRootGroupBox();
-  }
-
-  public OutlinesTableField getOutlinesTableField() {
-    return getFieldByClass(OutlinesTableField.class);
-  }
-
-  @Override
-  protected boolean getConfiguredHeaderVisible() {
-    return true;
-  }
-
-  @Override
-  protected boolean getConfiguredFooterVisible() {
-    return true;
-  }
-
-  @Order(10)
-  public class MainBox extends AbstractGroupBox {
-
-    @Override
-    protected boolean getConfiguredBorderVisible() {
-      return false;
-    }
-
-    @Override
-    protected void execInitField() {
-      //Table already is scrollable, it's not necessary to make the form scrollable too
-      DeviceTransformationConfig config = DeviceTransformationUtility.getDeviceTransformationConfig();
-      if (config != null) {
-        config.excludeFieldTransformation(this, MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE);
-      }
-    }
-
-    @Order(10)
-    public class OutlinesTableField extends AbstractTableField<OutlinesTableField.Table> {
-
-      @Override
-      protected boolean getConfiguredLabelVisible() {
-        return false;
-      }
-
-      @Override
-      protected int getConfiguredGridH() {
-        return 2;
-      }
-
-      @Order(10)
-      public class Table extends AbstractMobileTable {
-
-        @Override
-        protected boolean execIsAutoCreateTableRowForm() {
-          return false;
-        }
-
-        @Override
-        protected boolean getConfiguredAutoDiscardOnDelete() {
-          return true;
-        }
-
-        @Override
-        protected boolean getConfiguredAutoResizeColumns() {
-          return true;
-        }
-
-        @Override
-        protected boolean getConfiguredSortEnabled() {
-          return false;
-        }
-
-        public LabelColumn getLableColumn() {
-          return getColumnSet().getColumnByClass(LabelColumn.class);
-        }
-
-        public OutlineColumn getOutlineColumn() {
-          return getColumnSet().getColumnByClass(OutlineColumn.class);
-        }
-
-        @Override
-        protected void execDecorateRow(ITableRow row) {
-          final String outlineIcon = getOutlineColumn().getValue(row).getDefaultIconId();
-          if (outlineIcon != null) {
-            row.setIconId(outlineIcon);
-          }
-        }
-
-        @Order(10)
-        public class OutlineColumn extends AbstractColumn<IOutline> {
-
-          @Override
-          protected boolean getConfiguredDisplayable() {
-            return false;
-          }
-        }
-
-        @Order(20)
-        public class LabelColumn extends AbstractStringColumn {
-
-        }
-
-        @Override
-        protected void execRowsSelected(List<? extends ITableRow> rows) {
-          if (CollectionUtility.hasElements(rows)) {
-            IOutline outline = getOutlineColumn().getValue(CollectionUtility.firstElement(rows));
-            MobileDesktopUtility.activateOutline(outline);
-            getDesktop().hideForm(DefaultOutlineChooserForm.this);
-
-            clearSelectionDelayed();
-          }
-
-        }
-      }
-    }
-  }
-
-  public class ViewHandler extends AbstractFormHandler {
-
-    @Override
-    protected void execLoad() {
-      final OutlinesTableField.Table table = getOutlinesTableField().getTable();
-
-      for (IOutline outline : getDesktop().getAvailableOutlines()) {
-        if (outline.isVisible() && outline.getRootNode() != null) {
-          ITableRow row = table.createRow(new Object[]{outline, outline.getTitle()});
-          row.setEnabled(outline.isEnabled());
-          table.addRow(row);
-        }
-      }
-    }
-
-    @Override
-    protected void execFinally() {
-      final OutlinesTableField.Table table = getOutlinesTableField().getTable();
-      table.discardAllRows();
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IMainPageForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IMainPageForm.java
deleted file mode 100644
index 521ade2..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IMainPageForm.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-public interface IMainPageForm extends IPageForm {
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IOutlineChooserForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IOutlineChooserForm.java
deleted file mode 100644
index 8075420..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IOutlineChooserForm.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-/**
- * @since 3.9.0
- */
-public interface IOutlineChooserForm extends IForm {
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IPageForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IPageForm.java
deleted file mode 100644
index 14093b8..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/IPageForm.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-
-public interface IPageForm extends IForm {
-
-  IPage<?> getPage();
-
-  PageFormConfig getPageFormConfig();
-
-  void pageSelectedNotify();
-
-  /**
-   * returns true if either the detail form or the table of the page has changed, which makes a recreation of the form
-   * necessary.
-   */
-  boolean isDirty();
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/MainPageForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/MainPageForm.java
deleted file mode 100644
index 2ff3352..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/MainPageForm.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-public class MainPageForm extends PageForm implements IMainPageForm {
-
-  public MainPageForm(IPage<?> page, PageFormManager manager, PageFormConfig config) {
-    super(page, manager, config);
-  }
-
-  @Override
-  protected void initConfig() {
-    super.initConfig();
-
-    getPageTableField().setActionBarVisible(false);
-  }
-
-  @Override
-  protected boolean getConfiguredFooterVisible() {
-    return true;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageForm.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageForm.java
deleted file mode 100644
index ed5c850..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageForm.java
+++ /dev/null
@@ -1,739 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.mobile.transformation.DeviceTransformationConfig;
-import org.eclipse.scout.rt.client.mobile.transformation.DeviceTransformationUtility;
-import org.eclipse.scout.rt.client.mobile.transformation.MobileDeviceTransformation;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.AbstractMobileTable;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.DrillDownStyleMap;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.MobileTable;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.columns.IRowSummaryColumn;
-import org.eclipse.scout.rt.client.mobile.ui.basic.table.form.TableRowForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileForm;
-import org.eclipse.scout.rt.client.mobile.ui.form.IActionFetcher;
-import org.eclipse.scout.rt.client.mobile.ui.form.fields.table.AbstractMobileTableField;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.PageForm.MainBox.PageDetailFormField;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.PageForm.MainBox.PageTableGroupBox;
-import org.eclipse.scout.rt.client.mobile.ui.form.outline.PageForm.MainBox.PageTableGroupBox.PageTableField;
-import org.eclipse.scout.rt.client.ui.basic.table.AbstractTable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
-import org.eclipse.scout.rt.client.ui.basic.table.TableAdapter;
-import org.eclipse.scout.rt.client.ui.basic.table.TableEvent;
-import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.fields.GridData;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
-import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox;
-import org.eclipse.scout.rt.client.ui.form.fields.wrappedform.AbstractWrappedFormField;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
-import org.eclipse.scout.rt.shared.ScoutTexts;
-import org.eclipse.scout.rt.shared.TEXTS;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PageForm extends AbstractMobileForm implements IPageForm {
-  private static final Logger LOG = LoggerFactory.getLogger(PageForm.class);
-  private List<IButton> m_mainboxButtons;
-  private IPage<?> m_page;
-  private P_PageTableListener m_pageTableListener;
-  private P_PageTableSelectionListener m_pageTableSelectionListener;
-  private PageFormConfig m_pageFormConfig;
-  private PageFormManager m_pageFormManager;
-  private Map<ITableRow, AutoLeafPageWithNodes> m_autoLeafPageMap;
-  private boolean m_rowSelectionRequired;
-
-  public PageForm(IPage<?> page, PageFormManager manager, PageFormConfig pageFormConfig) {
-    super(false);
-    m_pageFormManager = manager;
-    m_pageFormConfig = pageFormConfig;
-    if (m_pageFormConfig == null) {
-      m_pageFormConfig = new PageFormConfig();
-    }
-    m_autoLeafPageMap = new HashMap<ITableRow, AutoLeafPageWithNodes>();
-
-    //Init (order is important)
-    setPageInternal(page);
-    initMainButtons();
-    callInitializer();
-    initFields();
-  }
-
-  @Override
-  public void initForm() {
-    // form
-    initFormInternal();
-
-    // fields
-    PageFormInitFieldVisitor v = new PageFormInitFieldVisitor();
-    visitFields(v);
-    v.handleResult();
-
-    // custom
-    interceptInitForm();
-  }
-
-  @Override
-  public PageFormConfig getPageFormConfig() {
-    return m_pageFormConfig;
-  }
-
-  @Override
-  protected boolean getConfiguredAskIfNeedSave() {
-    return false;
-  }
-
-  @Override
-  protected int getConfiguredDisplayHint() {
-    return DISPLAY_HINT_VIEW;
-  }
-
-  @Override
-  protected String getConfiguredDisplayViewId() {
-    return VIEW_ID_CENTER;
-  }
-
-  public PageTableField getPageTableField() {
-    return getFieldByClass(PageTableField.class);
-  }
-
-  public PageDetailFormField getPageDetailFormField() {
-    return getFieldByClass(PageDetailFormField.class);
-  }
-
-  public PageTableGroupBox getPageTableGroupBox() {
-    return getFieldByClass(PageTableGroupBox.class);
-  }
-
-  @Override
-  public final IPage<?> getPage() {
-    return m_page;
-  }
-
-  private void setPageInternal(IPage<?> page) {
-    m_page = page;
-    m_page = (IPage) m_page.getTree().resolveVirtualNode(m_page);
-
-    if (m_pageFormConfig.isDetailFormVisible() && m_page.getDetailForm() == null) {
-      TableRowForm autoDetailForm = createAutoDetailForm();
-      if (autoDetailForm != null) {
-        m_page.setDetailForm(autoDetailForm);
-        autoDetailForm.start();
-      }
-    }
-
-    setTitle(page.getCellForUpdate().getText());
-  }
-
-  /**
-   * If there is a detail form the table field is visible depending on its content. If there is no detail form the table
-   * field always is visible.
-   */
-  protected void updateTableFieldVisibility() {
-    ITable table = getPageTableField().getTable();
-    boolean hasDetailForm = getPageDetailFormField().getInnerForm() != null;
-
-    if (hasDetailForm) {
-      boolean hasTableRows = table != null && table.getRowCount() > 0;
-      getPageTableField().setVisible(hasTableRows);
-    }
-
-    //If there is no table make sure the table group box is invisible and the detail form grows and takes all the space.
-    //If there is a table, the detail form must not grow because the table does
-    if (getPageTableField().isVisible() != getPageTableGroupBox().isVisible()) {
-      getPageTableGroupBox().setVisible(getPageTableField().isVisible());
-
-      GridData gridData = getPageDetailFormField().getGridDataHints();
-      if (!getPageTableField().isVisible()) {
-        gridData.weightY = 1;
-      }
-      else {
-        gridData.weightY = 0;
-      }
-      getPageDetailFormField().setGridDataHints(gridData);
-      getRootGroupBox().rebuildFieldGrid();
-    }
-  }
-
-  /**
-   * Creates a {@link TableRowForm} out of the selected table row if the parent page is a {@link IPageWithTable}.
-   */
-  private TableRowForm createAutoDetailForm() {
-    ITable table = null;
-    IPage<?> parentPage = m_page.getParentPage();
-    if (parentPage instanceof IPageWithTable) {
-      table = ((IPageWithTable) parentPage).getTable();
-    }
-    if (table != null) {
-      if (table.getSelectedRow() == null) {
-        //If the parent page has not been selected before there is no row selected -> select it to create the tableRowForm
-        ITableRow row = m_page.getParentPage().getTableRowFor(m_page);
-        if (row != null) {
-          row.getTable().selectRow(row);
-        }
-      }
-      if (table.getSelectedRow() != null) {
-        return new TableRowForm(table.getSelectedRow());
-      }
-
-    }
-
-    return null;
-  }
-
-  @Override
-  protected IActionFetcher createHeaderActionFetcher() {
-    return new PageFormHeaderActionFetcher(this);
-  }
-
-  @Override
-  protected IActionFetcher createFooterActionFetcher() {
-    return new PageFormFooterActionFetcher(this);
-  }
-
-  private void initMainButtons() {
-    List<IButton> buttonList = new LinkedList<IButton>();
-
-    //Add buttons of the detail form to the main box
-    if (m_page.getDetailForm() != null) {
-      buttonList.addAll(m_page.getDetailForm().getRootGroupBox().getCustomProcessButtons());
-    }
-
-    m_mainboxButtons = buttonList;
-  }
-
-  private void initFields() {
-    if (m_pageFormConfig.isDetailFormVisible()) {
-      getPageDetailFormField().setInnerForm(m_page.getDetailForm());
-    }
-
-    //Don't display detail form field if there is no detail form -> saves space
-    boolean hasDetailForm = getPageDetailFormField().getInnerForm() != null;
-    getPageDetailFormField().setVisible(hasDetailForm);
-    ITable pageTable = m_page.getTable();
-
-    //Make sure the preview form does only contain folder pages.
-    if (!m_pageFormConfig.isTablePageAllowed() && m_page instanceof IPageWithTable) {
-      pageTable = new PlaceholderTable(m_page);
-      pageTable.initTable();
-      pageTable.addRowByArray(new Object[]{TEXTS.get("MobilePlaceholderTableTitle")});
-      pageTable.setDefaultIconId(m_page.getCell().getIconId());
-    }
-
-    AbstractMobileTable.setAutoCreateRowForm(pageTable, false);
-    getPageTableField().setTable(pageTable, true);
-    getPageTableField().setTableStatusVisible(m_pageFormConfig.isTableStatusVisible());
-    addTableListener();
-    updateTableFieldVisibility();
-
-    if (getPageTableGroupBox().isVisible() && !hasDetailForm) {
-      //If there is a table but no detail form, don't display a border -> make the table as big as the form.
-      //If there is a table and a detail form, display a border to make it look better.
-      getPageTableGroupBox().setBorderVisible(false);
-
-      //If there is just the table, the form itself does not need to be scrollable because the table already is
-      DeviceTransformationConfig config = DeviceTransformationUtility.getDeviceTransformationConfig();
-      if (config != null) {
-        config.excludeFieldTransformation(getRootGroupBox(), MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE);
-      }
-    }
-  }
-
-  @Override
-  protected void execDisposeForm() {
-    removeTableListener();
-    for (AutoLeafPageWithNodes autoLeafPage : m_autoLeafPageMap.values()) {
-      disposeAutoLeafPage(autoLeafPage);
-    }
-  }
-
-  private void updateDrillDownStyle() {
-    ITable table = getPageTableField().getTable();
-    if (table != null) {
-      setTableRowDrillDownStyle(table, table.getRows());
-    }
-  }
-
-  private void setTableRowDrillDownStyle(ITable table, List<ITableRow> rows) {
-    if (rows == null) {
-      return;
-    }
-
-    DrillDownStyleMap drillDownMap = MobileTable.getDrillDownStyleMap(table);
-    if (drillDownMap == null) {
-      drillDownMap = new DrillDownStyleMap();
-      AbstractMobileTable.setDrillDownStyleMap(table, drillDownMap);
-    }
-
-    for (ITableRow row : rows) {
-      if (!isDrillDownRow(row)) {
-        drillDownMap.put(row, IRowSummaryColumn.DRILL_DOWN_STYLE_NONE);
-      }
-      else {
-        drillDownMap.put(row, IRowSummaryColumn.DRILL_DOWN_STYLE_ICON);
-      }
-    }
-
-  }
-
-  private boolean isDrillDownRow(ITableRow tableRow) {
-    if (!m_pageFormConfig.isKeepSelection()) {
-      return true;
-    }
-
-    return PageFormManager.isDrillDownPage(getPage().getPageFor(tableRow));
-  }
-
-  public void formAddedNotify() {
-    LOG.debug("{} added", this);
-
-    //Clear selection if form gets visible again. It must not happen earlier, since the actions typically depend on the selected row.
-    clearTableSelectionIfNecessary();
-
-    //Make sure the rows display the correct drill down style
-    updateDrillDownStyle();
-
-    if (!m_page.isSelectedNode()) {
-      selectChildPageTableRowIfNecessary();
-
-      //Make sure the page which belongs to the form is active when the form is shown
-      m_page.getOutline().getUIFacade().setNodeSelectedAndExpandedFromUI(m_page);
-    }
-
-    addTableSelectionListener();
-    processSelectedTableRow();
-  }
-
-  @Override
-  public void pageSelectedNotify() {
-    if (m_rowSelectionRequired) {
-      selectFirstChildPageTableRowIfNecessary(getPageTableField().getTable());
-      m_rowSelectionRequired = false;
-    }
-  }
-
-  private void clearTableSelectionIfNecessary() {
-    if (getPageTableField().getTable() == null) {
-      return;
-    }
-
-    ITableRow selectedRow = getPageTableField().getTable().getSelectedRow();
-    if (selectedRow != null && isDrillDownRow(selectedRow)) {
-      LOG.debug("Clearing row for table {}", getPageTableField().getTable());
-
-      getPageTableField().getTable().selectRow(null);
-    }
-  }
-
-  public void formRemovedNotify() {
-    removeTableSelectionListener();
-  }
-
-  private void addTableListener() {
-    if (m_pageTableListener != null) {
-      return;
-    }
-    m_pageTableListener = new P_PageTableListener();
-
-    ITable table = getPageTableField().getTable();
-    if (table != null) {
-      table.addTableListener(m_pageTableListener);
-    }
-  }
-
-  private void removeTableListener() {
-    if (m_pageTableListener == null) {
-      return;
-    }
-    ITable table = getPageTableField().getTable();
-    if (table != null) {
-      table.removeTableListener(m_pageTableListener);
-    }
-    m_pageTableListener = null;
-  }
-
-  private void addTableSelectionListener() {
-    if (m_pageTableSelectionListener != null) {
-      return;
-    }
-    m_pageTableSelectionListener = new P_PageTableSelectionListener();
-
-    ITable table = getPageTableField().getTable();
-    if (table != null) {
-      table.addTableListener(m_pageTableSelectionListener);
-    }
-  }
-
-  private void removeTableSelectionListener() {
-    if (m_pageTableSelectionListener == null) {
-      return;
-    }
-    ITable table = getPageTableField().getTable();
-    if (table != null) {
-      table.removeTableListener(m_pageTableSelectionListener);
-    }
-    m_pageTableSelectionListener = null;
-  }
-
-  private void processSelectedTableRow() {
-    if (!m_pageFormConfig.isKeepSelection() && !m_pageFormConfig.isAutoSelectFirstChildPage()) {
-      return;
-    }
-
-    ITable pageTable = getPage().getTable();
-    if (pageTable == null) {
-      return;
-    }
-
-    ITableRow selectedRow = pageTable.getSelectedRow();
-    if (!PageFormManager.isDrillDownPage(getPage().getPageFor(selectedRow))) {
-      if (selectedRow != null) {
-        if (m_pageFormConfig.isKeepSelection()) {
-          handleTableRowSelected(pageTable, selectedRow);
-        }
-      }
-      else {
-        if (m_pageFormConfig.isAutoSelectFirstChildPage()) {
-          selectFirstChildPageTableRowIfNecessary(pageTable);
-        }
-      }
-    }
-  }
-
-  @Override
-  public boolean isDirty() {
-    if (m_pageFormConfig.isDetailFormVisible()) {
-      if (m_page.getDetailForm() != getPageDetailFormField().getInnerForm()) {
-        return true;
-      }
-    }
-    if (m_pageFormConfig.isTablePageAllowed() && m_page instanceof IPageWithTable) {
-      ITable pageTable = ((IPageWithTable) m_page).getTable();
-      if (pageTable != getPageTableField().getTable()) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Order(10)
-  public class MainBox extends AbstractGroupBox {
-
-    @Override
-    protected boolean getConfiguredBorderVisible() {
-      return false;
-    }
-
-    @Override
-    protected int getConfiguredGridColumnCount() {
-      return 1;
-    }
-
-    @Override
-    protected void injectFieldsInternal(OrderedCollection<IFormField> fields) {
-      if (m_mainboxButtons != null) {
-        fields.addAllLast(m_mainboxButtons);
-      }
-
-      super.injectFieldsInternal(fields);
-    }
-
-    @Order(5)
-    public class PageDetailFormField extends AbstractWrappedFormField<IForm> {
-
-      @Override
-      protected int getConfiguredGridW() {
-        return 2;
-      }
-
-      @Override
-      protected int getConfiguredGridH() {
-        return 2;
-      }
-
-      @Override
-      protected double getConfiguredGridWeightY() {
-        return 0;
-      }
-
-    }
-
-    @Order(10)
-    public class PageTableGroupBox extends AbstractGroupBox {
-
-      @Order(10)
-      public class PageTableField extends AbstractMobileTableField<ITable> {
-
-        @Override
-        protected boolean getConfiguredLabelVisible() {
-          return false;
-        }
-
-        @Override
-        protected boolean getConfiguredGridUseUiHeight() {
-          //If there is a detail form make the table as height as necessary to avoid a second scrollbar.
-          //If there is no detail form make the table itself scrollable.
-          return m_pageFormConfig.isDetailFormVisible() && m_page.getDetailForm() != null;
-        }
-
-        @Override
-        protected void setTableInternal(ITable table) {
-          super.setTableInternal(table);
-          setTableStatusVisible(false);
-        }
-      }
-    }
-  }
-
-  @Override
-  public Object computeExclusiveKey() {
-    return m_page;
-  }
-
-  @Override
-  public void start() {
-    startInternalExclusive(new FormHandler());
-  }
-
-  public class FormHandler extends AbstractFormHandler {
-
-    @Override
-    protected boolean getConfiguredOpenExclusive() {
-      return true;
-    }
-
-  }
-
-  private void handleTableRowSelected(ITable table, ITableRow tableRow) {
-    LOG.debug("Table row selected: {}", tableRow);
-
-    // If children are not loaded rowPage cannot be estimated.
-    //This is the case when the rows get replaced which restores the selection before the children are loaded (e.g. executed by a search).
-    if (!m_page.isLeaf() && !m_page.isChildrenLoaded()) {
-      if (tableRow == null) {
-        //Postpone the row selection since it cannot be done if the row page cannot be estimated
-        m_rowSelectionRequired = true;
-      }
-      return;
-    }
-
-    if (tableRow == null) {
-      //Make sure there always is a selected row. if NodePageSwitch is enabled the same page and therefore the same table is on different pageForms
-      selectFirstChildPageTableRowIfNecessary(table);
-      return;
-    }
-
-    IPage<?> rowPage = null;
-    if (table instanceof PlaceholderTable) {
-      rowPage = ((PlaceholderTable) table).getActualPage();
-    }
-    else if (m_autoLeafPageMap.containsKey(tableRow)) {
-      rowPage = m_autoLeafPageMap.get(tableRow);
-    }
-    else {
-      rowPage = m_page.getPageFor(tableRow);
-    }
-    if (rowPage == null) {
-      //Create auto leaf page including an outline and activate it.
-      //Adding to a "real" outline is not possible because the page to row maps in AbstractPageWithTable resp. AbstractPageWithNodes can only be modified by the page itself.
-      AutoLeafPageWithNodes autoPage = new AutoLeafPageWithNodes(tableRow, m_page);
-      AutoOutline autoOutline = new AutoOutline(autoPage);
-      autoOutline.selectNode(autoPage);
-      m_autoLeafPageMap.put(tableRow, autoPage);
-
-      rowPage = autoPage;
-    }
-
-    m_pageFormManager.pageSelectedNotify(this, rowPage);
-  }
-
-  private void handleTableRowsDeleted(ITable table, Collection<ITableRow> tableRows) {
-    if (tableRows == null) {
-      return;
-    }
-
-    for (ITableRow tableRow : tableRows) {
-      AutoLeafPageWithNodes autoPage = m_autoLeafPageMap.remove(tableRow);
-      if (autoPage != null) {
-        disposeAutoLeafPage(autoPage);
-
-        m_pageFormManager.pageRemovedNotify(this, autoPage);
-      }
-    }
-  }
-
-  private void disposeAutoLeafPage(AutoLeafPageWithNodes page) {
-    if (page == null || page.getOutline() == null) {
-      return;
-    }
-
-    IOutline outline = page.getOutline();
-    outline.removeAllChildNodes(outline.getRootNode());
-    outline.disposeTree();
-  }
-
-  private void handleTableRowsInserted(ITable table, List<ITableRow> tableRows) {
-    setTableRowDrillDownStyle(table, tableRows);
-  }
-
-  protected void selectFirstChildPageTableRowIfNecessary(final ITable pageDetailTable) {
-    if (!m_pageFormConfig.isAutoSelectFirstChildPage() || pageDetailTable == null || pageDetailTable.getRowCount() == 0) {
-      return;
-    }
-
-    IPage<?> pageToSelect = m_page.getPageFor(pageDetailTable.getRow(0));
-    if (pageDetailTable.getSelectedRow() == null) {
-      if (!PageFormManager.isDrillDownPage(pageToSelect)) {
-        pageDetailTable.selectFirstRow();
-      }
-    }
-
-  }
-
-  /**
-   * If the currently selected page is a child page belonging to this form, make sure the table reflects that -> select
-   * the child page in the table
-   */
-  private void selectChildPageTableRowIfNecessary() {
-    if (!m_pageFormConfig.isKeepSelection()) {
-      return;
-    }
-
-    IPage<?> selectedPage = (IPage) m_page.getOutline().getSelectedNode();
-    if (selectedPage != null && selectedPage.getParentPage() == m_page) {
-      ITableRow row = m_page.getTableRowFor(selectedPage);
-      if (row != null && !isDrillDownRow(row)) {
-        row.getTable().selectRow(row);
-      }
-    }
-  }
-
-  private class PlaceholderTable extends AbstractTable {
-    private IPage<?> m_actualPage;
-
-    public PlaceholderTable(IPage<?> page) {
-      m_actualPage = page;
-    }
-
-    public IPage<?> getActualPage() {
-      return m_actualPage;
-    }
-
-    @Override
-    protected boolean getConfiguredSortEnabled() {
-      return false;
-    }
-
-    @Override
-    protected boolean getConfiguredAutoResizeColumns() {
-      return true;
-    }
-
-    @Override
-    protected boolean getConfiguredMultiSelect() {
-      return false;
-    }
-
-    @SuppressWarnings("unused")
-    public LabelColumn getLabelColumn() {
-      return getColumnSet().getColumnByClass(LabelColumn.class);
-    }
-
-    @Order(1)
-    public class LabelColumn extends AbstractStringColumn {
-
-      @Override
-      protected String getConfiguredHeaderText() {
-        return ScoutTexts.get("Folders");
-      }
-
-    }
-  }
-
-  private class P_PageTableListener extends TableAdapter {
-    @Override
-    public void tableChanged(TableEvent event) {
-      try {
-        switch (event.getType()) {
-          case TableEvent.TYPE_ALL_ROWS_DELETED:
-          case TableEvent.TYPE_ROWS_DELETED: {
-            handleTableRowDeleted(event);
-            break;
-          }
-          case TableEvent.TYPE_ROWS_INSERTED:
-            handleTableRowsInserted(event);
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-    }
-
-    private void handleTableRowDeleted(TableEvent event) {
-      PageForm.this.handleTableRowsDeleted(event.getTable(), event.getRows());
-      updateTableFieldVisibility();
-    }
-
-    private void handleTableRowsInserted(TableEvent event) {
-      PageForm.this.handleTableRowsInserted(event.getTable(), event.getRows());
-      updateTableFieldVisibility();
-    }
-
-  }
-
-  private class P_PageTableSelectionListener extends TableAdapter {
-    @Override
-    public void tableChanged(TableEvent event) {
-      try {
-        switch (event.getType()) {
-          case TableEvent.TYPE_ROWS_SELECTED: {
-            handleTableRowSelected(event);
-            break;
-          }
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-    }
-
-    private void handleTableRowSelected(TableEvent event) {
-      if (event.isConsumed()) {
-        return;
-      }
-
-      ITableRow tableRow = event.getFirstRow();
-      PageForm.this.handleTableRowSelected(event.getTable(), tableRow);
-    }
-
-  }
-
-  @Override
-  public String toString() {
-    return super.toString() + " with page " + m_page;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormConfig.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormConfig.java
deleted file mode 100644
index cd96c42..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormConfig.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-public class PageFormConfig {
-  private boolean m_tablePageAllowed;
-  private boolean m_detailFormVisible;
-  private boolean m_keepSelection;
-  private boolean m_autoSelectFirstChildPage;
-  private boolean m_tableStatusVisible;
-
-  public boolean isTablePageAllowed() {
-    return m_tablePageAllowed;
-  }
-
-  public void setTablePageAllowed(boolean tablePagesAllowed) {
-    m_tablePageAllowed = tablePagesAllowed;
-  }
-
-  public boolean isDetailFormVisible() {
-    return m_detailFormVisible;
-  }
-
-  public void setDetailFormVisible(boolean detailFormVisible) {
-    m_detailFormVisible = detailFormVisible;
-  }
-
-  public boolean isKeepSelection() {
-    return m_keepSelection;
-  }
-
-  public void setKeepSelection(boolean keepSelection) {
-    m_keepSelection = keepSelection;
-  }
-
-  public boolean isTableStatusVisible() {
-    return m_tableStatusVisible;
-  }
-
-  public void setTableStatusVisible(boolean tableStatusVisible) {
-    m_tableStatusVisible = tableStatusVisible;
-  }
-
-  public boolean isAutoSelectFirstChildPage() {
-    return m_autoSelectFirstChildPage;
-  }
-
-  /**
-   * True if the first child page should automatically be selected whenever a pageForm gets displayed and no child page
-   * has already been selected yet.
-   */
-  public void setAutoSelectFirstChildPage(boolean autoSelectFirstChildPage) {
-    m_autoSelectFirstChildPage = autoSelectFirstChildPage;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormFooterActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormFooterActionFetcher.java
deleted file mode 100644
index 0caa216..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormFooterActionFetcher.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.action.ActionButtonBarUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileAction;
-import org.eclipse.scout.rt.client.mobile.ui.form.FormFooterActionFetcher;
-import org.eclipse.scout.rt.client.mobile.ui.form.IMobileAction;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-/**
- * Additionally fetches the actions of the current page and places them on the left side.
- */
-public class PageFormFooterActionFetcher extends FormFooterActionFetcher {
-
-  public PageFormFooterActionFetcher(PageForm form) {
-    super(form);
-  }
-
-  @Override
-  public PageForm getForm() {
-    return (PageForm) super.getForm();
-  }
-
-  @Override
-  public List<IMenu> fetch() {
-    List<IMenu> footerActions = super.fetch();
-    IPage<?> page = getForm().getPage();
-
-    List<IMenu> nodeActions = ActionButtonBarUtility.fetchPageActions(page);
-    for (IMenu action : nodeActions) {
-      AbstractMobileAction.setHorizontalAlignment(action, IMobileAction.HORIZONTAL_ALIGNMENT_LEFT);
-    }
-    footerActions.addAll(0, nodeActions);
-
-    return footerActions;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormHeaderActionFetcher.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormHeaderActionFetcher.java
deleted file mode 100644
index c6dd274..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormHeaderActionFetcher.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.List;
-
-import org.eclipse.scout.rt.client.mobile.ui.action.ActionButtonBarUtility;
-import org.eclipse.scout.rt.client.mobile.ui.form.AbstractMobileAction;
-import org.eclipse.scout.rt.client.mobile.ui.form.FormHeaderActionFetcher;
-import org.eclipse.scout.rt.client.mobile.ui.form.IMobileAction;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-/**
- * Additionally fetches the actions of the current page and places them on the right side.
- */
-public class PageFormHeaderActionFetcher extends FormHeaderActionFetcher {
-
-  public PageFormHeaderActionFetcher(PageForm form) {
-    super(form);
-  }
-
-  @Override
-  public PageForm getForm() {
-    return (PageForm) super.getForm();
-  }
-
-  @Override
-  public List<IMenu> fetch() {
-    List<IMenu> headerActions = super.fetch();
-    IPage<?> page = getForm().getPage();
-
-    List<IMenu> nodeActions = ActionButtonBarUtility.fetchPageActions(page);
-    for (IMenu action : nodeActions) {
-      AbstractMobileAction.setHorizontalAlignment(action, IMobileAction.HORIZONTAL_ALIGNMENT_RIGHT);
-    }
-    headerActions.addAll(0, nodeActions);
-
-    return headerActions;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormInitFieldVisitor.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormInitFieldVisitor.java
deleted file mode 100644
index 13291e5..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormInitFieldVisitor.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.client.ui.form.IFormFieldVisitor;
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
-import org.eclipse.scout.rt.client.ui.form.fields.wrappedform.IWrappedFormField;
-
-/**
- * Compared to the default InitFormVisitor used in
- * {@link FormUtility#initFormFields(org.eclipse.scout.rt.client.ui.form.IForm)), the inner form of a wrappedFormField
- * is never initialized. This is necessary to avoid a double initialization because the inner form always is initialized
- * already.
- */
-public class PageFormInitFieldVisitor implements IFormFieldVisitor {
-  private RuntimeException m_firstEx;
-  private Set<IForm> m_formsToIgnore;
-
-  public PageFormInitFieldVisitor() {
-    m_formsToIgnore = new HashSet<IForm>();
-  }
-
-  @Override
-  public boolean visitField(IFormField field, int level, int fieldIndex) {
-    try {
-      if (allowInitField(field)) {
-        field.initField();
-      }
-    }
-    catch (RuntimeException e) {
-      if (m_firstEx == null) {
-        m_firstEx = e;
-      }
-    }
-    return true;
-  }
-
-  public void handleResult() {
-    m_formsToIgnore.clear();
-    if (m_firstEx != null) {
-      throw m_firstEx;
-    }
-  }
-
-  private boolean allowInitField(IFormField field) {
-    if (field instanceof IWrappedFormField<?>) {
-      IForm innerForm = ((IWrappedFormField<?>) field).getInnerForm();
-      if (innerForm != null) {
-        m_formsToIgnore.add(innerForm);
-      }
-      return true;
-    }
-
-    //Don't initialize the fields of the inner form of a wrapped form field
-    if (m_formsToIgnore.contains(field.getForm())) {
-      return false;
-    }
-
-    return true;
-  }
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormManager.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormManager.java
deleted file mode 100644
index 7990c48..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormManager.java
+++ /dev/null
@@ -1,518 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.mobile.ui.desktop.ActiveOutlineObserver;
-import org.eclipse.scout.rt.client.mobile.ui.desktop.MobileDesktopUtility;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.basic.tree.ITreeNode;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeAdapter;
-import org.eclipse.scout.rt.client.ui.basic.tree.TreeEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent;
-import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithNodes;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PageFormManager {
-  private static final Logger LOG = LoggerFactory.getLogger(PageFormManager.class);
-
-  private PageFormMap m_pageFormMap;
-  private ActiveOutlineObserver m_activeOutlineObserver;
-  private P_OutlineTreeListener m_outlineTreeListener;
-  private P_DesktopListener m_desktopListener;
-  private Map<IPage, String> m_selectedPageSlotMap;
-
-  private String m_leftPageSlotViewId;
-  private String m_middlePageSlotViewId;
-  private IDesktop m_desktop;
-
-  private List<IForm> m_blockedForms;
-  private boolean m_pageSelectionRunning;
-
-  public PageFormManager(String... pageSlotViewIds) {
-    this(null, pageSlotViewIds);
-  }
-
-  public PageFormManager(IDesktop desktop, String... pageSlotViewIds) {
-    if (desktop == null) {
-      desktop = ClientSessionProvider.currentSession().getDesktop();
-    }
-    m_desktop = desktop;
-    if (m_desktop == null) {
-      throw new IllegalArgumentException("No desktop found. Cannot create OutlineFormsMediator.");
-    }
-
-    initPageSlots(pageSlotViewIds);
-    m_pageFormMap = new PageFormMap();
-    m_blockedForms = new LinkedList<IForm>();
-    m_activeOutlineObserver = new ActiveOutlineObserver(desktop);
-    m_selectedPageSlotMap = new HashMap<IPage, String>();
-
-    //Since the page is activated by the outline and the outline itself also listens to tree selection events,
-    //a UI listener is attached to make sure this listener is called at the end and therefore after the page has been activated properly.
-    m_outlineTreeListener = new P_OutlineTreeListener();
-    m_activeOutlineObserver.addOutlineUITreeListener(m_outlineTreeListener);
-
-    m_desktopListener = new P_DesktopListener();
-    desktop.addDesktopListener(m_desktopListener);
-  }
-
-  private void initPageSlots(String... pageSlotViewIds) {
-    if (pageSlotViewIds == null || pageSlotViewIds.length == 0 || !StringUtility.hasText(pageSlotViewIds[0])) {
-      throw new IllegalArgumentException("At least one pageSlotViewId needs to be specified.");
-    }
-
-    m_leftPageSlotViewId = pageSlotViewIds[0];
-    if (pageSlotViewIds.length > 1) {
-      m_middlePageSlotViewId = pageSlotViewIds[1];
-    }
-  }
-
-  public String getLeftPageSlotViewId() {
-    return m_leftPageSlotViewId;
-  }
-
-  public String getMiddlePageSlotViewId() {
-    return m_middlePageSlotViewId;
-  }
-
-  public boolean hasOnlyOnePageSlot() {
-    return m_middlePageSlotViewId == null;
-  }
-
-  public boolean isPageSelectionRunning() {
-    return m_pageSelectionRunning;
-  }
-
-  protected void setPageSelectionRunning(boolean pageSelectionRunning) {
-    m_pageSelectionRunning = pageSelectionRunning;
-  }
-
-  public static boolean isDrillDownPage(IPage<?> page) {
-    return page instanceof IPageWithTable && page.getParentNode() instanceof IPageWithNodes;
-  }
-
-  private void destroy() {
-    if (m_desktopListener != null) {
-      getDesktop().removeDesktopListener(m_desktopListener);
-      m_desktopListener = null;
-    }
-
-    if (m_outlineTreeListener != null) {
-      m_activeOutlineObserver.removeOutlineUITreeListener(m_outlineTreeListener);
-      m_outlineTreeListener = null;
-    }
-
-    m_pageFormMap.clear();
-  }
-
-  private void hidePageForms() {
-    for (IPageForm pageForm : getDesktop().findForms(IPageForm.class)) {
-      getDesktop().hideForm(pageForm);
-    }
-  }
-
-  private void hidePage(IPage<?> page) {
-    if (page == null) {
-      return;
-    }
-
-    LOG.debug("Hiding page: {}", page);
-    IPageForm pageForm = m_pageFormMap.get(page);
-    if (pageForm != null) {
-      getDesktop().hideForm(pageForm);
-    }
-  }
-
-  private IPageForm showPage(IPage<?> page) {
-    IPageForm pageForm = getPageForm(page, true);
-    if (pageForm != null) {
-      return pageForm;
-    }
-    LOG.debug("Showing page: {}", page);
-
-    String displayViewId = getLeftPageSlotViewId();
-
-    if (!hasOnlyOnePageSlot()) {
-      displayViewId = computePageFormSlot(page);
-    }
-
-    return showPage(page, displayViewId);
-  }
-
-  public IPageForm getPageForm(IPage<?> page, boolean onlyShowing) {
-    return m_pageFormMap.get(page, onlyShowing);
-  }
-
-  public String computePageFormSlot(IPage<?> page) {
-    if (page == null) {
-      return null;
-    }
-
-    if (page instanceof AutoLeafPageWithNodes) {
-      return getMiddlePageSlotViewId();
-    }
-
-    if (page.getParentNode() == null) {
-      return getLeftPageSlotViewId();
-    }
-
-    //PageWithTables should be displayed on the left side
-    if (isDrillDownPage(page)) {
-      return getLeftPageSlotViewId();
-    }
-
-    //Special case for nested PageWithTables:
-    //The right side can only contain a pageWithTable if the left side also shows a pageWithTable.
-    //In that case a selection of the "Details" table row of the right side selects the right pageWithTable again.
-    //This pageWithTable should now be displayed on the left side that's why the leftPageSlotViewId is returned.
-    String currentViewId = m_selectedPageSlotMap.get(page);
-    if (getMiddlePageSlotViewId().equals(currentViewId) && page.getParentPage() instanceof IPageWithTable) {
-      return getLeftPageSlotViewId();
-    }
-
-    return getMiddlePageSlotViewId();
-  }
-
-  private IPageForm showPage(IPage<?> page, String viewId) {
-    updateLeftPageIfNecessary(page, viewId);
-
-    IPageForm pageForm = m_pageFormMap.get(viewId, page);
-    if (pageForm != null && pageForm.isDirty()) {
-      pageForm.doClose();
-      m_pageFormMap.remove(pageForm);
-      pageForm = null;
-    }
-    if (pageForm == null) {
-      if (getLeftPageSlotViewId().equals(viewId)) {
-        pageForm = createMainPageForm(page);
-      }
-      else {
-        pageForm = createPageForm(page);
-      }
-      pageForm.setShowOnStart(false);
-      pageForm.setDisplayViewId(viewId);
-      pageForm.start();
-
-      m_pageFormMap.put(pageForm);
-    }
-
-    if (!pageForm.isShowing()) {
-      getDesktop().showForm(pageForm);
-    }
-
-    return pageForm;
-  }
-
-  /**
-   * If a page gets shown on the right side it's necessary to make sure the left side displays the correct page, which
-   * is the parent page.
-   * <p>
-   * Normally, on regular drill down, the left page gets shown first and afterwards the right one. In this situation
-   * everything is fine and the method does nothing.<br>
-   * The left page may be wrong if the right page gets shown first, which may happen in case of bookmark activation or a
-   * node page switch. In such situations the left side needs to be updated with the correct page.
-   * <p>
-   * Node page switch: The node page on the right side moves to the left side when selecting a node page, happens on
-   * nested PageWithNodes
-   */
-  private void updateLeftPageIfNecessary(IPage<?> page, String viewId) {
-    if (getMiddlePageSlotViewId() == null) {
-      return;
-    }
-
-    if (getMiddlePageSlotViewId().equals(viewId) && page.getParentPage() != null && !(page instanceof AutoLeafPageWithNodes)) {
-      IPageForm parentPageForm = m_pageFormMap.get(page.getParentPage(), true);
-      if (parentPageForm == null || getMiddlePageSlotViewId().equals(parentPageForm.getDisplayViewId())) {
-
-        //Make sure there is always the correct page on the left side which is the parent page
-        showPage(page.getParentPage(), getLeftPageSlotViewId());
-      }
-    }
-  }
-
-  protected IMainPageForm createMainPageForm(IPage<?> page) {
-    PageFormConfig config = createMainPageFormConfig(page);
-    return new MainPageForm(page, this, config);
-  }
-
-  protected IPageForm createPageForm(IPage<?> page) {
-    PageFormConfig config = createPageFormConfig(page);
-    return new PageForm(page, this, config);
-  }
-
-  protected PageFormConfig createMainPageFormConfig(IPage<?> page) {
-    PageFormConfig config = new PageFormConfig();
-    config.setTablePageAllowed(true);
-    config.setTableStatusVisible(true);
-    if (hasOnlyOnePageSlot()) {
-      config.setDetailFormVisible(true);
-    }
-    else {
-      config.setKeepSelection(true);
-      config.setAutoSelectFirstChildPage(true);
-    }
-    return config;
-  }
-
-  protected PageFormConfig createPageFormConfig(IPage<?> page) {
-    PageFormConfig config = new PageFormConfig();
-    config.setDetailFormVisible(true);
-    return config;
-  }
-
-  private IDesktop getDesktop() {
-    return m_desktop;
-  }
-
-  public void pageSelectedNotify(PageForm pageForm, IPage<?> selectedPage) {
-    if (selectedPage == null) {
-      return;
-    }
-
-    //A AutoLeafPage is not attached to a real outline. Since it already has been activated just show it.
-    if (selectedPage instanceof AutoLeafPageWithNodes) {
-      showPage(selectedPage);
-    }
-    else {
-      if (selectedPage.isSelectedNode()) {
-        //Trigger selection again to move it to the left side and to make sure it's treated like a main page (see MultiPageChangeStrategy)
-        selectedPage.getOutline().selectNode(null);
-      }
-      m_selectedPageSlotMap.put(selectedPage, pageForm.getDisplayViewId());
-      try {
-        selectAndExpandPage(selectedPage);
-      }
-      finally {
-        m_selectedPageSlotMap.remove(selectedPage);
-      }
-    }
-  }
-
-  /**
-   * Mainly a copy from AbstractTree.getUIFacade.setNodeSelectedAndExpandedFromUI() without setTreeChanging(true/false)
-   * and additional outline change. TreeChanging must not be set otherwise collecting node menus does not work anymore.
-   */
-  private void selectAndExpandPage(IPage<?> page) {
-    try {
-      setPageSelectionRunning(true);
-
-      //Make sure outline is correctly set
-      IOutline outline = page.getOutline();
-      if (getDesktop().getOutline() != page.getOutline()) {
-        getDesktop().activateOutline(page.getOutline());
-      }
-
-      //Select node
-      ITreeNode node = outline.resolveVirtualNode(page);
-      if (node != null) {
-        if (node.isChildrenDirty() || node.isChildrenVolatile()) {
-          node.loadChildren();
-        }
-        outline.selectNode(node, false);
-        outline.setNodeExpanded(node, true);
-        if (!outline.isScrollToSelection()) {
-          outline.scrollToSelection();
-        }
-      }
-    }
-    finally {
-      setPageSelectionRunning(false);
-      showBlockedForms();
-    }
-  }
-
-  private void handleTreeNodeSelected(final ITreeNode deselctedNode, final ITreeNode selectedNode) {
-    LOG.debug("Tree node selected: {}", selectedNode);
-    if (selectedNode == null) {
-      hidePageForms();
-      return;
-    }
-
-    IPageForm pageForm = showPage((IPage) selectedNode);
-    pageForm.pageSelectedNotify();
-  }
-
-  private void handleTreeNodesDeleted(Collection<ITreeNode> deletedNodes) {
-    if (deletedNodes == null) {
-      return;
-    }
-
-    for (ITreeNode node : deletedNodes) {
-
-      //If a node gets deleted the child nodes typically get detached from the tree too, but no separate event will be fired.
-      //So we need to make sure the pageForms of the child pages are properly removed as well.
-      handleTreeNodesDeleted(node.getChildNodes());
-
-      if (node instanceof IPage<?> && node.getTree() == null) {
-        IPage<?> page = (IPage) node;
-        handlePageRemoved(page);
-      }
-    }
-  }
-
-  public void pageRemovedNotify(PageForm pageForm, IPage<?> page) {
-    handlePageRemoved(page);
-  }
-
-  private void handlePageRemoved(IPage<?> page) {
-    if (page == null) {
-      return;
-    }
-
-    try {
-      IPageForm pageForm = m_pageFormMap.get(page);
-      if (pageForm != null) {
-        pageForm.doClose();
-        hidePage(page);
-      }
-    }
-    finally {
-      m_pageFormMap.remove(page);
-    }
-
-    // Normally, when removing the selected page, the parent page gets selected and the corresponding page form shown.
-    // In case of the AutoLeafPageWithNodes, the parent page already is selected, so no selection event will be fired. Therefore we need to show the page form manually.
-    if (page instanceof AutoLeafPageWithNodes) {
-      IPage<?> parentPage = ((AutoLeafPageWithNodes) page).getActualParentPage();
-      if (parentPage.isSelectedNode()) {
-        showPage(parentPage);
-      }
-    }
-  }
-
-  public boolean acceptForm(IForm form) {
-    //Always block detail forms because they are displayed as inner forms on the page forms.
-    if (form == getDesktop().getPageDetailForm()) {
-      return false;
-    }
-
-    //If the page selection is running queue the opening of the form to make sure the page form is opened first.
-    if (isPageSelectionRunning()) {
-      if (!(form instanceof PageForm)) {
-        if (!m_blockedForms.contains(form)) {
-          m_blockedForms.add(form);
-        }
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  private void showBlockedForms() {
-    for (IForm form : m_blockedForms.toArray(new IForm[m_blockedForms.size()])) {
-      m_blockedForms.remove(form);
-      MobileDesktopUtility.addFormToDesktop(form);
-    }
-  }
-
-  private void handlePageFormAdded(PageForm pageForm) {
-    if (pageForm == null) {
-      return;
-    }
-
-    String displayViewId = pageForm.getDisplayViewId();
-    MobileDesktopUtility.removeFormsFromDesktop(IPageForm.class, displayViewId, pageForm);
-    if (getLeftPageSlotViewId().equals(displayViewId)) {
-      MobileDesktopUtility.removeFormsFromDesktop(IPageForm.class, getMiddlePageSlotViewId(), pageForm);
-    }
-    pageForm.formAddedNotify();
-  }
-
-  private void handlePageFormRemoved(PageForm pageForm) {
-    if (pageForm == null) {
-      return;
-    }
-
-    pageForm.formRemovedNotify();
-  }
-
-  private class P_OutlineTreeListener extends TreeAdapter {
-
-    @Override
-    public void treeChanged(TreeEvent event) {
-      try {
-        switch (event.getType()) {
-          case TreeEvent.TYPE_NODES_SELECTED: {
-            handleTreeNodeSelected(event.getDeselectedNode(), event.getNewSelectedNode());
-            break;
-          }
-          case TreeEvent.TYPE_NODES_DELETED: {
-            handleTreeNodesDeleted(event.getNodes());
-            break;
-          }
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-    }
-
-  }
-
-  private class P_DesktopListener implements DesktopListener {
-
-    @Override
-    public void desktopChanged(DesktopEvent event) {
-      try {
-        switch (event.getType()) {
-          case DesktopEvent.TYPE_FORM_SHOW: {
-            handleFormAdded(event);
-            break;
-          }
-          case DesktopEvent.TYPE_FORM_HIDE: {
-            handleFormRemoved(event);
-            break;
-          }
-          case DesktopEvent.TYPE_DESKTOP_CLOSED: {
-            destroy();
-            break;
-          }
-        }
-      }
-      catch (RuntimeException e) {
-        BEANS.get(ExceptionHandler.class).handle(e);
-      }
-    }
-
-    private void handleFormAdded(DesktopEvent event) {
-      IForm form = event.getForm();
-      if (form instanceof PageForm) {
-        handlePageFormAdded((PageForm) form);
-      }
-    }
-
-    private void handleFormRemoved(DesktopEvent event) {
-      IForm form = event.getForm();
-      if (form instanceof PageForm) {
-        handlePageFormRemoved((PageForm) form);
-      }
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormMap.java b/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormMap.java
deleted file mode 100644
index de64a92..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/ui/form/outline/PageFormMap.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.ui.form.outline;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
-
-public class PageFormMap {
-  private Map<String, List<IPageForm>> m_pageFormMaps;
-
-  public PageFormMap() {
-    m_pageFormMaps = new HashMap<String, List<IPageForm>>();
-  }
-
-  public IPageForm get(IPage<?> page) {
-    return get(page, false);
-  }
-
-  public IPageForm get(IPage<?> page, boolean onlyVisible) {
-    if (page == null) {
-      return null;
-    }
-
-    for (List<IPageForm> pageFormList : m_pageFormMaps.values()) {
-      if (pageFormList == null) {
-        continue;
-      }
-
-      for (IPageForm pageForm : pageFormList) {
-        if (page.equals(pageForm.getPage())) {
-          IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
-          if (!onlyVisible || desktop.isShowing(pageForm)) {
-            return pageForm;
-          }
-        }
-      }
-    }
-
-    return null;
-  }
-
-  public IPageForm get(String displayViewId, IPage<?> page) {
-    if (displayViewId == null || page == null) {
-      return null;
-    }
-
-    List<IPageForm> list = m_pageFormMaps.get(displayViewId);
-    if (list == null) {
-      return null;
-    }
-
-    for (IPageForm pageForm : list) {
-      if (displayViewId.equals(pageForm.getDisplayViewId()) && page.equals(pageForm.getPage())) {
-        return pageForm;
-      }
-    }
-
-    return null;
-  }
-
-  public void put(IPageForm pageForm) {
-    String displayViewId = pageForm.getDisplayViewId();
-    List<IPageForm> list = m_pageFormMaps.get(displayViewId);
-    if (list == null) {
-      list = new LinkedList<IPageForm>();
-    }
-
-    list.add(pageForm);
-    m_pageFormMaps.put(displayViewId, list);
-  }
-
-  public void remove(IPage<?> page) {
-    for (List<IPageForm> pageFormList : m_pageFormMaps.values()) {
-      if (pageFormList == null) {
-        continue;
-      }
-
-      for (IPageForm pageForm : new LinkedList<IPageForm>(pageFormList)) {
-        if (page.equals(pageForm.getPage())) {
-          pageFormList.remove(pageForm);
-        }
-      }
-    }
-  }
-
-  public void remove(IPageForm pageForm) {
-    for (List<IPageForm> pageFormList : m_pageFormMaps.values()) {
-      if (pageFormList == null) {
-        continue;
-      }
-      pageFormList.remove(pageForm);
-    }
-  }
-
-  public void clear() {
-    m_pageFormMaps.clear();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/META-INF/scout.xml b/org.eclipse.scout.rt.client.mobile/src/main/resources/META-INF/scout.xml
deleted file mode 100644
index 5892b3c..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/META-INF/scout.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-    All rights reserved. This program and the accompanying materials
-    are made available under the terms of the Eclipse Public License v1.0
-    which accompanies this distribution, and is available at
-    http://www.eclipse.org/legal/epl-v10.html
-
-    Contributors:
-        BSI Business Systems Integration AG - initial API and implementation
-
--->
-<scout>
-</scout>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellContent.html b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellContent.html
deleted file mode 100644
index 76cd999..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellContent.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<html>
-<table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0" style="table-layout:fixed;border-collapse: collapse; border-bottom:1px solid #e1efec" >
-  <colgroup>
-    <col width="#ICON_COL_WIDTH#/">
-    <col />
-    <col width="#DRILL_DOWN_COL_WIDTH#/"/>
-  </colgroup>
-  <tbody>
-  <tr>
-    <td align="center">#ICON#</td>
-    <td style="text-overflow:ellipsis;overflow:hidden;white-space:nowrap;">#CONTENT#</td>
-    <td>#DRILL_DOWN#</td>
-  </tr>
-  </tbody>
-</table>
-</html>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellMoreElements.html b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellMoreElements.html
deleted file mode 100644
index 4dabc57..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableCellMoreElements.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0" style="table-layout:fixed;border-collapse: collapse; border-bottom:1px solid #e1efec">
-  <colgroup>
-    <col />
-  </colgroup>
-  <tbody>
-  <tr>
-    <td align="center" style="text-overflow:ellipsis;overflow:hidden;white-space:nowrap;">#CONTENT#</td>
-  </tr>
-  </tbody>
-</table>
-</html>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDown.html b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDown.html
deleted file mode 100644
index 8fcc6b4..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDown.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<span
-  style="
-    display:block;
-    background-image:url('cid:mobile_drill_down');
-    background-repeat:no-repeat;
-    background-position:center;
-    width:100%;height:50px;">
-</span>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDownButton.html b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDownButton.html
deleted file mode 100644
index 25ffcbf..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/html/MobileTableDrillDownButton.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<a
-  href="http://local/scout?action=drill_down"
-  style="
-    display:block;
-    background-image:url('cid:mobile_drill_down_button');
-    background-repeat:no-repeat;
-    background-position:center;
-    width:100%;height:50px;"
-  onclick="currentElement=event.target || event.srcElement;currentElement.style.backgroundImage='url(cid:mobile_drill_down_button_pressed)';return false;">
-</a>
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts.properties b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts.properties
deleted file mode 100644
index 12d546b..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-#     BSI Business Systems Integration AG - initial API and implementation
-#
-
-MobileBusyBlockingAbort=Abort
-MobileBusyBlockingMessage=Processing request...
-MobileOutlineChooserTitle=Outlines
-MobilePagingShowNext=Show next elements
-MobilePagingShowPrevious=Show previous elements
-MobilePlaceholderTableTitle=Details
-MobileSmartFormTitle=Choose {0}
-MobileSmartFormTitleDefault=Choose object
-MobileTableDefaultHeader=Objects
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_de.properties b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_de.properties
deleted file mode 100644
index 47cbcae..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_de.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-#     BSI Business Systems Integration AG - initial API and implementation
-#
-
-MobileBusyBlockingAbort=Abbrechen
-MobileBusyBlockingMessage=Verarbeitung l\u00E4uft...
-MobileOutlineChooserTitle=Sichten
-MobilePagingShowNext=Weitere Elemente anzeigen
-MobilePagingShowPrevious=Vorherige Elemente anzeigen
-MobilePlaceholderTableTitle=Details
-MobileSmartFormTitle={0} w\u00E4hlen
-MobileSmartFormTitleDefault=Objekt w\u00E4hlen
-MobileTableDefaultHeader=Objekte
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_ru.properties b/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_ru.properties
deleted file mode 100644
index f66cdc5..0000000
--- a/org.eclipse.scout.rt.client.mobile/src/main/resources/org/eclipse/scout/rt/client/mobile/texts/Texts_ru.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (c) 2010-2015 BSI Business Systems Integration AG.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-#     BSI Business Systems Integration AG - initial API and implementation
-#
-
-MobileBusyBlockingAbort=\u041F\u0440\u0435\u0440\u0432\u0430\u0442\u044C
-MobileBusyBlockingMessage=\u041E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 ...
-MobileOutlineChooserTitle=\u041A\u043E\u043D\u0442\u0443\u0440\u044B
-MobilePagingShowNext=\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B
-MobilePagingShowPrevious=\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B
-MobilePlaceholderTableTitle=\u0414\u0435\u0442\u0430\u043B\u044C\u043D\u043E
-MobileSmartFormTitle=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 {0}
-MobileSmartFormTitleDefault=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0431\u044A\u0435\u043A\u0442
-MobileTableDefaultHeader=\u041E\u0431\u044A\u0435\u043A\u0442\u044B
diff --git a/org.eclipse.scout.rt.client.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.client.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.client.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.client.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.client.test/pom.xml b/org.eclipse.scout.rt.client.test/pom.xml
index dabb11c..814afde 100644
--- a/org.eclipse.scout.rt.client.test/pom.xml
+++ b/org.eclipse.scout.rt.client.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
@@ -39,7 +39,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.commons</groupId>
-      <artifactId>commons-math</artifactId>
+      <artifactId>commons-math3</artifactId>
     </dependency>
 
     <dependency>
diff --git a/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/rt/client/testenvironment/TestEnvironmentClientSession.java b/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/rt/client/testenvironment/TestEnvironmentClientSession.java
index 0eef218..d1e54ea 100644
--- a/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/rt/client/testenvironment/TestEnvironmentClientSession.java
+++ b/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/rt/client/testenvironment/TestEnvironmentClientSession.java
@@ -41,7 +41,7 @@
 
   @Override
   protected void execLoadSession() {
-    //do not enable client notifications, do not add service tunnel
+    // do not enable client notifications, do not add service tunnel
     final TestEnvironmentDesktop d = new TestEnvironmentDesktop();
     setDesktop(d);
     simulateDesktopOpened(d);
@@ -83,7 +83,7 @@
    * Simulates that the desktop has been opened.
    */
   protected void simulateDesktopOpened(IDesktop desktop) {
-    desktop.getUIFacade().fireGuiAttached();
-    desktop.getUIFacade().fireDesktopOpenedFromUI();
+    desktop.getUIFacade().openFromUI();
+    desktop.getUIFacade().fireGuiAttached(null);
   }
 }
diff --git a/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/testing/client/BlockingTestUtility.java b/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/testing/client/BlockingTestUtility.java
index 2dca998..941149f 100644
--- a/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/testing/client/BlockingTestUtility.java
+++ b/org.eclipse.scout.rt.client.test/src/main/java/org/eclipse/scout/testing/client/BlockingTestUtility.java
@@ -4,6 +4,8 @@
  */
 package org.eclipse.scout.testing.client;
 
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 import org.eclipse.scout.rt.client.IClientSession;
@@ -14,9 +16,11 @@
 import org.eclipse.scout.rt.platform.context.RunContext;
 import org.eclipse.scout.rt.platform.exception.DefaultRuntimeExceptionTranslator;
 import org.eclipse.scout.rt.platform.exception.PlatformException;
+import org.eclipse.scout.rt.platform.filter.IFilter;
 import org.eclipse.scout.rt.platform.job.IBlockingCondition;
 import org.eclipse.scout.rt.platform.job.IFuture;
 import org.eclipse.scout.rt.platform.job.IJobManager;
+import org.eclipse.scout.rt.platform.job.JobInput;
 import org.eclipse.scout.rt.platform.job.JobState;
 import org.eclipse.scout.rt.platform.job.Jobs;
 import org.eclipse.scout.rt.platform.job.listener.IJobListener;
@@ -43,6 +47,15 @@
   /**
    * Helper method to test code which will enter a blocking condition.
    * <p>
+   * calls {@link #runBlockingAction(IRunnable, IRunnable, boolean)} with awaitBackgroundJobs=false
+   */
+  public static void runBlockingAction(final IRunnable runnableGettingBlocked, final IRunnable runnableOnceBlocked) {
+    runBlockingAction(runnableGettingBlocked, runnableOnceBlocked, false);
+  }
+
+  /**
+   * Helper method to test code which will enter a blocking condition.
+   * <p>
    * If <code>runnableOnceBlocked</code> throws an exception, it is given to {@link JUnitExceptionHandler} to make the
    * JUnit test fail.
    *
@@ -50,21 +63,34 @@
    *          {@code IRunnable} that will enter a blocking condition.
    * @param runnableOnceBlocked
    *          {@code IRunnable} to be executed once the 'runnableGettingBlocked' enters a blocking condition.
+   * @param awaitBackgroundJobs
+   *          true waits for background jobs running in the same session to complete before runnableOnceBlocked is
+   *          called
    */
-  public static void runBlockingAction(final IRunnable runnableGettingBlocked, final IRunnable runnableOnceBlocked) {
+  public static void runBlockingAction(final IRunnable runnableGettingBlocked, final IRunnable runnableOnceBlocked, final boolean awaitBackgroundJobs) {
     final ClientRunContext runContext = ClientRunContexts.copyCurrent();
     final IBlockingCondition onceBlockedDoneCondition = Jobs.newBlockingCondition(true);
 
+    //remember the list of client jobs before blocking
+    final Set<IFuture<?>> jobsBefore = new HashSet<>();
+    jobsBefore.addAll(BEANS.get(IJobManager.class).getFutures(new IFilter<IFuture<?>>() {
+      @Override
+      public boolean accept(IFuture<?> cand) {
+        final RunContext candContext = cand.getJobInput().getRunContext();
+        return candContext instanceof ClientRunContext && ((ClientRunContext) candContext).getSession() == runContext.getSession();
+      }
+    }));
+
     final IRegistrationHandle listenerRegistration = IFuture.CURRENT.get().addListener(Jobs.newEventFilterBuilder()
         .andMatchEventType(JobEventType.JOB_STATE_CHANGED)
         .andMatchState(JobState.WAITING_FOR_BLOCKING_CONDITION)
         .andMatchExecutionHint(ModelJobs.EXECUTION_HINT_UI_INTERACTION_REQUIRED)
         .toFilter(), new IJobListener() {
-
           @Override
           public void changed(final JobEvent event) {
-            ModelJobs.schedule(new IRunnable() {
+            //waitFor was entered
 
+            final IRunnable callRunnableOnceBlocked = new IRunnable() {
               @Override
               public void run() throws Exception {
                 try {
@@ -75,10 +101,38 @@
                   onceBlockedDoneCondition.setBlocking(false);
                 }
               }
-            }, ModelJobs.newInput(runContext)
+            };
+            final JobInput jobInputForRunnableOnceBlocked = ModelJobs.newInput(runContext)
                 .withExceptionHandling(BEANS.get(JUnitExceptionHandler.class), true)
-                .withName("JUnit: Handling blocked thread because waiting for a blocking condition"));
-          }
+                .withName("JUnit: Handling blocked thread because waiting for a blocking condition");
+
+            if (awaitBackgroundJobs) {
+              //wait until all background jobs finished
+              Jobs.schedule(new IRunnable() {
+                @Override
+                public void run() throws Exception {
+                  jobsBefore.add(IFuture.CURRENT.get());
+                  BEANS.get(IJobManager.class).awaitFinished(new IFilter<IFuture<?>>() {
+                    @Override
+                    public boolean accept(IFuture<?> f) {
+                      RunContext candContext = f.getJobInput().getRunContext();
+                      return candContext instanceof ClientRunContext && ((ClientRunContext) candContext).getSession() == runContext.getSession() && !jobsBefore.contains(f);
+                    }
+                  }, 5, TimeUnit.MINUTES);
+
+                  //call runnableOnceBlocked
+                  ModelJobs.schedule(callRunnableOnceBlocked, jobInputForRunnableOnceBlocked);
+
+                }
+              }, Jobs.newInput().withName("wait until background jobs finished"));
+
+            }
+            else {
+              //call runnableOnceBlocked directly
+              ModelJobs.schedule(callRunnableOnceBlocked, jobInputForRunnableOnceBlocked);
+            }
+
+          }//end JobListener.changed
         });
     try {
       runnableGettingBlocked.run(); // this action will enter a blocking condition which causes the 'runnableOnceBlocked' to be executed.
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ClientSessionTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ClientSessionTest.java
index d6060fd..177fb59 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ClientSessionTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ClientSessionTest.java
@@ -20,7 +20,7 @@
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.BeanMetaData;
 import org.eclipse.scout.rt.platform.IBean;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.eclipse.scout.rt.testing.shared.TestingUtility;
 import org.junit.Test;
 
@@ -41,7 +41,7 @@
     try {
       bean = TestingUtility.registerBean(new BeanMetaData(TestEnvironmentClientSession.class));
 
-      IClientSession session = BEANS.get(ClientSessionProvider.class).provide(ClientRunContexts.empty().withUserAgent(UserAgent.createDefault()));
+      IClientSession session = BEANS.get(ClientSessionProvider.class).provide(ClientRunContexts.empty().withUserAgent(UserAgents.createDefault()));
       WeakReference<IClientSession> ref = new WeakReference<IClientSession>(session);
 
       session.stop();
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/cache/ClientCacheTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/cache/ClientCacheTest.java
index 041e045..dab486a 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/cache/ClientCacheTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/cache/ClientCacheTest.java
@@ -31,8 +31,8 @@
 
   @Test
   public void testCacheNotificationHandlerRegistration() {
-    TypeParameterBeanRegistry<INotificationHandler> registry = new TypeParameterBeanRegistry<>();
-    registry.registerBeans(INotificationHandler.class, BEANS.all(INotificationHandler.class));
+    TypeParameterBeanRegistry<INotificationHandler> registry = new TypeParameterBeanRegistry<>(INotificationHandler.class);
+    registry.registerBeans(BEANS.all(INotificationHandler.class));
     List<INotificationHandler> handlers = registry.getBeans(InvalidateCacheNotification.class);
 
     // ensure that in client exactly one cache notification handler is registered and
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/context/ClientRunContextTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/context/ClientRunContextTest.java
index 1114e62..af61590 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/context/ClientRunContextTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/context/ClientRunContextTest.java
@@ -28,9 +28,8 @@
 import org.eclipse.scout.rt.platform.nls.NlsLocale;
 import org.eclipse.scout.rt.shared.ISession;
 import org.eclipse.scout.rt.shared.ScoutTexts;
-import org.eclipse.scout.rt.shared.ui.UiDeviceType;
-import org.eclipse.scout.rt.shared.ui.UiLayer;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.eclipse.scout.rt.testing.platform.runner.PlatformTestRunner;
 import org.junit.After;
 import org.junit.Before;
@@ -68,7 +67,7 @@
     runContext.getPropertyMap().put("A", "B");
     runContext.withSubject(new Subject());
     runContext.withSession(mock(IClientSession.class), true);
-    runContext.withUserAgent(UserAgent.create(UiLayer.UNKNOWN, UiDeviceType.UNKNOWN, "n/a"));
+    runContext.withUserAgent(UserAgents.create().build());
     runContext.withLocale(Locale.CANADA_FRENCH);
 
     ClientRunContext copy = runContext.copy();
@@ -205,8 +204,8 @@
   @Test
   public void testCurrentUserAgent() {
     IClientSession session = mock(IClientSession.class);
-    UserAgent userAgent1 = newUserAgent();
-    UserAgent userAgent2 = newUserAgent();
+    UserAgent userAgent1 = UserAgents.create().build();
+    UserAgent userAgent2 = UserAgents.create().build();
 
     // ThreadLocal set, Session set with UserAgent
     ISession.CURRENT.set(session);
@@ -224,8 +223,8 @@
   @Test
   public void testCurrentUserAgentAndSetNullUserAgent() {
     IClientSession session = mock(IClientSession.class);
-    UserAgent userAgent1 = newUserAgent();
-    UserAgent userAgent2 = newUserAgent();
+    UserAgent userAgent1 = UserAgents.create().build();
+    UserAgent userAgent2 = UserAgents.create().build();
 
     // ThreadLocal set, Session set with UserAgent
     ISession.CURRENT.set(session);
@@ -257,9 +256,9 @@
   @Test
   public void testCurrentUserAgentAndSetNotNullUserAgent() {
     IClientSession session = mock(IClientSession.class);
-    UserAgent userAgent1 = newUserAgent();
-    UserAgent userAgent2 = newUserAgent();
-    UserAgent userAgent3 = newUserAgent();
+    UserAgent userAgent1 = UserAgents.create().build();
+    UserAgent userAgent2 = UserAgents.create().build();
+    UserAgent userAgent3 = UserAgents.create().build();
 
     // ThreadLocal set, Session set with UserAgent
     ISession.CURRENT.set(session);
@@ -294,8 +293,4 @@
     }
     return set;
   }
-
-  private static UserAgent newUserAgent() {
-    return UserAgent.create(UiLayer.UNKNOWN, UiDeviceType.UNKNOWN, "n/a");
-  }
 }
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/DeepLinksTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/DeepLinksTest.java
new file mode 100644
index 0000000..3972d55
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/DeepLinksTest.java
@@ -0,0 +1,60 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
+public class DeepLinksTest {
+
+  IDeepLinks m_deepLinks = BEANS.get(IDeepLinks.class);
+
+  @BeforeClass
+  public static void setUpBeforeClass() {
+    BEANS.getBeanManager().registerClass(FooBarDeepLinkHandler.class);
+  }
+
+  @AfterClass
+  public static void tearDownAfterClass() {
+    BEANS.getBeanManager().unregisterClass(FooBarDeepLinkHandler.class);
+  }
+
+  @Test
+  public void testCanHandleDeepLink() {
+    assertFalse(m_deepLinks.canHandleDeepLink("ticket-1234567"));
+    assertTrue(m_deepLinks.canHandleDeepLink("foobar-123"));
+  }
+
+  @Test
+  public void testHandleDeepLink() throws DeepLinkException {
+    m_deepLinks.handleDeepLink("foobar-123");
+    FooBarDeepLinkHandler handler = BEANS.get(FooBarDeepLinkHandler.class);
+    assertEquals("123", handler.getLastMatch());
+  }
+
+  @Test(expected = DeepLinkException.class)
+  public void testHandleDeepLink_Exception() throws Exception {
+    m_deepLinks.handleDeepLink("foobar-321");
+  }
+
+  /**
+   * The outline deep link handler should be registered by the Scout framework by default.
+   */
+  @Test
+  public void testOutlineDeepLinkHandler() throws Exception {
+    assertTrue(m_deepLinks.canHandleDeepLink("outline-123"));
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/FooBarDeepLinkHandler.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/FooBarDeepLinkHandler.java
new file mode 100644
index 0000000..2ca20f5
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/FooBarDeepLinkHandler.java
@@ -0,0 +1,32 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.util.regex.Matcher;
+
+public class FooBarDeepLinkHandler extends AbstractDeepLinkHandler {
+
+  public static final String HANDLER_NAME = "foobar";
+
+  private String m_lastMatch;
+
+  protected FooBarDeepLinkHandler() {
+    super(defaultPattern(HANDLER_NAME, "[0-9]+"));
+  }
+
+  @Override
+  public String getName() {
+    return HANDLER_NAME;
+  }
+
+  @Override
+  protected void handleImpl(Matcher matcher) throws DeepLinkException {
+    m_lastMatch = matcher.group(1);
+    if ("321".equals(m_lastMatch)) {
+      throw new DeepLinkException();
+    }
+  }
+
+  public String getLastMatch() {
+    return m_lastMatch;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandlerTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandlerTest.java
new file mode 100644
index 0000000..3bf0f93
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandlerTest.java
@@ -0,0 +1,87 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.eclipse.scout.rt.client.session.ClientSessionProvider;
+import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
+import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
+public class OutlineDeepLinkHandlerTest {
+
+  // used to generate a fletcher16 checksum from the class-name
+  private static class P_OutlineFoo extends AbstractOutline {
+
+    @Override
+    public String getTitle() {
+      return "Foo";
+    }
+  }
+
+  private static class P_OutlineBar extends AbstractOutline {
+
+    @Override
+    public String getTitle() {
+      return "Bar";
+    }
+  }
+
+  @Test
+  public void testCreateBrowserHistory() {
+    OutlineDeepLinkHandler handler = new OutlineDeepLinkHandler();
+    IOutline outline = new P_OutlineFoo();
+    BrowserHistoryEntry entry = handler.createBrowserHistoryEntry(outline);
+    assertEquals("outline-04446", entry.getDeepLinkPath());
+    // title of outline is added to title of desktop (this string is used for the title in the browser-window)
+    assertEquals("Test Environment Application - Foo", entry.getTitle());
+    // title of outline is used to create the (i)nfo URL parameter
+    assertEquals("./?dl=outline-04446&i=foo", entry.getPath());
+  }
+
+  /**
+   * Checks if the OutlineHandler activates the correct outline for a given deep-link path.
+   */
+  @Test
+  public void testHandleImpl() throws Exception {
+    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
+    IOutline outlineFoo = new P_OutlineFoo();
+    IOutline outlineBar = new P_OutlineBar();
+
+    addOutlineToDesktop(desktop, outlineFoo);
+    addOutlineToDesktop(desktop, outlineBar);
+    desktop.activateOutline(outlineBar);
+    assertSame(outlineBar, desktop.getOutline());
+
+    OutlineDeepLinkHandler handler = new OutlineDeepLinkHandler();
+    handler.handle("outline-04446");
+    assertSame(outlineFoo, desktop.getOutline());
+  }
+
+  /**
+   * Adds an outline to the desktop by reflection.
+   */
+  private void addOutlineToDesktop(IDesktop desktop, IOutline outline) throws ReflectiveOperationException {
+    AbstractDesktop ad = (AbstractDesktop) desktop;
+    Field field = AbstractDesktop.class.getDeclaredField("m_availableOutlines");
+    field.setAccessible(true);
+    @SuppressWarnings("unchecked")
+    List<IOutline> outlines = (List<IOutline>) field.get(ad);
+    outlines.add(outline);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopExtensionTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopExtensionTest.java
index 7fcc8c0..01a4013 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopExtensionTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopExtensionTest.java
@@ -14,12 +14,20 @@
 
 import org.eclipse.scout.extension.AbstractLocalExtensionTestCase;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopInitChain;
+import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.shared.extension.IExtensionRegistry;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
 public class DesktopExtensionTest extends AbstractLocalExtensionTestCase {
 
   @Test
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/services/common/code/CodeServiceClientProxyTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/services/common/code/CodeServiceClientProxyTest.java
index dd506c9..5a29212 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/services/common/code/CodeServiceClientProxyTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/services/common/code/CodeServiceClientProxyTest.java
@@ -70,9 +70,10 @@
    * Test method for
    * {@link org.eclipse.scout.rt.client.services.common.code.CodeServiceClientProxy#getAllCodeTypes(java.lang.String)}.
    */
+  @SuppressWarnings("deprecation")
   @Test
   public void testGetAllCodeTypes() throws Exception {
-    List<ICodeType<?, ?>> codeTypes = m_service.getAllCodeTypes("");
+    List<ICodeType<?, ?>> codeTypes = m_service.getAllCodeTypes();
     assertEquals("size", 2, codeTypes.size());
     ICodeType<?, ?> codeType = codeTypes.get(0);
     ICodeType<?, ?> companyRatingCodeType;
@@ -88,7 +89,7 @@
     assertEquals("CompanyRatingCodeType class", CompanyRatingCodeType.class, companyRatingCodeType.getClass());
     assertEquals("CompanyTypeCodeType class", CompanyTypeCodeType.class, companyTypeCodeType.getClass());
 
-    codeTypes = m_service.getAllCodeTypes("");
+    codeTypes = m_service.getAllCodeTypes();
     assertEquals("size", 2, codeTypes.size());
 
     codeTypes = m_service.getAllCodeTypes(CLIENT_CODE_TYPE_PREFIX);
@@ -102,7 +103,7 @@
   @Test
   public void testFindCodeTypeById() throws Exception {
     //Preload the code, as a client application would do in ClientSession#execLoadSession():
-    List<ICodeType<?, ?>> codeTypes = m_service.getAllCodeTypes("");
+    List<ICodeType<?, ?>> codeTypes = m_service.getAllCodeTypes();
     assertEquals("size", 2, codeTypes.size());
 
     ICodeType<Long, ?> companyTypeCodeType = m_service.findCodeTypeById(CompanyTypeCodeType.ID);
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/NestedMenusTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/NestedMenusTest.java
index 7288872..c8d1e4c 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/NestedMenusTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/NestedMenusTest.java
@@ -20,14 +20,18 @@
 import org.eclipse.scout.rt.client.ui.form.ScoutInfoForm;
 import org.eclipse.scout.rt.platform.Order;
 import org.eclipse.scout.rt.shared.TEXTS;
-import org.eclipse.scout.rt.testing.platform.runner.PlatformTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 /**
  * Accessing a nested menu yields null because child menus are not traversed.
  */
-@RunWith(PlatformTestRunner.class)
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
 public class NestedMenusTest {
 
   @Test
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/TableMenuTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/TableMenuTest.java
index 44a581e..37f95bd 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/TableMenuTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/action/menu/TableMenuTest.java
@@ -93,7 +93,7 @@
    * Tests the visibility for a multi selection menu
    */
   @Test
-  public void setMultiSeleciton() {
+  public void setMultiSelection() {
     Table t = new Table();
     t.addRowsByMatrix(TEST_ROWS);
     ITableContextMenu contextMenu = t.getContextMenu();
@@ -110,7 +110,7 @@
    * Tests the visibility for a empty space menu
    */
   @Test
-  public void testEmptySeleciton() {
+  public void testEmptySelection() {
     Table t = new Table();
     t.addRowsByMatrix(TEST_ROWS);
     ITableContextMenu contextMenu = t.getContextMenu();
@@ -123,6 +123,72 @@
   }
 
   /**
+   * Tests empty space menu disabled if table disabled, empty selection
+   */
+  @Test
+  public void testTableDisabledEmptySelection() {
+    Table t = new Table();
+    t.setEnabled(false);
+    t.addRowsByMatrix(TEST_ROWS);
+    ITableContextMenu contextMenu = t.getContextMenu();
+
+    t.selectRows(CollectionUtility.<ITableRow> emptyArrayList(), false);
+    IActionFilter filter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), true);
+    List<IMenu> visibleMenus = ActionUtility.normalizedActions(contextMenu.getChildActions(), filter);
+    assertEquals(false, visibleMenus.get(0).isEnabled());
+  }
+
+  /**
+   * Tests menu disabled if table disabled, single selection
+   */
+  @Test
+  public void testTableDisabledSingleSelection() {
+    Table t = new Table();
+    t.setEnabled(false);
+    t.addRowsByMatrix(TEST_ROWS);
+    ITableContextMenu contextMenu = t.getContextMenu();
+
+    t.selectRows(CollectionUtility.arrayList(t.getRow(0)), false);
+    IActionFilter filter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), true);
+    List<IMenu> visibleMenus = ActionUtility.normalizedActions(contextMenu.getChildActions(), filter);
+    assertEquals(false, visibleMenus.get(0).isEnabled());
+  }
+
+  /**
+   * Tests menu empty space menu enabled if row disabled, empty selection
+   */
+  @Test
+  public void testRowDisabledEmptySelection() {
+    Table t = new Table();
+    t.addRowsByMatrix(TEST_ROWS);
+    ITableContextMenu contextMenu = t.getContextMenu();
+
+    t.getRow(0).setEnabled(false);
+
+    t.selectRows(CollectionUtility.<ITableRow> emptyArrayList(), false);
+    IActionFilter filter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), true);
+    List<IMenu> visibleMenus = ActionUtility.normalizedActions(contextMenu.getChildActions(), filter);
+    assertEquals(true, visibleMenus.get(0).isEnabled());
+  }
+
+  /**
+   * Tests menu disabled if row disabled, single selection
+   */
+  @Test
+  public void testRowDisabledSingleSelection() {
+    Table t = new Table();
+    t.addRowsByMatrix(TEST_ROWS);
+    ITableContextMenu contextMenu = t.getContextMenu();
+
+    t.getRow(0).setEnabled(false);
+
+    t.selectRows(CollectionUtility.arrayList(t.getRow(0)), false);
+    IActionFilter filter = ActionUtility.createMenuFilterMenuTypes(contextMenu.getCurrentMenuTypes(), true);
+    List<IMenu> visibleMenus = ActionUtility.normalizedActions(contextMenu.getChildActions(), filter);
+    assertEquals(false, visibleMenus.get(0).isEnabled());
+  }
+
+  /**
    * Tests that {@link AbstractMenu#execOwnerValueChanged} is only called only multi-selection menus, if multiple rows
    * are selected.
    */
@@ -228,6 +294,10 @@
         return CollectionUtility.hashSet(TableMenuType.SingleSelection);
       }
 
+      @Override
+      protected void execOwnerValueChanged(Object newOwnerValue) {
+        setEnabled(true);
+      }
     }
 
     @Order(111)
@@ -240,6 +310,7 @@
 
       @Override
       protected void execOwnerValueChanged(Object newOwnerValue) {
+        setEnabled(true);
         setVisible(CompareUtility.equals(getPrenameColumn().getSelectedValue(), "Hugo"));
       }
     }
@@ -252,6 +323,10 @@
         return CollectionUtility.hashSet(TableMenuType.MultiSelection);
       }
 
+      @Override
+      protected void execOwnerValueChanged(Object newOwnerValue) {
+        setEnabled(true);
+      }
     }
 
     @Order(120)
@@ -261,6 +336,11 @@
       protected Set<? extends IMenuType> getConfiguredMenuTypes() {
         return CollectionUtility.hashSet(TableMenuType.EmptySpace);
       }
+
+      @Override
+      protected void execOwnerValueChanged(Object newOwnerValue) {
+        setEnabled(true);
+      }
     }
   }
 
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/ReplaceTableTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/ReplaceTableTest.java
index dd87660..54e247c 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/ReplaceTableTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/ReplaceTableTest.java
@@ -13,8 +13,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
-import org.eclipse.scout.rt.client.IClientSession;
-import org.eclipse.scout.rt.client.session.ClientSessionProvider;
 import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
 import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
 import org.eclipse.scout.rt.client.ui.basic.table.ReplaceTableTest.BaseForm.MainBox.FirstGroupBox;
@@ -32,14 +30,9 @@
 import org.eclipse.scout.rt.client.ui.form.fields.tablefield.AbstractTableField;
 import org.eclipse.scout.rt.platform.Order;
 import org.eclipse.scout.rt.platform.Replace;
-import org.eclipse.scout.rt.shared.ui.UiDeviceType;
-import org.eclipse.scout.rt.shared.ui.UiLayer;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
 import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
 import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
 import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -51,25 +44,6 @@
 @RunWithClientSession(TestEnvironmentClientSession.class)
 public class ReplaceTableTest {
 
-  private static UserAgent m_originalUserAgent;
-
-  private static final UserAgent WEB_USER_AGENT = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP);
-
-  @BeforeClass
-  public static void setUpBeforeClass() {
-    // Since AbstractTable adds a different number of menus for web and rich client,
-    // we set a web user agent here, since this will be the default user agent.
-    // see: AbstractTable#addHeaderMenus()
-    IClientSession cs = ClientSessionProvider.currentSession();
-    m_originalUserAgent = cs.getUserAgent();
-    cs.setUserAgent(WEB_USER_AGENT);
-  }
-
-  @AfterClass
-  public static void tearDownAfterClass() throws Exception {
-    ClientSessionProvider.currentSession().setUserAgent(m_originalUserAgent);
-  }
-
   @Test
   public void testColumnId() {
     assertEquals("Base", new BaseColumn().getColumnId());
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableLoadingPerfTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableLoadingPerfTest.java
index 5217bf9..042ace8 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableLoadingPerfTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableLoadingPerfTest.java
@@ -15,7 +15,7 @@
 import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
 import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn;
 import org.eclipse.scout.rt.platform.Order;
 import org.junit.Test;
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableTest.java
index 142f31f..bf5aa2c 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/TableTest.java
@@ -368,10 +368,33 @@
     assertEquals("rows size", 5, rows.size());
     int i = 0;
     assertRowEquals(10, "Lorem", 1, table, rows, i++);
-    assertRowEquals(30, "Ipsum", 1, table, rows, i++);
-    assertRowEquals(25, "Lorem", 1, table, rows, i++);
     assertRowEquals(20, "Ipsum", 1, table, rows, i++);
+    assertRowEquals(25, "Lorem", 1, table, rows, i++);
+    assertRowEquals(30, "Ipsum", 1, table, rows, i++);
     assertRowEquals(1, "A Total", 2, table, rows, i++);
+
+    // remove third column from sorting
+    table.getColumnSet().getColumnByClass(P_Table.ThirdColumn.class).setInitialAlwaysIncludeSortAtBegin(false);
+    table.getColumnSet().getColumnByClass(P_Table.ThirdColumn.class).setInitialSortIndex(-1);
+
+    // add second column to sorting
+    table.getColumnSet().getColumnByClass(P_Table.SecondColumn.class).setInitialSortIndex(0);
+
+    // sortAscending of a column with sortActive = false shouldn't have any effect
+    table.getColumnSet().getColumnByClass(P_Table.FirstColumn.class).setInitialSortAscending(false);
+
+    table.getColumnSet().resetSortingAndGrouping();
+    table.sort();
+
+    // check the sort order of the rows:
+    rows = table.getRows();
+    assertEquals("rows size", 5, rows.size());
+    i = 0;
+    assertRowEquals(1, "A Total", 2, table, rows, i++);
+    assertRowEquals(20, "Ipsum", 1, table, rows, i++);
+    assertRowEquals(30, "Ipsum", 1, table, rows, i++);
+    assertRowEquals(10, "Lorem", 1, table, rows, i++);
+    assertRowEquals(25, "Lorem", 1, table, rows, i++);
   }
 
   @Test
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractDateColumnTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractDateColumnTest.java
index 168bdd8..08cd599 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractDateColumnTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractDateColumnTest.java
@@ -67,7 +67,8 @@
 
   private void setParseErrorInUI(ITableRow row, AbstractDateColumn column) {
     AbstractDateField field = (AbstractDateField) column.prepareEdit(row);
-    field.getUIFacade().setParseErrorFromUI("invalid", "invalid", null);
+    field.getUIFacade().setDisplayTextFromUI("invalid");
+    field.getUIFacade().setParseErrorFromUI();
     column.completeEdit(row, field);
   }
 
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopTest.java
index 6bdae95..445db5d 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopTest.java
@@ -16,12 +16,20 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
 import org.eclipse.scout.rt.client.ui.basic.tree.ITreeNode;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
 public class AbstractDesktopTest {
 
   private IOutline m_outline;
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/AbstractFormTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/AbstractFormTest.java
index 37ade89..fecd8ef 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/AbstractFormTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/AbstractFormTest.java
@@ -138,13 +138,13 @@
     String expectedErrorMessage = HTML.fragment(
         HTML.bold(ScoutTexts.get("FormEmptyMandatoryFieldsMessage")),
         HTML.ul(HTML.li(form.getStringField().getFullyQualifiedLabel(": "))),
-        HTML.br()).toEncodedHtml();
+        HTML.br()).toHtml();
 
     try {
       form.validateForm();
     }
     catch (VetoException ve) {
-      htmlErrorMessage = ve.getHtmlMessage().toEncodedHtml();
+      htmlErrorMessage = ve.getHtmlMessage().toHtml();
     }
 
     assertEquals(expectedErrorMessage, htmlErrorMessage);
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTest.java
new file mode 100644
index 0000000..baf46a8
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTest.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.ui.form.fields.integerfield;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.scout.rt.client.dto.FormData;
+import org.eclipse.scout.rt.client.dto.FormData.DefaultSubtypeSdkCommand;
+import org.eclipse.scout.rt.client.dto.FormData.SdkCommand;
+import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
+import org.eclipse.scout.rt.client.ui.form.fields.browserfield.AbstractBrowserField;
+import org.eclipse.scout.rt.platform.resource.BinaryResource;
+import org.eclipse.scout.rt.platform.util.CollectionUtility;
+import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
+import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
+import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(ClientTestRunner.class)
+@RunWithSubject("default")
+@RunWithClientSession(TestEnvironmentClientSession.class)
+@FormData(value = AbstractBrowserFieldTestData.class, defaultSubtypeSdkCommand = DefaultSubtypeSdkCommand.CREATE, sdkCommand = SdkCommand.CREATE)
+public class AbstractBrowserFieldTest extends AbstractBrowserField {
+
+  @Test
+  public void testImportFormData() {
+    // location only
+    AbstractBrowserFieldTestData formData = new AbstractBrowserFieldTestData();
+    formData.setLocation("http://www.example.org");
+    importFormFieldData(formData, false);
+
+    Assert.assertEquals("http://www.example.org", getLocation());
+    Assert.assertNull(getBinaryResource());
+    Assert.assertTrue(CollectionUtility.isEmpty(getAttachments()));
+
+    final BinaryResource resource = new BinaryResource("document.txt", "Welcome".getBytes(StandardCharsets.UTF_8));
+
+    // resource only
+    formData = new AbstractBrowserFieldTestData();
+    formData.setBinaryResource(resource);
+    importFormFieldData(formData, false);
+
+    Assert.assertNull(getLocation());
+    Assert.assertEquals(resource, getBinaryResource());
+    Assert.assertTrue(CollectionUtility.isEmpty(getAttachments()));
+
+    final Set<BinaryResource> attachments = new HashSet<>();
+    attachments.add(new BinaryResource("attachment.txt", "Content".getBytes(StandardCharsets.UTF_8)));
+    attachments.add(new BinaryResource("image.png", new byte[]{12, 43, 12, 71, 73, 12, 51}));
+
+    // resource and attachment
+    formData = new AbstractBrowserFieldTestData();
+    formData.setBinaryResource(resource);
+    formData.setAttachments(attachments);
+    importFormFieldData(formData, false);
+
+    Assert.assertNull(getLocation());
+    Assert.assertEquals(resource, getBinaryResource());
+    Assert.assertEquals(attachments, getAttachments());
+
+    // set all three (not a valid case, but import form data will import was is provided)
+    formData = new AbstractBrowserFieldTestData();
+    formData.setLocation("http://www.example.org");
+    formData.setBinaryResource(resource);
+    formData.setAttachments(attachments);
+    importFormFieldData(formData, false);
+
+    Assert.assertEquals("http://www.example.org", getLocation());
+    Assert.assertEquals(resource, getBinaryResource());
+    Assert.assertEquals(attachments, getAttachments());
+  }
+}
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTestData.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTestData.java
new file mode 100644
index 0000000..43bdd31
--- /dev/null
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/integerfield/AbstractBrowserFieldTestData.java
@@ -0,0 +1,15 @@
+package org.eclipse.scout.rt.client.ui.form.fields.integerfield;
+
+import javax.annotation.Generated;
+
+import org.eclipse.scout.rt.shared.data.form.fields.browserfield.AbstractBrowserFieldData;
+
+/**
+ * <b>NOTE:</b><br>
+ * This class is auto generated by the Scout SDK. No manual modifications recommended.
+ */
+@Generated(value = "org.eclipse.scout.rt.client.ui.form.fields.integerfield.AbstractBrowserFieldTest", comments = "This class is auto generated by the Scout SDK. No manual modifications recommended.")
+public class AbstractBrowserFieldTestData extends AbstractBrowserFieldData {
+
+  private static final long serialVersionUID = 1L;
+}
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/SequenceBoxTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/SequenceBoxTest.java
index 63c5bd9..e28ea0a 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/SequenceBoxTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/SequenceBoxTest.java
@@ -134,12 +134,12 @@
 
     f.resetSearchFilter();
     String searchFilterText = f.getSearchFilter().getDisplayTextsPlain();
-    assertEquals("baseLabel from = " + DateUtility.formatTime(cal.getTime()), searchFilterText);
+    assertEquals("baseLabel from = \n" + DateUtility.formatTime(cal.getTime()), searchFilterText);
 
     f.getStartField().setLabel(null);
     f.resetSearchFilter();
     searchFilterText = f.getSearchFilter().getDisplayTextsPlain();
-    assertEquals("baseLabel = " + DateUtility.formatTime(cal.getTime()), searchFilterText);
+    assertEquals("baseLabel = \n" + DateUtility.formatTime(cal.getTime()), searchFilterText);
   }
 
   @Test
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/SmartFieldParseValueTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/SmartFieldParseValueTest.java
index 310c83d..a26ee10 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/SmartFieldParseValueTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/SmartFieldParseValueTest.java
@@ -64,6 +64,7 @@
   public void setUp() {
     m_smartField = new SmartField();
     m_smartField.registerProposalChooserInternal();
+    LookupRows.ROW_1.withEnabled(true);
   }
 
   /**
@@ -180,6 +181,20 @@
     assertNull(m_smartField.getErrorStatus());
   }
 
+  /**
+   * Test case for #172835. When one of the lookup rows is disabled and the user types accepts exactly that row by
+   * display text, the row cannot be accepted.
+   */
+  @Test
+  public void testHandleAcceptByDisplayText_InactiveLookupRow() throws Exception {
+    String displayText = "aName";
+    LookupRows.ROW_1.withEnabled(false);
+    boolean openProposalChooser = m_smartField.handleAcceptByDisplayText(displayText);
+    assertTrue(openProposalChooser);
+    assertNull(m_smartField.getCurrentLookupRow());
+    assertNotNull(m_smartField.getErrorStatus());
+  }
+
   int getProposalTableRowCount() {
     return ((ITable) m_smartField.getProposalChooser().getModel()).getRowCount();
   }
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxTest.java
index 2945a2d..46e4ea6d 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxTest.java
@@ -251,7 +251,7 @@
     MessageBox messageBox = argument.getValue();
     assertEquals("Intro text", expectedIntro, messageBox.getHeader());
     assertEquals("Action text", expectedAction, messageBox.getBody());
-    assertEquals("Html", expectedHtml, messageBox.getHtml() == null ? null : messageBox.getHtml().toEncodedHtml());
+    assertEquals("Html", expectedHtml, messageBox.getHtml() == null ? null : messageBox.getHtml().toHtml());
     assertEquals("Yes button text", TEXTS.get("YesButton"), messageBox.getYesButtonText());
     assertEquals("No button text", TEXTS.get("NoButton"), messageBox.getNoButtonText());
     assertEquals("Cancel button text", null, messageBox.getCancelButtonText());
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/shared/extension/dto/PageDataExtensionTest.java b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/shared/extension/dto/PageDataExtensionTest.java
index 08ae4bd..9f5e248 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/shared/extension/dto/PageDataExtensionTest.java
+++ b/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/shared/extension/dto/PageDataExtensionTest.java
@@ -24,7 +24,7 @@
 import org.eclipse.scout.rt.shared.extension.dto.fixture.OrigPageWithTableData.OrigPageWithTableRowData;
 import org.eclipse.scout.rt.shared.extension.dto.fixture.ThirdIntegerColumn;
 import org.eclipse.scout.rt.shared.extension.dto.fixture.ThirdIntegerColumnData;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -38,7 +38,7 @@
     final IClientSession session = Mockito.mock(IClientSession.class);
     System.setProperty("user.area", "@user.home/test");
     Mockito.when(session.getUserId()).thenReturn("userid");
-    Mockito.when(session.getUserAgent()).thenReturn(UserAgent.createDefault());
+    Mockito.when(session.getUserAgent()).thenReturn(UserAgents.createDefault());
     ISession.CURRENT.set(session);
   }
 
diff --git a/org.eclipse.scout.rt.client/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.client/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.client/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.client/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.client/pom.xml b/org.eclipse.scout.rt.client/pom.xml
index d295e58..207ffae 100644
--- a/org.eclipse.scout.rt.client/pom.xml
+++ b/org.eclipse.scout.rt.client/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/AbstractClientSession.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/AbstractClientSession.java
index 3f831c2..3c27e4e 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/AbstractClientSession.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/AbstractClientSession.java
@@ -21,7 +21,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
@@ -73,6 +72,7 @@
 import org.eclipse.scout.rt.shared.session.SessionData;
 import org.eclipse.scout.rt.shared.session.SessionEvent;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -98,8 +98,6 @@
 
   /* locked by m_sharedVarLock*/
   private final SharedVariableMap m_sharedVariableMap;
-  private final CountDownLatch m_sharedVarsInitialized = new CountDownLatch(1);
-  private final Object m_sharedVarLock = new Object();
 
   private IMemoryPolicy m_memoryPolicy;
   private final SessionData m_sessionData;
@@ -116,10 +114,7 @@
     m_subject = Subject.getSubject(AccessController.getContext());
     m_objectExtensions = new ObjectExtensions<AbstractClientSession, IClientSessionExtension<? extends AbstractClientSession>>(this);
     m_scoutTexts = new ScoutTexts();
-
-    synchronized (m_sharedVarLock) {
-      m_sharedVariableMap = new SharedVariableMap();
-    }
+    m_sharedVariableMap = new SharedVariableMap();
 
     setLocale(NlsLocale.get());
 
@@ -195,7 +190,7 @@
   @Override
   public UserAgent getUserAgent() {
     if (m_userAgent == null) {
-      m_userAgent = UserAgent.createDefault();
+      m_userAgent = UserAgents.createDefault();
       LOG.warn("UserAgent not set; using default [default={}]", m_userAgent);
     }
     return m_userAgent;
@@ -226,9 +221,7 @@
 
   @Override
   public Map<String, Object> getSharedVariableMap() {
-    synchronized (m_sharedVarLock) {
-      return CollectionUtility.copyMap(m_sharedVariableMap);
-    }
+    return CollectionUtility.copyMap(m_sharedVariableMap);
   }
 
   /**
@@ -240,10 +233,7 @@
    * </p>
    */
   protected <T> T getSharedContextVariable(String name, Class<T> type) {
-    Object o;
-    synchronized (m_sharedVarLock) {
-      o = m_sharedVariableMap.get(name);
-    }
+    Object o = m_sharedVariableMap.get(name);
     return TypeCastUtility.castValue(o, type);
   }
 
@@ -306,48 +296,22 @@
    */
   @Override
   public void replaceSharedVariableMapInternal(SharedVariableMap newMap) {
-    synchronized (m_sharedVarLock) {
-      m_sharedVariableMap.updateInternal(newMap);
-    }
-    m_sharedVarsInitialized.countDown();
+    m_sharedVariableMap.updateInternal(newMap);
+  }
+
+  protected void initializeSharedVariables(long timeout, TimeUnit unit) {
+    initializeSharedVariables();
   }
 
   /**
    * Pings the server to get the initial shared variables. Blocks until the initial version of the shared variables is
    * available or the timeout is reached.
    *
-   * @param timeout
-   *          the maximum time to wait
-   * @param unit
-   *          the time unit of the {@code timeout} argument
    * @throws ProcessingException
    *           if interrupted (and the variables are not initialized)
    */
-  protected void initializeSharedVariables(long timeout, TimeUnit unit) {
+  protected void initializeSharedVariables() {
     BEANS.get(IPingService.class).ping("");
-    awaitSharedVariablesInitialized(timeout, unit);
-  }
-
-  /**
-   * Wait until the shared variables are initialized by a notification from the server
-   *
-   * @throws ProcessingException
-   *           if interrupted (and the variables are not initialized)
-   */
-  protected void awaitSharedVariablesInitialized(long timeout, TimeUnit unit) {
-    try {
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Awaiting shared variable map");
-      }
-      m_sharedVarsInitialized.await(timeout, unit);
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Shared variables updated");
-      }
-    }
-    catch (java.lang.InterruptedException e) {
-      Thread.currentThread().interrupt(); // Restore the interrupted status because cleared by catching InterruptedException.
-      throw new ThreadInterruptedException("Interrupted while waiting for shared variables to be initialized");
-    }
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationDispatcher.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationDispatcher.java
index ecdc704..3df158c 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationDispatcher.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationDispatcher.java
@@ -202,7 +202,7 @@
   private class P_NotificationFutureCallback implements IDoneHandler<Void> {
     private IFuture<Void> m_future;
 
-    public P_NotificationFutureCallback(IFuture<Void> furture) {
+    P_NotificationFutureCallback(IFuture<Void> furture) {
       m_future = furture;
     }
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationPoller.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationPoller.java
index fd27fa5..dea77d4 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationPoller.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/clientnotification/ClientNotificationPoller.java
@@ -15,7 +15,6 @@
 
 import javax.annotation.PostConstruct;
 
-import org.eclipse.scout.rt.client.IClientNode;
 import org.eclipse.scout.rt.client.context.ClientRunContexts;
 import org.eclipse.scout.rt.platform.ApplicationScoped;
 import org.eclipse.scout.rt.platform.BEANS;
@@ -28,11 +27,12 @@
 import org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledException;
 import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
 import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedException;
+import org.eclipse.scout.rt.shared.INode;
 import org.eclipse.scout.rt.shared.SharedConfigProperties.NotificationSubjectProperty;
 import org.eclipse.scout.rt.shared.clientnotification.ClientNotificationMessage;
 import org.eclipse.scout.rt.shared.clientnotification.IClientNotificationService;
 import org.eclipse.scout.rt.shared.servicetunnel.IServiceTunnel;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,7 +50,7 @@
       m_pollerFuture = Jobs.schedule(new P_NotificationPoller(), Jobs.newInput()
           .withRunContext(ClientRunContexts.copyCurrent()
               .withSubject(BEANS.get(NotificationSubjectProperty.class).getValue())
-              .withUserAgent(UserAgent.createDefault())
+              .withUserAgent(UserAgents.createDefault())
               .withSession(null, false))
           .withName(ClientNotificationPoller.class.getSimpleName()));
     }
@@ -81,7 +81,7 @@
     public void run() {
       while (!RunMonitor.CURRENT.get().isCancelled()) {
         try {
-          handleMessagesReceived(BEANS.get(IClientNotificationService.class).getNotifications(IClientNode.ID));
+          handleMessagesReceived(BEANS.get(IClientNotificationService.class).getNotifications(INode.ID));
         }
         catch (ThreadInterruptedException | FutureCancelledException e) {
           LOG.debug("Client notification polling has been interrupted.", e);
@@ -93,4 +93,5 @@
       }
     }
   }
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/AbstractDeepLinkHandler.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/AbstractDeepLinkHandler.java
new file mode 100644
index 0000000..c67ee98
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/AbstractDeepLinkHandler.java
@@ -0,0 +1,60 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all classes that provide deep-link logic.
+ */
+public abstract class AbstractDeepLinkHandler implements IDeepLinkHandler {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractDeepLinkHandler.class);
+
+  private final Pattern m_pattern;
+
+  protected AbstractDeepLinkHandler(Pattern pattern) {
+    m_pattern = pattern;
+  }
+
+  /**
+   * Creates a regexp pattern to validate/parse the value of the deep-link URL parameter.
+   */
+  protected static Pattern defaultPattern(String handlerName, String dataGroup) {
+    return Pattern.compile("^" + handlerName + "-(" + dataGroup + ")$");
+  }
+
+  /**
+   * This method creates a deep-link path to be used in the URL parameter. The returned value has the format:
+   * <code>[handler name]-[handler data]</code>. Example <code>outline-12345</code>.
+   *
+   * @param handlerData
+   * @return
+   */
+  protected String toDeepLinkPath(String handlerData) {
+    return getName() + "-" + handlerData;
+  }
+
+  @Override
+  public boolean matches(String path) {
+    return m_pattern.matcher(path).matches();
+  }
+
+  @Override
+  public boolean handle(String path) throws DeepLinkException {
+    Matcher matcher = m_pattern.matcher(path);
+    if (matcher.matches()) {
+      LOG.debug("Handling deep-link name={} path={}", getName(), path);
+      handleImpl(matcher);
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+
+  protected abstract void handleImpl(Matcher matcher) throws DeepLinkException;
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkException.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkException.java
new file mode 100644
index 0000000..c111a78
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkException.java
@@ -0,0 +1,40 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import org.eclipse.scout.rt.platform.exception.VetoException;
+
+/**
+ * A checked exception which indicates that a deep-link URL could not be processed for some (business logic) reason.
+ * There are two cases:
+ * <ol>
+ * <li>The regex pattern is valid and matches, but no data has been found for the requested deep-link path</li>
+ * <li>A resource has been found but the current user has no permissions to read the resource. In that case this
+ * exception contains the original VetoException as cause</li>
+ * </ol>
+ */
+public class DeepLinkException extends Exception {
+
+  private static final long serialVersionUID = 1L;
+
+  public DeepLinkException() {
+  }
+
+  /**
+   * Use this constructor if resource requested by deep-link was not found.
+   *
+   * @param message
+   */
+  public DeepLinkException(String message) {
+    super(message);
+  }
+
+  /**
+   * Use this constructor if user has insufficient permissions to display the requested deep-link.
+   *
+   * @param cause
+   *          the original VetoException thrown when permission is denied
+   */
+  public DeepLinkException(VetoException cause) {
+    super(cause);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkUriBuilder.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkUriBuilder.java
new file mode 100644
index 0000000..b32b0bc
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinkUriBuilder.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+ * http://www.bsiag.com/
+ */
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.eclipse.scout.rt.client.IClientSession;
+import org.eclipse.scout.rt.client.session.ClientSessionProvider;
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.eclipse.scout.rt.platform.util.UriBuilder;
+import org.eclipse.scout.rt.shared.deeplink.DeepLinkUrlParameter;
+import org.eclipse.scout.rt.shared.deeplink.DeepLinkUtility;
+
+public class DeepLinkUriBuilder {
+
+  private final UriBuilder m_builder;
+
+  private String m_info;
+
+  private String m_path;
+
+  private DeepLinkUriBuilder(UriBuilder builder) {
+    m_builder = builder;
+  }
+
+  public static DeepLinkUriBuilder createAbsolute() {
+    IClientSession clientSession = ClientSessionProvider.currentSession();
+    return new DeepLinkUriBuilder(new UriBuilder(clientSession.getBrowserURI()));
+  }
+
+  public static DeepLinkUriBuilder createRelative() {
+    return new DeepLinkUriBuilder(new UriBuilder("./"));
+  }
+
+  public DeepLinkUriBuilder parameterPath(String path) {
+    m_path = path;
+    m_builder.parameter(DeepLinkUrlParameter.DEEP_LINK, path);
+    return this;
+  }
+
+  /**
+   * Sets the 'info' field used to create a BrowserHistoryEntry. Use this method if you want to set the info but don't
+   * want to add an info-parameter to the URL.
+   */
+  public DeepLinkUriBuilder info(String info) {
+    m_info = info;
+    return this;
+  }
+
+  public DeepLinkUriBuilder parameterInfo(String info) {
+    if (StringUtility.hasText(info)) {
+      m_info = info;
+      m_builder.parameter(DeepLinkUrlParameter.INFO, DeepLinkUtility.toSlug(info));
+    }
+    return this;
+  }
+
+  public DeepLinkUriBuilder parameter(String name, String value) {
+    m_builder.parameter(name, value);
+    return this;
+  }
+
+  public BrowserHistoryEntry createBrowserHistoryEntry() {
+    if (m_path == null) {
+      throw new IllegalStateException("Cannot create BrowserHistoryEntry without deep-link path");
+    }
+    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
+    StringBuilder title = new StringBuilder(desktop.getTitle());
+    if (StringUtility.hasText(m_info)) {
+      title.append(" - ").append(m_info);
+    }
+    return new BrowserHistoryEntry(m_builder.createURI(), title.toString(), m_path);
+  }
+
+  public URL createURL() {
+    return m_builder.createURL();
+  }
+
+  public URI createURI() {
+    return m_builder.createURI();
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinks.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinks.java
new file mode 100644
index 0000000..9f2c270
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/DeepLinks.java
@@ -0,0 +1,55 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides access to registered deep-link handlers.
+ * 
+ * @see IDeepLinkHandler
+ */
+public class DeepLinks implements IDeepLinks {
+  private static final Logger LOG = LoggerFactory.getLogger(DeepLinks.class);
+
+  private List<IDeepLinkHandler> m_handlers;
+
+  public DeepLinks() {
+    m_handlers = new ArrayList<>(BEANS.all(IDeepLinkHandler.class));
+    if (LOG.isInfoEnabled()) {
+      StringBuilder sb = new StringBuilder();
+      for (IDeepLinkHandler handler : m_handlers) {
+        sb.append("\n- ").append(handler);
+      }
+      LOG.info("Registered {} deep-link handlers:{}", m_handlers.size(), sb.toString());
+    }
+  }
+
+  @Override
+  public boolean canHandleDeepLink(String deepLinkPath) {
+    if (StringUtility.isNullOrEmpty(deepLinkPath)) {
+      return false;
+    }
+    for (IDeepLinkHandler handler : m_handlers) {
+      if (handler.matches(deepLinkPath)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public boolean handleDeepLink(String deepLinkPath) throws DeepLinkException {
+    for (IDeepLinkHandler handler : m_handlers) {
+      if (handler.handle(deepLinkPath)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinkHandler.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinkHandler.java
new file mode 100644
index 0000000..41f2f7e
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinkHandler.java
@@ -0,0 +1,36 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.util.regex.Matcher;
+
+import org.eclipse.scout.rt.client.IClientSession;
+import org.eclipse.scout.rt.platform.ApplicationScoped;
+
+/**
+ * Interface for all classes that provide deep-link logic.
+ */
+@ApplicationScoped
+public interface IDeepLinkHandler {
+
+  String NUMERIC_REGEX = "\\d+";
+
+  /**
+   * @return True if this handler can handle the given path, false otherwise
+   */
+  boolean matches(String path);
+
+  /**
+   * Executes the deep-link action on the model.
+   *
+   * @throws DeepLinkException
+   *           when something went wrong while executing the {@link #handleImpl(Matcher, IClientSession)} method. For
+   *           instance the user has no permissions to view the requested resource or the resource is not available
+   * @return True if this handler has handled the given path, false otherwise
+   */
+  boolean handle(String path) throws DeepLinkException;
+
+  /**
+   * @return the name of this handler as used in the deep-link URL.
+   */
+  String getName();
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinks.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinks.java
new file mode 100644
index 0000000..667c902
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/IDeepLinks.java
@@ -0,0 +1,31 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import org.eclipse.scout.rt.platform.ApplicationScoped;
+
+/**
+ * @since 6.0
+ */
+@ApplicationScoped
+public interface IDeepLinks {
+
+  /**
+   * @return True if the given path is a valid deep-link path. Only syntax is checked at this point.
+   * @param deepLinkPath
+   *          The deep-link path in the format <code>[handler name]-[handler data]</code>.
+   */
+  boolean canHandleDeepLink(String deepLinkPath);
+
+  /**
+   * Handles the deep-link by delegating to a handler that can process the given path.
+   *
+   * @param deepLinkPath
+   *          The deep-link path in the format <code>[handler name]-[handler data]</code>.
+   * @return whether or not a handler has handled the request
+   * @throws IllegalArgumentException
+   *           when path is not a valid deep-link (check with canHandleDeepLink() before you call this method)
+   * @throws DeepLinkException
+   *           when the deep-link couldn't be processed for some reasons (e.g. missing permissions)
+   */
+  boolean handleDeepLink(String deepLinkPath) throws DeepLinkException;
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandler.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandler.java
new file mode 100644
index 0000000..3e39dfa
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/deeplink/OutlineDeepLinkHandler.java
@@ -0,0 +1,79 @@
+package org.eclipse.scout.rt.client.deeplink;
+
+import java.util.regex.Matcher;
+
+import org.eclipse.scout.rt.client.session.ClientSessionProvider;
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.platform.util.StringUtility;
+
+/**
+ * Deep-link handler for outlines.
+ * <ul>
+ * <li>Format: <code>outline-[outlineId]</code>, Outline ID is checksum generated from the absolute class name</li>
+ * <li>Example: <code>outline-1234567</code></li>
+ * </ul>
+ */
+@Order(1000)
+public class OutlineDeepLinkHandler extends AbstractDeepLinkHandler {
+
+  private static final String HANDLER_NAME = "outline";
+
+  public OutlineDeepLinkHandler() {
+    super(defaultPattern(HANDLER_NAME, "\\d+"));
+  }
+
+  @Override
+  public void handleImpl(Matcher matcher) throws DeepLinkException {
+    String outlineId = matcher.group(1);
+    IOutline selectedOutline = null;
+    IDesktop desktop = ClientSessionProvider.currentSession().getDesktop();
+    for (IOutline outline : desktop.getAvailableOutlines()) {
+      String tmpOutlineId = outlineId(outline);
+      if (tmpOutlineId.equals(outlineId)) {
+        selectedOutline = outline;
+        break;
+      }
+    }
+    if (selectedOutline == null) {
+      throw new DeepLinkException("No outline with ID " + outlineId + " found");
+    }
+    if (!selectedOutline.isVisible() || !selectedOutline.isEnabled()) {
+      throw new DeepLinkException("Outline ID " + outlineId + " is not enabled or visible");
+    }
+    desktop.activateOutline(selectedOutline);
+  }
+
+  public BrowserHistoryEntry createBrowserHistoryEntry(IOutline outline) {
+    return DeepLinkUriBuilder.createRelative()
+        .parameterInfo(outline.getTitle())
+        .parameterPath(toDeepLinkPath(outlineId(outline)))
+        .createBrowserHistoryEntry();
+  }
+
+  private static String outlineId(IOutline outline) {
+    int nameChecksum = fletcher16(outline);
+    nameChecksum = Math.abs(nameChecksum);
+    return StringUtility.lpad(String.valueOf(nameChecksum), "0", 5);
+  }
+
+  private static short fletcher16(IOutline outline) {
+    short sum1 = 0;
+    short sum2 = 0;
+    short modulus = 255;
+    String data = outline.getClass().getName();
+    for (int i = 0; i < data.length(); i++) {
+      sum1 = (short) ((sum1 + data.charAt(i)) % modulus);
+      sum2 = (short) ((sum2 + sum1) % modulus);
+    }
+    return (short) ((sum2 << 8) | sum1);
+  }
+
+  @Override
+  public String getName() {
+    return HANDLER_NAME;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/ColumnData.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/ColumnData.java
index c200b56..8f4c9c2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/ColumnData.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/ColumnData.java
@@ -38,15 +38,15 @@
  * </table>
  * <h3>Examples</h3>
  * <h4>Ignore a table column</h4> <blockquote>
- * 
+ *
  * <pre>
  * &#ColumnData(SdkColumnCommand.IGNORE)
  * public class DisplayColumn extends AbstractStringColumn { ... }
  * </pre>
- * 
+ *
  * </blockquote> The NameField will not be considered in the form data. The NameField is an inner type in a
  * form.</blockquote>
- * 
+ *
  * @since 3.10.0-M5
  */
 @Retention(RetentionPolicy.RUNTIME)
@@ -55,7 +55,7 @@
 
   SdkColumnCommand value();
 
-  public static enum SdkColumnCommand {
+  enum SdkColumnCommand {
     CREATE, IGNORE
   }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/FormData.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/FormData.java
index 4f32d75..b982a70 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/FormData.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/dto/FormData.java
@@ -154,11 +154,11 @@
 
   Class[] interfaces() default {};
 
-  public static enum SdkCommand {
+  enum SdkCommand {
     CREATE, USE, IGNORE, DEFAULT
   }
 
-  public static enum DefaultSubtypeSdkCommand {
+  enum DefaultSubtypeSdkCommand {
     CREATE, IGNORE, DEFAULT
   }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/action/tool/AbstractToolButtonExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/action/tool/AbstractToolButtonExtension.java
index a4a7c4f..ad99c14 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/action/tool/AbstractToolButtonExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/action/tool/AbstractToolButtonExtension.java
@@ -10,10 +10,10 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.extension.ui.action.tool;
 
-import org.eclipse.scout.rt.client.extension.ui.action.AbstractActionExtension;
+import org.eclipse.scout.rt.client.extension.ui.action.menu.AbstractMenuExtension;
 import org.eclipse.scout.rt.client.ui.action.tool.AbstractToolButton;
 
-public abstract class AbstractToolButtonExtension<OWNER extends AbstractToolButton> extends AbstractActionExtension<OWNER> implements IToolButtonExtension<OWNER> {
+public abstract class AbstractToolButtonExtension<OWNER extends AbstractToolButton> extends AbstractMenuExtension<OWNER> implements IToolButtonExtension<OWNER> {
 
   public AbstractToolButtonExtension(OWNER owner) {
     super(owner);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/AbstractTableControlExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/AbstractFormTableControlExtension.java
similarity index 76%
rename from org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/AbstractTableControlExtension.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/AbstractFormTableControlExtension.java
index b68bbda..f24a80e 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/AbstractTableControlExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/AbstractFormTableControlExtension.java
@@ -8,15 +8,15 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.extension.ui.basic.table.control;
+package org.eclipse.scout.rt.client.extension.ui.basic.table.controls;
 
 import org.eclipse.scout.rt.client.extension.ui.action.AbstractActionExtension;
-import org.eclipse.scout.rt.client.extension.ui.basic.table.control.TableControlChains.TableControlInitFormChain;
+import org.eclipse.scout.rt.client.extension.ui.basic.table.controls.FormTableControlChains.TableControlInitFormChain;
 import org.eclipse.scout.rt.client.ui.basic.table.controls.AbstractTableControl;
 
-public abstract class AbstractTableControlExtension<OWNER extends AbstractTableControl> extends AbstractActionExtension<OWNER> implements ITableControlExtension<OWNER> {
+public abstract class AbstractFormTableControlExtension<OWNER extends AbstractTableControl> extends AbstractActionExtension<OWNER> implements IFormTableControlExtension<OWNER> {
 
-  public AbstractTableControlExtension(OWNER owner) {
+  public AbstractFormTableControlExtension(OWNER owner) {
     super(owner);
   }
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/TableControlChains.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/FormTableControlChains.java
similarity index 81%
rename from org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/TableControlChains.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/FormTableControlChains.java
index 37ae43b..8ff0651 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/TableControlChains.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/FormTableControlChains.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.extension.ui.basic.table.control;
+package org.eclipse.scout.rt.client.extension.ui.basic.table.controls;
 
 import java.util.List;
 
@@ -17,15 +17,15 @@
 import org.eclipse.scout.rt.client.ui.basic.table.controls.AbstractTableControl;
 import org.eclipse.scout.rt.shared.extension.AbstractExtensionChain;
 
-public final class TableControlChains {
+public final class FormTableControlChains {
 
-  private TableControlChains() {
+  private FormTableControlChains() {
   }
 
-  protected abstract static class AbstractTableControlChain extends AbstractExtensionChain<ITableControlExtension<? extends AbstractTableControl>> {
+  protected abstract static class AbstractTableControlChain extends AbstractExtensionChain<IFormTableControlExtension<? extends AbstractTableControl>> {
 
     public AbstractTableControlChain(List<? extends IActionExtension<? extends AbstractAction>> extensions) {
-      super(extensions, ITableControlExtension.class);
+      super(extensions, IFormTableControlExtension.class);
     }
   }
 
@@ -39,7 +39,7 @@
       MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
 
         @Override
-        protected void callMethod(ITableControlExtension<? extends AbstractTableControl> next) throws Exception {
+        protected void callMethod(IFormTableControlExtension<? extends AbstractTableControl> next) throws Exception {
           next.execInitForm(TableControlInitFormChain.this);
         }
       };
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/ITableControlExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/IFormTableControlExtension.java
similarity index 83%
rename from org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/ITableControlExtension.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/IFormTableControlExtension.java
index cbcc0e0..4d46665 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/control/ITableControlExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/basic/table/controls/IFormTableControlExtension.java
@@ -8,13 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.extension.ui.basic.table.control;
+package org.eclipse.scout.rt.client.extension.ui.basic.table.controls;
 
 import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
-import org.eclipse.scout.rt.client.extension.ui.basic.table.control.TableControlChains.TableControlInitFormChain;
+import org.eclipse.scout.rt.client.extension.ui.basic.table.controls.FormTableControlChains.TableControlInitFormChain;
 import org.eclipse.scout.rt.client.ui.basic.table.controls.AbstractTableControl;
 
-public interface ITableControlExtension<OWNER extends AbstractTableControl> extends IActionExtension<OWNER> {
+public interface IFormTableControlExtension<OWNER extends AbstractTableControl> extends IActionExtension<OWNER> {
 
   void execInitForm(TableControlInitFormChain chain);
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/AbstractDesktopExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/AbstractDesktopExtension.java
index a4e4604..d2282a2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/AbstractDesktopExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/AbstractDesktopExtension.java
@@ -10,11 +10,9 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.extension.ui.desktop;
 
-import java.util.List;
-
-import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopAddTrayMenusChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopBeforeClosingChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopClosingChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopDefaultViewChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopFormAboutToShowChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiAttachedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiDetachedChain;
@@ -25,7 +23,6 @@
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageDetailTableChangedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageSearchFormChangedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopTablePageLoadedChain;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
@@ -50,11 +47,6 @@
   }
 
   @Override
-  public void execAddTrayMenus(DesktopAddTrayMenusChain chain, List<IMenu> menus) {
-    chain.execAddTrayMenus(menus);
-  }
-
-  @Override
   public void execBeforeClosing(DesktopBeforeClosingChain chain) {
     chain.execBeforeClosing();
   }
@@ -103,4 +95,9 @@
   public void execGuiDetached(DesktopGuiDetachedChain chain) {
     chain.execGuiDetached();
   }
+
+  @Override
+  public void execDefaultView(DesktopDefaultViewChain chain) {
+    chain.execDefaultView();
+  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopChains.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopChains.java
index c49a401..1b57e0f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopChains.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/DesktopChains.java
@@ -12,7 +12,6 @@
 
 import java.util.List;
 
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
@@ -66,23 +65,6 @@
     }
   }
 
-  public static class DesktopAddTrayMenusChain extends AbstractDesktopChain {
-
-    public DesktopAddTrayMenusChain(List<? extends IDesktopExtension<? extends AbstractDesktop>> extensions) {
-      super(extensions);
-    }
-
-    public void execAddTrayMenus(final List<IMenu> menus) {
-      MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
-        @Override
-        protected void callMethod(IDesktopExtension<? extends AbstractDesktop> next) {
-          next.execAddTrayMenus(DesktopAddTrayMenusChain.this, menus);
-        }
-      };
-      callChain(methodInvocation, menus);
-    }
-  }
-
   public static class DesktopBeforeClosingChain extends AbstractDesktopChain {
 
     public DesktopBeforeClosingChain(List<? extends IDesktopExtension<? extends AbstractDesktop>> extensions) {
@@ -253,4 +235,21 @@
       callChain(methodInvocation);
     }
   }
+
+  public static class DesktopDefaultViewChain extends AbstractDesktopChain {
+
+    public DesktopDefaultViewChain(List<? extends IDesktopExtension<? extends AbstractDesktop>> extensions) {
+      super(extensions);
+    }
+
+    public void execDefaultView() {
+      MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
+        @Override
+        protected void callMethod(IDesktopExtension<? extends AbstractDesktop> next) {
+          next.execDefaultView(DesktopDefaultViewChain.this);
+        }
+      };
+      callChain(methodInvocation);
+    }
+  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/IDesktopExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/IDesktopExtension.java
index e616ce5..c61c5ce 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/IDesktopExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/IDesktopExtension.java
@@ -10,11 +10,9 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.extension.ui.desktop;
 
-import java.util.List;
-
-import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopAddTrayMenusChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopBeforeClosingChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopClosingChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopDefaultViewChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopFormAboutToShowChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiAttachedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiDetachedChain;
@@ -25,7 +23,6 @@
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageDetailTableChangedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageSearchFormChangedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopTablePageLoadedChain;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
@@ -35,15 +32,10 @@
 
 public interface IDesktopExtension<DESKTOP extends AbstractDesktop> extends IExtension<DESKTOP> {
 
-  /**
-   * @param chain
-   */
   void execInit(DesktopInitChain chain);
 
   void execOpened(DesktopOpenedChain chain);
 
-  void execAddTrayMenus(DesktopAddTrayMenusChain chain, List<IMenu> menus);
-
   void execBeforeClosing(DesktopBeforeClosingChain chain);
 
   void execPageDetailFormChanged(DesktopPageDetailFormChangedChain chain, IForm oldForm, IForm newForm);
@@ -64,4 +56,6 @@
 
   void execGuiDetached(DesktopGuiDetachedChain chain);
 
+  void execDefaultView(DesktopDefaultViewChain chain);
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/AbstractFormToolButtonExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/AbstractFormToolButtonExtension.java
index e05a571..bde4c82 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/AbstractFormToolButtonExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/AbstractFormToolButtonExtension.java
@@ -10,19 +10,18 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.extension.ui.desktop.outline;
 
-import org.eclipse.scout.rt.client.extension.ui.action.tool.AbstractToolButtonExtension;
-import org.eclipse.scout.rt.client.extension.ui.desktop.outline.FormToolButtonChains.FormToolButtonInitFormChain;
+import org.eclipse.scout.rt.client.extension.ui.form.AbstractFormMenuExtension;
 import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 
-public abstract class AbstractFormToolButtonExtension<FORM extends IForm, OWNER extends AbstractFormToolButton<FORM>> extends AbstractToolButtonExtension<OWNER> implements IFormToolButtonExtension<FORM, OWNER> {
+/**
+ * @deprecated use {@link AbstractFormMenuExtension} instead
+ */
+@SuppressWarnings("deprecation")
+@Deprecated
+public abstract class AbstractFormToolButtonExtension<FORM extends IForm, OWNER extends AbstractFormToolButton<FORM>> extends AbstractFormMenuExtension<FORM, OWNER> implements IFormToolButtonExtension<FORM, OWNER> {
 
   public AbstractFormToolButtonExtension(OWNER owner) {
     super(owner);
   }
-
-  @Override
-  public void execInitForm(FormToolButtonInitFormChain<FORM> chain, FORM form) {
-    chain.execInitForm(form);
-  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/FormToolButtonChains.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/FormToolButtonChains.java
index 85102bc..ee4823e 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/FormToolButtonChains.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/FormToolButtonChains.java
@@ -13,20 +13,23 @@
 import java.util.List;
 
 import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.FormMenuChains;
+import org.eclipse.scout.rt.client.extension.ui.form.FormMenuChains.AbstractFormMenuChain;
 import org.eclipse.scout.rt.client.ui.action.AbstractAction;
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.shared.extension.AbstractExtensionChain;
 
+/**
+ * @deprecated use {@link FormMenuChains} instead
+ */
+@Deprecated
 public final class FormToolButtonChains {
 
   private FormToolButtonChains() {
   }
 
-  protected abstract static class AbstractFormToolButtonChain<FORM extends IForm> extends AbstractExtensionChain<IFormToolButtonExtension<FORM, ? extends AbstractFormToolButton<FORM>>> {
-
+  protected abstract static class AbstractFormToolButtonChain<FORM extends IForm> extends AbstractFormMenuChain<FORM> {
     public AbstractFormToolButtonChain(List<? extends IActionExtension<? extends AbstractAction>> extensions) {
-      super(extensions, IFormToolButtonExtension.class);
+      super(extensions);
     }
   }
 
@@ -35,15 +38,5 @@
     public FormToolButtonInitFormChain(List<? extends IActionExtension<? extends AbstractAction>> extensions) {
       super(extensions);
     }
-
-    public void execInitForm(final FORM form) {
-      MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
-        @Override
-        protected void callMethod(IFormToolButtonExtension<FORM, ? extends AbstractFormToolButton<FORM>> next) throws Exception {
-          next.execInitForm(FormToolButtonInitFormChain.this, form);
-        }
-      };
-      callChain(methodInvocation, form);
-    }
   }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/IFormToolButtonExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/IFormToolButtonExtension.java
index 0fca870..fa343b9 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/IFormToolButtonExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/desktop/outline/IFormToolButtonExtension.java
@@ -10,12 +10,17 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.extension.ui.desktop.outline;
 
-import org.eclipse.scout.rt.client.extension.ui.action.tool.IToolButtonExtension;
 import org.eclipse.scout.rt.client.extension.ui.desktop.outline.FormToolButtonChains.FormToolButtonInitFormChain;
+import org.eclipse.scout.rt.client.extension.ui.form.IFormMenuExtension;
 import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 
-public interface IFormToolButtonExtension<FORM extends IForm, OWNER extends AbstractFormToolButton<FORM>> extends IToolButtonExtension<OWNER> {
+/**
+ * @deprecated use {@link IFormMenuExtension} instead
+ */
+@SuppressWarnings("deprecation")
+@Deprecated
+public interface IFormToolButtonExtension<FORM extends IForm, OWNER extends AbstractFormToolButton<FORM>> extends IFormMenuExtension<FORM, OWNER> {
 
   void execInitForm(FormToolButtonInitFormChain<FORM> chain, FORM form);
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/AbstractFormMenuExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/AbstractFormMenuExtension.java
new file mode 100644
index 0000000..3ba4d7d
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/AbstractFormMenuExtension.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.extension.ui.form;
+
+import org.eclipse.scout.rt.client.extension.ui.action.menu.AbstractMenuExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.FormMenuChains.FormMenuInitFormChain;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+
+public abstract class AbstractFormMenuExtension<FORM extends IForm, OWNER extends AbstractFormMenu<FORM>> extends AbstractMenuExtension<OWNER> implements IFormMenuExtension<FORM, OWNER> {
+
+  public AbstractFormMenuExtension(OWNER owner) {
+    super(owner);
+  }
+
+  @Override
+  public void execInitForm(FormMenuInitFormChain<FORM> chain, FORM form) {
+    chain.execInitForm(form);
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/FormMenuChains.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/FormMenuChains.java
new file mode 100644
index 0000000..c5c9393
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/FormMenuChains.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.extension.ui.form;
+
+import java.util.List;
+
+import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
+import org.eclipse.scout.rt.client.ui.action.AbstractAction;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.shared.extension.AbstractExtensionChain;
+
+public final class FormMenuChains {
+
+  private FormMenuChains() {
+  }
+
+  public abstract static class AbstractFormMenuChain<FORM extends IForm> extends AbstractExtensionChain<IFormMenuExtension<FORM, ? extends AbstractFormMenu<FORM>>> {
+
+    public AbstractFormMenuChain(List<? extends IActionExtension<? extends AbstractAction>> extensions) {
+      super(extensions, IFormMenuExtension.class);
+    }
+  }
+
+  public static class FormMenuInitFormChain<FORM extends IForm> extends AbstractFormMenuChain<FORM> {
+
+    public FormMenuInitFormChain(List<? extends IActionExtension<? extends AbstractAction>> extensions) {
+      super(extensions);
+    }
+
+    public void execInitForm(final FORM form) {
+      MethodInvocation<Object> methodInvocation = new MethodInvocation<Object>() {
+        @Override
+        protected void callMethod(IFormMenuExtension<FORM, ? extends AbstractFormMenu<FORM>> next) throws Exception {
+          next.execInitForm(FormMenuInitFormChain.this, form);
+        }
+      };
+      callChain(methodInvocation, form);
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/IFormMenuExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/IFormMenuExtension.java
new file mode 100644
index 0000000..de51f3b
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/extension/ui/form/IFormMenuExtension.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.extension.ui.form;
+
+import org.eclipse.scout.rt.client.extension.ui.action.menu.IMenuExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.FormMenuChains.FormMenuInitFormChain;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+
+public interface IFormMenuExtension<FORM extends IForm, OWNER extends AbstractFormMenu<FORM>> extends IMenuExtension<OWNER> {
+
+  void execInitForm(FormMenuInitFormChain<FORM> chain, FORM form);
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/bookmark/internal/BookmarkUtility.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/bookmark/internal/BookmarkUtility.java
index ee1c3bc..332a1c9 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/bookmark/internal/BookmarkUtility.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/bookmark/internal/BookmarkUtility.java
@@ -607,7 +607,7 @@
     }
     b.setTitle(buf.toString());
     // text
-    StringBuffer text = new StringBuffer();
+    StringBuilder text = new StringBuilder();
     // add constraints texts
     String prefix = "";
     for (int i = 0; i < path.size(); i++) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/file/FileService.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/file/FileService.java
index 63c8977..2855abd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/file/FileService.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/file/FileService.java
@@ -87,7 +87,9 @@
           f = getFileLocation(spec.getDirectory(), spec.getName(), false);
         }
         if (spec.exists() && spec.hasContent()) {
-          spec.writeData(new FileOutputStream(f));
+          try (OutputStream out = new FileOutputStream(f)) {
+            spec.writeData(out);
+          }
           f.setLastModified(spec.getLastModified());
         }
         else if (!spec.exists()) {
@@ -169,7 +171,9 @@
             int counter = 0;
             long fileDate = spec.getLastModified();
             File part = getFileLocation(fileDirectory, spec.getName() + "." + counter, false);
-            spec.writeData(new FileOutputStream(part));
+            try (OutputStream out = new FileOutputStream(part)) {
+              spec.writeData(out);
+            }
             part.setLastModified(fileDate);
             RemoteFile specPart = spec;
             while (specPart.hasMoreParts()) {
@@ -177,7 +181,9 @@
               part = getFileLocation(fileDirectory, spec.getName() + "." + counter, false);
               if (!part.exists() || fileDate != part.lastModified()) {
                 specPart = svc.getRemoteFilePart(spec, counter);
-                specPart.writeData(new FileOutputStream(part));
+                try (OutputStream out = new FileOutputStream(part)) {
+                  specPart.writeData(out);
+                }
                 part.setLastModified(fileDate);
               }
               else {
@@ -207,7 +213,9 @@
           }
           else {
             // normal files
-            spec.writeData(new FileOutputStream(f));
+            try (OutputStream out = new FileOutputStream(f)) {
+              spec.writeData(out);
+            }
             f.setLastModified(spec.getLastModified());
           }
         }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/icon/AbstractIconProviderService.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/icon/AbstractIconProviderService.java
index 3d8b139..bc87bce 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/icon/AbstractIconProviderService.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/icon/AbstractIconProviderService.java
@@ -10,6 +10,7 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.services.common.icon;
 
+import java.io.InputStream;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -108,9 +109,9 @@
         String iconName = iconNames[i];
         URL url = findResource(relativePath);
         if (url != null) {
-          try {
+          try (InputStream in = url.openStream()) {
             IconSpec iconSpec = new IconSpec();
-            byte[] content = IOUtility.getContent(url.openStream(), true);
+            byte[] content = IOUtility.readBytes(in);
             if (content != null) {
               iconSpec.setContent(content);
             }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/security/PermissionServiceClientProxy.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/security/PermissionServiceClientProxy.java
index 462ac9e..f1e4f62 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/security/PermissionServiceClientProxy.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/services/common/security/PermissionServiceClientProxy.java
@@ -30,9 +30,6 @@
   private final Object m_stateLock = new Object();
   private final Map<Object, ServiceState> m_stateMap = new HashMap<Object, ServiceState>();
 
-  public PermissionServiceClientProxy() {
-  }
-
   private ServiceState getServiceState() {
     IClientSession session = ClientSessionProvider.currentSession();
     Object key = null;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/servicetunnel/http/ClientHttpServiceTunnel.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/servicetunnel/http/ClientHttpServiceTunnel.java
index ab65227..c8531e6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/servicetunnel/http/ClientHttpServiceTunnel.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/servicetunnel/http/ClientHttpServiceTunnel.java
@@ -13,23 +13,21 @@
 import java.net.URL;
 import java.util.List;
 
-import org.eclipse.scout.rt.client.IClientNode;
 import org.eclipse.scout.rt.client.clientnotification.ClientNotificationDispatcher;
+import org.eclipse.scout.rt.client.context.ClientRunContext;
 import org.eclipse.scout.rt.client.context.ClientRunContexts;
 import org.eclipse.scout.rt.client.services.common.perf.IPerformanceAnalyzerService;
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.context.RunContext;
+import org.eclipse.scout.rt.platform.Replace;
 import org.eclipse.scout.rt.platform.job.DoneEvent;
 import org.eclipse.scout.rt.platform.job.IBlockingCondition;
 import org.eclipse.scout.rt.platform.job.IDoneHandler;
 import org.eclipse.scout.rt.platform.job.Jobs;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
-import org.eclipse.scout.rt.shared.ISession;
 import org.eclipse.scout.rt.shared.clientnotification.ClientNotificationMessage;
-import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelRequest;
 import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelResponse;
-import org.eclipse.scout.rt.shared.servicetunnel.http.AbstractHttpServiceTunnel;
+import org.eclipse.scout.rt.shared.servicetunnel.http.HttpServiceTunnel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,7 +35,8 @@
  * Client-side tunnel used to invoke a service through HTTP. This class re-defines methods of it's super class since the
  * internal class does not belong to the public API.
  */
-public class ClientHttpServiceTunnel extends AbstractHttpServiceTunnel implements IClientServiceTunnel {
+@Replace
+public class ClientHttpServiceTunnel extends HttpServiceTunnel implements IClientServiceTunnel {
 
   private static final Logger LOG = LoggerFactory.getLogger(ClientHttpServiceTunnel.class);
 
@@ -62,19 +61,6 @@
   }
 
   @Override
-  protected void beforeTunnel(ServiceTunnelRequest serviceRequest) {
-    ISession session = ISession.CURRENT.get();
-    if (session != null) {
-      serviceRequest.setSessionId(session.getId());
-    }
-    else {
-      // use this client's node-id for session less communication
-      serviceRequest.setSessionId(IClientNode.ID);
-    }
-    serviceRequest.setClientNodeId(IClientNode.ID);
-  }
-
-  @Override
   protected void afterTunnel(long t0, ServiceTunnelResponse serviceResponse) {
     if (isAnalyzeNetworkLatency()) {
       // performance analyzer
@@ -132,7 +118,8 @@
   }
 
   @Override
-  protected RunContext createCurrentRunContext() {
+  public ClientRunContext createRunContext() {
     return ClientRunContexts.copyCurrent();
   }
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/AbstractDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/AbstractDeviceTransformer.java
new file mode 100644
index 0000000..5d8696c
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/AbstractDeviceTransformer.java
@@ -0,0 +1,116 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+
+public abstract class AbstractDeviceTransformer implements IDeviceTransformer {
+  private IDesktop m_desktop;
+  private Set<IForm> m_dirtyGridData = new HashSet<>();
+  private DeviceTransformationConfig m_deviceTransformationConfig;
+
+  public AbstractDeviceTransformer() {
+    m_deviceTransformationConfig = createDeviceTransformationConfig();
+    initTransformationConfig();
+  }
+
+  protected DeviceTransformationConfig createDeviceTransformationConfig() {
+    return new DeviceTransformationConfig();
+  }
+
+  @Override
+  public DeviceTransformationConfig getDeviceTransformationConfig() {
+    return m_deviceTransformationConfig;
+  }
+
+  protected void initTransformationConfig() {
+  }
+
+  @Override
+  public void setDesktop(IDesktop desktop) {
+    m_desktop = desktop;
+  }
+
+  @Override
+  public abstract boolean isActive();
+
+  public IDesktop getDesktop() {
+    return m_desktop;
+  }
+
+  @Override
+  public void dispose() {
+  }
+
+  @Override
+  public void transformDesktop() {
+  }
+
+  @Override
+  public void transformForm(IForm form) {
+  }
+
+  @Override
+  public void notifyFormDisposed(IForm form) {
+  }
+
+  @Override
+  public boolean isFormExcluded(IForm form) {
+    return getDeviceTransformationConfig().isFormExcluded(form);
+  }
+
+  @Override
+  public boolean isFormFieldExcluded(IFormField formField) {
+    return getDeviceTransformationConfig().isFieldExcluded(formField);
+  }
+
+  @Override
+  public void transformFormField(IFormField field) {
+  }
+
+  @Override
+  public void transformOutline(IOutline outline) {
+  }
+
+  @Override
+  public void transformPage(IPage<?> page) {
+  }
+
+  @Override
+  public void transformPageDetailForm(IForm form) {
+  }
+
+  @Override
+  public void transformPageDetailTable(ITable table) {
+  }
+
+  @Override
+  public void notifyDesktopClosing() {
+  }
+
+  @Override
+  public void notifyPageSearchFormInit(IPageWithTable<ITable> page) {
+  }
+
+  @Override
+  public boolean isGridDataDirty(IForm form) {
+    return m_dirtyGridData.contains(form);
+  }
+
+  @Override
+  public void gridDataRebuilt(IForm form) {
+    m_dirtyGridData.remove(form);
+  }
+
+  protected void markGridDataDirty(IForm form) {
+    m_dirtyGridData.add(form);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DesktopExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DesktopExtension.java
new file mode 100644
index 0000000..8d2e255
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DesktopExtension.java
@@ -0,0 +1,41 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.desktop.AbstractDesktopExtension;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopClosingChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopInitChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageDetailFormChangedChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageDetailTableChangedChain;
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class DesktopExtension extends AbstractDesktopExtension<AbstractDesktop> {
+
+  public DesktopExtension(AbstractDesktop owner) {
+    super(owner);
+  }
+
+  @Override
+  public void execInit(DesktopInitChain chain) {
+    super.execInit(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformDesktop();
+  }
+
+  @Override
+  public void execClosing(DesktopClosingChain chain) {
+    super.execClosing(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().notifyDesktopClosing();
+  }
+
+  @Override
+  public void execPageDetailFormChanged(DesktopPageDetailFormChangedChain chain, IForm oldForm, IForm newForm) {
+    super.execPageDetailFormChanged(chain, oldForm, newForm);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformPageDetailForm(newForm);
+  }
+
+  @Override
+  public void execPageDetailTableChanged(DesktopPageDetailTableChangedChain chain, ITable oldTable, ITable newTable) {
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformPageDetailTable(newTable);
+  }
+}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationConfig.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationConfig.java
similarity index 98%
rename from org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationConfig.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationConfig.java
index 07c3ff5..f4358a0 100644
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationConfig.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationConfig.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
+package org.eclipse.scout.rt.client.transformation;
 
 import java.util.HashSet;
 import java.util.Map;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationPlatformListener.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationPlatformListener.java
new file mode 100644
index 0000000..0479cc6
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationPlatformListener.java
@@ -0,0 +1,23 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.IPlatform;
+import org.eclipse.scout.rt.platform.IPlatformListener;
+import org.eclipse.scout.rt.platform.PlatformEvent;
+import org.eclipse.scout.rt.shared.extension.IExtensionRegistry;
+
+public class DeviceTransformationPlatformListener implements IPlatformListener {
+
+  @Override
+  public void stateChanged(PlatformEvent event) {
+    if (event.getState() == IPlatform.State.PlatformStarted) {
+      BEANS.get(IExtensionRegistry.class).register(DesktopExtension.class);
+      BEANS.get(IExtensionRegistry.class).register(OutlineExtension.class);
+      BEANS.get(IExtensionRegistry.class).register(PageExtension.class);
+      BEANS.get(IExtensionRegistry.class).register(PageWithTableExtension.class);
+      BEANS.get(IExtensionRegistry.class).register(FormExtension.class);
+      BEANS.get(IExtensionRegistry.class).register(FormFieldExtension.class);
+    }
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationService.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationService.java
new file mode 100644
index 0000000..0403faf
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationService.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.IClientSession;
+import org.eclipse.scout.rt.client.session.ClientSessionProvider;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.shared.session.ISessionListener;
+import org.eclipse.scout.rt.shared.session.SessionEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @since 3.9.0
+ */
+public class DeviceTransformationService implements IDeviceTransformationService {
+  private static final Logger LOG = LoggerFactory.getLogger(DeviceTransformationService.class);
+
+  private static final String SESSION_DATA_KEY = "DeviceTransformationServiceData";
+  private IDeviceTransformer m_nullTransformer = new NullDeviceTransformer();
+
+  @Override
+  public void install(IDesktop desktop) {
+    IClientSession session = ClientSessionProvider.currentSession();
+    if (session == null) {
+      throw new IllegalArgumentException("No current session available");
+    }
+    if (desktop == null) {
+      throw new IllegalArgumentException("Desktop must not be null");
+    }
+    if (getDeviceTransformer(session) != null) {
+      // Already installed for the current session
+      return;
+    }
+
+    IDeviceTransformer data = createDeviceTransformer();
+    data.setDesktop(desktop);
+    session.setData(SESSION_DATA_KEY, data);
+    session.addListener(new P_SessionListener());
+    LOG.debug("DeviceTransformationService installed for session {}", session);
+  }
+
+  @Override
+  public void uninstall() {
+    uninstall(ClientSessionProvider.currentSession());
+  }
+
+  protected void uninstall(IClientSession session) {
+    IDeviceTransformer transformer = getDeviceTransformer(session);
+    if (transformer == null) {
+      // Not installed for current session
+      return;
+    }
+    transformer.dispose();
+    session.setData(SESSION_DATA_KEY, null);
+    LOG.debug("DeviceTransformationService uninstalled for session {}", session);
+  }
+
+  protected IDeviceTransformer createDeviceTransformer() {
+    return BEANS.get(MainDeviceTransformer.class);
+  }
+
+  @Override
+  public IDeviceTransformer getDeviceTransformer() {
+    IDeviceTransformer transformer = getDeviceTransformer(ClientSessionProvider.currentSession());
+    if (transformer == null) {
+      return m_nullTransformer;
+    }
+    return transformer;
+  }
+
+  protected IDeviceTransformer getDeviceTransformer(IClientSession session) {
+    if (session == null) {
+      return null;
+    }
+    Object data = session.getData(SESSION_DATA_KEY);
+    if (data == null) {
+      return null;
+    }
+    return (IDeviceTransformer) data;
+  }
+
+  private class P_SessionListener implements ISessionListener {
+    @Override
+    public void sessionChanged(SessionEvent event) {
+      if (event.getType() == SessionEvent.TYPE_STOPPED) {
+        IClientSession session = (IClientSession) event.getSource();
+        session.removeListener(this);
+        uninstall(session);
+      }
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationUtility.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationUtility.java
similarity index 91%
rename from org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationUtility.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationUtility.java
index df014e4..01bb5f2 100644
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/DeviceTransformationUtility.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/DeviceTransformationUtility.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
+package org.eclipse.scout.rt.client.transformation;
 
 import org.eclipse.scout.rt.platform.BEANS;
 
@@ -17,6 +17,10 @@
  */
 public class DeviceTransformationUtility {
 
+  private DeviceTransformationUtility() {
+
+  }
+
   /**
    * @return a reference to the active device transformation configuration.
    */
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormExtension.java
new file mode 100644
index 0000000..7edd4c6
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormExtension.java
@@ -0,0 +1,27 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.form.AbstractFormExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.FormChains.FormDisposeFormChain;
+import org.eclipse.scout.rt.client.extension.ui.form.FormChains.FormInitFormChain;
+import org.eclipse.scout.rt.client.ui.form.AbstractForm;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class FormExtension extends AbstractFormExtension<AbstractForm> {
+
+  public FormExtension(AbstractForm ownerForm) {
+    super(ownerForm);
+  }
+
+  @Override
+  public void execInitForm(FormInitFormChain chain) {
+    super.execInitForm(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformForm(getOwner());
+  }
+
+  @Override
+  public void execDisposeForm(FormDisposeFormChain chain) {
+    super.execDisposeForm(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().notifyFormDisposed(getOwner());
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormFieldExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormFieldExtension.java
new file mode 100644
index 0000000..7d3b20d
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/FormFieldExtension.java
@@ -0,0 +1,20 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.form.fields.AbstractFormFieldExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.fields.FormFieldChains.FormFieldInitFieldChain;
+import org.eclipse.scout.rt.client.ui.form.fields.AbstractFormField;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class FormFieldExtension extends AbstractFormFieldExtension<AbstractFormField> {
+
+  public FormFieldExtension(AbstractFormField ownerField) {
+    super(ownerField);
+  }
+
+  @Override
+  public void execInitField(FormFieldInitFieldChain chain) {
+    super.execInitField(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformFormField(getOwner());
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformation.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformation.java
similarity index 91%
rename from org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformation.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformation.java
index 0eb3747..297e5b8 100644
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformation.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformation.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
+package org.eclipse.scout.rt.client.transformation;
 
 /**
  * @since 3.9.0
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationService.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformationService.java
similarity index 91%
rename from org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationService.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformationService.java
index 67c0e1a..1af3cdf 100644
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/IDeviceTransformationService.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformationService.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
+package org.eclipse.scout.rt.client.transformation;
 
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
 import org.eclipse.scout.rt.platform.service.IService;
@@ -18,8 +18,6 @@
  */
 public interface IDeviceTransformationService extends IService {
 
-  void install();
-
   void install(IDesktop desktop);
 
   void uninstall();
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformer.java
new file mode 100644
index 0000000..6f0efb6
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/IDeviceTransformer.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+import org.eclipse.scout.rt.platform.Bean;
+
+/**
+ * @since 3.9.0
+ */
+@Bean
+public interface IDeviceTransformer {
+
+  boolean isActive();
+
+  void dispose();
+
+  void setDesktop(IDesktop desktop);
+
+  void transformDesktop();
+
+  void transformForm(IForm form);
+
+  void transformFormField(IFormField field);
+
+  void transformOutline(IOutline outline);
+
+  void transformPage(IPage<?> page);
+
+  void transformPageDetailForm(IForm form);
+
+  void transformPageDetailTable(ITable table);
+
+  void notifyFormDisposed(IForm form);
+
+  void notifyDesktopClosing();
+
+  void notifyPageSearchFormInit(IPageWithTable<ITable> page);
+
+  boolean isFormExcluded(IForm form);
+
+  boolean isFormFieldExcluded(IFormField formField);
+
+  boolean isGridDataDirty(IForm form);
+
+  void gridDataRebuilt(IForm form);
+
+  DeviceTransformationConfig getDeviceTransformationConfig();
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MainDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MainDeviceTransformer.java
new file mode 100644
index 0000000..1473dc2
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MainDeviceTransformer.java
@@ -0,0 +1,268 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
+import org.eclipse.scout.rt.client.ui.form.FormUtility;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.filter.IFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MainDeviceTransformer implements IDeviceTransformer {
+  private static final Logger LOG = LoggerFactory.getLogger(MainDeviceTransformer.class);
+
+  private List<IDeviceTransformer> m_transformers;
+  private final Map<IForm, WeakReference<IForm>> m_transformedForms = new WeakHashMap<>();
+  private final Map<IOutline, WeakReference<IOutline>> m_transformedOutlines = new WeakHashMap<>();
+
+  public List<IDeviceTransformer> getTransformers() {
+    if (m_transformers == null) {
+      m_transformers = createTransformers();
+      LOG.info("Using following device transformers{}", m_transformers);
+    }
+    return m_transformers;
+  }
+
+  protected List<IDeviceTransformer> createTransformers() {
+    return BEANS.all(IDeviceTransformer.class, new IFilter<IDeviceTransformer>() {
+      @Override
+      public boolean accept(IDeviceTransformer transformer) {
+        return !(transformer instanceof MainDeviceTransformer) && transformer.isActive();
+      }
+    });
+  }
+
+  @Override
+  public boolean isActive() {
+    return !getTransformers().isEmpty();
+  }
+
+  @Override
+  public void dispose() {
+    if (!isActive()) {
+      return;
+    }
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.dispose();
+    }
+    if (!m_transformedForms.isEmpty()) {
+      LOG.warn("Transformed forms map is not empty. Make sure every form gets closed properly to free up memory as quickly as possible. Cleaning up now...");
+      m_transformedForms.clear();
+    }
+    m_transformedOutlines.clear();
+  }
+
+  @Override
+  public void setDesktop(IDesktop desktop) {
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.setDesktop(desktop);
+    }
+  }
+
+  @Override
+  public void transformDesktop() {
+    if (!isActive()) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformDesktop();
+    }
+  }
+
+  @Override
+  public void transformForm(IForm form) {
+    if (!isActive() || isFormExcluded(form)) {
+      return;
+    }
+
+    WeakReference<IForm> formRef = m_transformedForms.get(form);
+    if (formRef != null) {
+      // already transformed
+      // form may be reinitialized any time (e.g. using doReset()) -> don't transform again
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformForm(form);
+    }
+
+    if (isGridDataDirty(form)) {
+      FormUtility.rebuildFieldGrid(form, true);
+      gridDataRebuilt(form);
+      if (isGridDataDirty(form)) {
+        throw new IllegalStateException("Potential memory leak: gridData still marked as dirty for form " + form);
+      }
+    }
+
+    //mark form as transformed
+    m_transformedForms.put(form, new WeakReference<IForm>(form));
+  }
+
+  @Override
+  public void notifyFormDisposed(IForm form) {
+    m_transformedForms.remove(form);
+  }
+
+  @Override
+  public boolean isFormExcluded(IForm form) {
+    if (!isActive()) {
+      return false;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      if (transformer.isFormExcluded(form)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public boolean isFormFieldExcluded(IFormField formField) {
+    if (!isActive()) {
+      return false;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      if (transformer.isFormFieldExcluded(formField)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public void transformFormField(IFormField field) {
+    if (!isActive() || isFormExcluded(field.getForm()) || isFormFieldExcluded(field)) {
+      return;
+    }
+
+    WeakReference<IForm> formRef = m_transformedForms.get(field.getForm());
+    if (formRef != null) {
+      // Already transformed
+      // fields can only be added during form initialization -> no need to transform again if form has already been initialized
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformFormField(field);
+    }
+  }
+
+  @Override
+  public void transformOutline(IOutline outline) {
+    if (!isActive()) {
+      return;
+    }
+
+    WeakReference<IOutline> outlineRef = m_transformedOutlines.get(outline);
+    if (outlineRef != null) {
+      // Already transformed
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformOutline(outline);
+    }
+
+    // mark as transformed
+    m_transformedOutlines.put(outline, new WeakReference<IOutline>(outline));
+  }
+
+  @Override
+  public void transformPage(IPage<?> page) {
+    if (!isActive()) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformPage(page);
+    }
+  }
+
+  @Override
+  public void transformPageDetailForm(IForm form) {
+    if (!isActive() || form == null || isFormExcluded(form)) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformPageDetailForm(form);
+    }
+  }
+
+  @Override
+  public void transformPageDetailTable(ITable table) {
+    if (!isActive() || table == null) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.transformPageDetailTable(table);
+    }
+  }
+
+  @Override
+  public void notifyDesktopClosing() {
+    if (!isActive()) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.notifyDesktopClosing();
+    }
+  }
+
+  @Override
+  public void notifyPageSearchFormInit(IPageWithTable<ITable> page) {
+    if (!isActive()) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.notifyPageSearchFormInit(page);
+    }
+  }
+
+  @Override
+  public boolean isGridDataDirty(IForm form) {
+    if (!isActive()) {
+      return false;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      if (transformer.isGridDataDirty(form)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public void gridDataRebuilt(IForm form) {
+    if (!isActive()) {
+      return;
+    }
+
+    for (IDeviceTransformer transformer : getTransformers()) {
+      transformer.gridDataRebuilt(form);
+    }
+  }
+
+  @Override
+  public DeviceTransformationConfig getDeviceTransformationConfig() {
+    return null;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformation.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformation.java
similarity index 82%
rename from org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformation.java
rename to org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformation.java
index 7511c14..df3bee9 100644
--- a/org.eclipse.scout.rt.client.mobile/src/main/java/org/eclipse/scout/rt/client/mobile/transformation/MobileDeviceTransformation.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformation.java
@@ -8,20 +8,19 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client.mobile.transformation;
+package org.eclipse.scout.rt.client.transformation;
 
 /**
  * @since 3.9.0
  */
 public enum MobileDeviceTransformation implements IDeviceTransformation {
   MOVE_FIELD_LABEL_TO_TOP,
+  MOVE_FIELD_STATUS_TO_TOP,
   MAKE_FIELD_SCALEABLE,
   MAKE_MAINBOX_SCROLLABLE,
   REDUCE_GROUPBOX_COLUMNS_TO_ONE,
   HIDE_PLACEHOLDER_FIELD,
+  HIDE_FIELD_STATUS,
   DISABLE_FORM_CANCEL_CONFIRMATION,
-  DISPLAY_FORM_HEADER,
-  ADD_MISSING_BACK_ACTION_TO_FORM_HEADER,
-  DISPLAY_OUTLINE_ROOT_NODE,
-  DISPLAY_PAGE_TABLE
+  AUTO_CLOSE_SEARCH_FORM
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformer.java
new file mode 100644
index 0000000..e0d0790
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/MobileDeviceTransformer.java
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.transformation;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
+import org.eclipse.scout.rt.client.ui.action.menu.TableMenuType;
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.basic.table.controls.ITableControl;
+import org.eclipse.scout.rt.client.ui.basic.table.controls.SearchFormTableControl;
+import org.eclipse.scout.rt.client.ui.basic.tree.ITree;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.OutlineMenuWrapper;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.ISearchForm;
+import org.eclipse.scout.rt.client.ui.form.FormEvent;
+import org.eclipse.scout.rt.client.ui.form.FormListener;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.fields.GridData;
+import org.eclipse.scout.rt.client.ui.form.fields.ICompositeField;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.IBooleanField;
+import org.eclipse.scout.rt.client.ui.form.fields.groupbox.IGroupBox;
+import org.eclipse.scout.rt.client.ui.form.fields.placeholder.IPlaceholderField;
+import org.eclipse.scout.rt.client.ui.form.fields.sequencebox.ISequenceBox;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.platform.util.CollectionUtility;
+import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
+
+/**
+ * @since 3.9.0
+ */
+@Order(5200)
+public class MobileDeviceTransformer extends AbstractDeviceTransformer {
+
+  @Override
+  public boolean isActive() {
+    return UserAgentUtility.isMobileDevice();
+  }
+
+  @Override
+  protected void initTransformationConfig() {
+    List<IDeviceTransformation> transformations = new LinkedList<IDeviceTransformation>();
+
+    transformations.add(MobileDeviceTransformation.MOVE_FIELD_LABEL_TO_TOP);
+    transformations.add(MobileDeviceTransformation.MOVE_FIELD_STATUS_TO_TOP);
+    transformations.add(MobileDeviceTransformation.MAKE_FIELD_SCALEABLE);
+    transformations.add(MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE);
+    transformations.add(MobileDeviceTransformation.REDUCE_GROUPBOX_COLUMNS_TO_ONE);
+    transformations.add(MobileDeviceTransformation.HIDE_PLACEHOLDER_FIELD);
+    transformations.add(MobileDeviceTransformation.HIDE_FIELD_STATUS);
+    transformations.add(MobileDeviceTransformation.DISABLE_FORM_CANCEL_CONFIRMATION);
+    transformations.add(MobileDeviceTransformation.AUTO_CLOSE_SEARCH_FORM);
+
+    for (IDeviceTransformation transformation : transformations) {
+      getDeviceTransformationConfig().enableTransformation(transformation);
+    }
+  }
+
+  @Override
+  public void transformDesktop() {
+    getDesktop().setDisplayStyle(IDesktop.DISPLAY_STYLE_COMPACT);
+  }
+
+  @Override
+  public void transformForm(IForm form) {
+    if (getDeviceTransformationConfig().isFormExcluded(form)) {
+      return;
+    }
+
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.DISABLE_FORM_CANCEL_CONFIRMATION)) {
+      form.setAskIfNeedSave(false);
+    }
+    if (form.getDisplayHint() == IForm.DISPLAY_HINT_VIEW) {
+      transformView(form);
+    }
+
+  }
+
+  protected void transformView(IForm form) {
+    form.setDisplayViewId(IForm.VIEW_ID_CENTER);
+  }
+
+  @Override
+  public void transformOutline(IOutline outline) {
+    outline.setNavigateButtonsVisible(false);
+    outline.setLazyExpandingEnabled(false);
+    outline.setAutoToggleBreadcrumbStyle(false);
+    outline.setDisplayStyle(ITree.DISPLAY_STYLE_BREADCRUMB);
+  }
+
+  @Override
+  public void transformPage(IPage page) {
+    if (page instanceof IPageWithTable) {
+      transformPageWithTable((IPageWithTable) page);
+    }
+  }
+
+  public void transformPageWithTable(IPageWithTable page) {
+    page.setLeaf(false);
+    page.setAlwaysCreateChildPage(true);
+
+    for (ITableControl control : page.getTable().getTableControls()) {
+      if (!(control instanceof SearchFormTableControl)) {
+        // TODO CGU Maybe some controls could be useful, like group ware or tile preview, how to distinguish?
+        control.setVisibleGranted(false);
+      }
+    }
+  }
+
+  @Override
+  public void transformPageDetailForm(IForm form) {
+    // Detail forms will be displayed inside a page (tree node)
+    // Make sure these inner forms are not scrollable because the outline already is
+    IGroupBox mainBox = form.getRootGroupBox();
+    if (mainBox.isScrollable().isTrue()) {
+      mainBox.setScrollable(false);
+      markGridDataDirty(mainBox.getForm());
+    }
+  }
+
+  @Override
+  public void transformPageDetailTable(ITable table) {
+    super.transformPageDetailTable(table);
+    IPage<?> activePage = getDesktop().getOutline().getActivePage();
+    IPage<?> parentPage = activePage.getParentPage();
+    if (parentPage == null) {
+      return;
+    }
+    ITable parentTable = parentPage.getTable();
+    if (parentTable == null) {
+      return;
+    }
+
+    // Remove empty space menus of the current detail table which are already defined on the parent detail table as single selection menus
+    // This prevents duplicate menus because the ui concatenates these menus when a node is shown
+    // It is important to only remove outline wrapper menus which are defined on the parent table because the menu could be defined on a page and therefore needs to be displayed
+    List<IMenu> newMenus = new ArrayList<IMenu>();
+    for (IMenu menu : table.getMenus()) {
+      if ((menu instanceof OutlineMenuWrapper)) {
+        OutlineMenuWrapper menuWrapper = (OutlineMenuWrapper) menu;
+        IMenu originalMenu = unwrapOutlineWrapperMenu(menuWrapper);
+        if (menuWrapper.getMenuTypes().contains(TableMenuType.EmptySpace)
+            && originalMenu.getMenuTypes().contains(TableMenuType.SingleSelection)
+            && parentTable.getMenus().contains(originalMenu)) {
+          // This menu should be removed -> don't add it to the list of new menus
+          continue;
+        }
+      }
+      newMenus.add(menu);
+    }
+    if (!CollectionUtility.equalsCollection(newMenus, table.getContextMenu().getChildActions())) {
+      table.getContextMenu().setChildActions(newMenus);
+    }
+  }
+
+  protected static IMenu unwrapOutlineWrapperMenu(IMenu menu) {
+    while (menu instanceof OutlineMenuWrapper) {
+      menu = ((OutlineMenuWrapper) menu).getWrappedMenu();
+    }
+    return menu;
+  }
+
+  @Override
+  public void notifyPageSearchFormInit(final IPageWithTable<ITable> page) {
+    if (!getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.AUTO_CLOSE_SEARCH_FORM)) {
+      return;
+    }
+    ISearchForm searchForm = page.getSearchFormInternal();
+    searchForm.addFormListener(new FormListener() {
+      @Override
+      public void formChanged(FormEvent e) {
+        if (FormEvent.TYPE_STORE_AFTER == e.getType()) {
+          onSearchFormStored(page);
+        }
+      }
+    });
+  }
+
+  protected void onSearchFormStored(IPageWithTable<ITable> page) {
+    SearchFormTableControl tableControl = page.getTable().getTableControl(SearchFormTableControl.class);
+    if (tableControl != null) {
+      tableControl.setSelected(false);
+    }
+  }
+
+  @Override
+  public void transformFormField(IFormField field) {
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MOVE_FIELD_LABEL_TO_TOP, field)) {
+      moveLabelToTop(field);
+    }
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MAKE_FIELD_SCALEABLE, field)) {
+      makeFieldScalable(field);
+    }
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.HIDE_FIELD_STATUS, field)) {
+      hideStatus(field);
+    }
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MOVE_FIELD_STATUS_TO_TOP, field)) {
+      moveStatusToTop(field);
+    }
+
+    if (field instanceof IGroupBox) {
+      transformGroupBox((IGroupBox) field);
+    }
+    else if (field instanceof IPlaceholderField) {
+      transformPlaceholderField((IPlaceholderField) field);
+    }
+  }
+
+  /**
+   * Makes sure weightX is set to 1 which makes the field scalable.
+   * <p>
+   * Reason:<br>
+   * The width of the field should be adjusted according to the display width, otherwise it may be too big to be
+   * displayed. <br>
+   * Additionally, since we use a one column layout, setting weightX to 0 might destroy the layout because it affects
+   * all the fields in the groupBox.
+   */
+  protected void makeFieldScalable(IFormField field) {
+    // Since a sequencebox contains several fields it's very risky to modify the gridData because it could make the fields too big or too small.
+    if (field.getParentField() instanceof ISequenceBox) {
+      return;
+    }
+
+    // Make sure weightX is set to 1 so the field grows and shrinks and does not break the 1 column layout
+    GridData gridDataHints = field.getGridDataHints();
+    if (gridDataHints.weightX == 0) {
+      gridDataHints.weightX = 1;
+      field.setGridDataHints(gridDataHints);
+
+      markGridDataDirty(field.getForm());
+    }
+  }
+
+  protected void moveLabelToTop(IFormField field) {
+    if (field instanceof IGroupBox) {
+      return;
+    }
+
+    if (IFormField.LABEL_POSITION_ON_FIELD == field.getLabelPosition()) {
+      return;
+    }
+
+    // Do not modify the labels inside a sequencebox
+    if (field.getParentField() instanceof ISequenceBox) {
+      return;
+    }
+
+    field.setLabelPosition(IFormField.LABEL_POSITION_TOP);
+
+    // The actual label of the boolean field is on the right side and position=top has no effect.
+    // Removing the label actually removes the place on the left side so that it gets aligned to the other fields.
+    if (field instanceof IBooleanField) {
+      field.setLabelVisible(false);
+    }
+  }
+
+  protected void moveStatusToTop(IFormField field) {
+    field.setStatusPosition(IFormField.STATUS_POSITION_TOP);
+  }
+
+  protected void hideStatus(IFormField field) {
+    if ((field instanceof ICompositeField)) {
+      ((ICompositeField) field).setStatusVisible(false, false);
+    }
+    else {
+      field.setStatusVisible(false);
+    }
+  }
+
+  protected void transformMainBox(IGroupBox groupBox) {
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.MAKE_MAINBOX_SCROLLABLE, groupBox)) {
+      makeGroupBoxScrollable(groupBox);
+    }
+  }
+
+  protected void makeGroupBoxScrollable(IGroupBox groupBox) {
+    if (!groupBox.isScrollable().isTrue()) {
+      groupBox.setScrollable(true);
+
+      // GridDataHints have been modified by setScrollable. Update the actual gridData with those hints.
+      markGridDataDirty(groupBox.getForm());
+    }
+  }
+
+  protected void transformGroupBox(IGroupBox groupBox) {
+    if (groupBox.isMainBox()) {
+      transformMainBox(groupBox);
+    }
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.REDUCE_GROUPBOX_COLUMNS_TO_ONE, groupBox)) {
+      groupBox.setGridColumnCountHint(1);
+    }
+  }
+
+  /**
+   * Makes placeholder fields invisible since they just waste space on 1 column layouts
+   */
+  protected void transformPlaceholderField(IPlaceholderField field) {
+    if (getDeviceTransformationConfig().isTransformationEnabled(MobileDeviceTransformation.HIDE_PLACEHOLDER_FIELD, field)) {
+      field.setVisible(false);
+    }
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/NullDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/NullDeviceTransformer.java
new file mode 100644
index 0000000..f310278
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/NullDeviceTransformer.java
@@ -0,0 +1,91 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+
+//SONAR:OFF
+public class NullDeviceTransformer implements IDeviceTransformer {
+
+  @Override
+  public boolean isActive() {
+    return true;
+  }
+
+  @Override
+  public void dispose() {
+  }
+
+  @Override
+  public void setDesktop(IDesktop desktop) {
+  }
+
+  @Override
+  public void transformDesktop() {
+  }
+
+  @Override
+  public void transformForm(IForm form) {
+  }
+
+  @Override
+  public void transformFormField(IFormField field) {
+  }
+
+  @Override
+  public void transformOutline(IOutline outline) {
+  }
+
+  @Override
+  public void transformPage(IPage<?> page) {
+  }
+
+  @Override
+  public void transformPageDetailForm(IForm form) {
+  }
+
+  @Override
+  public void transformPageDetailTable(ITable table) {
+  }
+
+  @Override
+  public void notifyFormDisposed(IForm form) {
+  }
+
+  @Override
+  public void notifyDesktopClosing() {
+  }
+
+  @Override
+  public void notifyPageSearchFormInit(IPageWithTable<ITable> page) {
+  }
+
+  @Override
+  public boolean isFormExcluded(IForm form) {
+    return false;
+  }
+
+  @Override
+  public boolean isFormFieldExcluded(IFormField formField) {
+    return false;
+  }
+
+  @Override
+  public boolean isGridDataDirty(IForm form) {
+    return false;
+  }
+
+  @Override
+  public void gridDataRebuilt(IForm form) {
+  }
+
+  @Override
+  public DeviceTransformationConfig getDeviceTransformationConfig() {
+    return null;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/OutlineExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/OutlineExtension.java
new file mode 100644
index 0000000..7a2ed39
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/OutlineExtension.java
@@ -0,0 +1,20 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.basic.tree.TreeChains.TreeInitTreeChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.outline.AbstractOutlineExtension;
+import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractOutline;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class OutlineExtension extends AbstractOutlineExtension<AbstractOutline> {
+
+  public OutlineExtension(AbstractOutline owner) {
+    super(owner);
+  }
+
+  @Override
+  public void execInitTree(TreeInitTreeChain chain) {
+    super.execInitTree(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformOutline(getOwner());
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageExtension.java
new file mode 100644
index 0000000..2ffb7db
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageExtension.java
@@ -0,0 +1,20 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.desktop.outline.pages.AbstractPageExtension;
+import org.eclipse.scout.rt.client.extension.ui.desktop.outline.pages.PageChains.PageInitPageChain;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.AbstractPage;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class PageExtension extends AbstractPageExtension<AbstractPage> {
+
+  public PageExtension(AbstractPage owner) {
+    super(owner);
+  }
+
+  @Override
+  public void execInitPage(PageInitPageChain chain) {
+    super.execInitPage(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().transformPage(getOwner());
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageWithTableExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageWithTableExtension.java
new file mode 100644
index 0000000..20a7705
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/PageWithTableExtension.java
@@ -0,0 +1,21 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.extension.ui.desktop.outline.pages.AbstractPageWithTableExtension;
+import org.eclipse.scout.rt.client.extension.ui.desktop.outline.pages.PageWithTableChains.PageWithTableInitSearchFormChain;
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.outline.pages.AbstractPageWithTable;
+import org.eclipse.scout.rt.platform.BEANS;
+
+public class PageWithTableExtension extends AbstractPageWithTableExtension<ITable, AbstractPageWithTable<ITable>> {
+
+  public PageWithTableExtension(AbstractPageWithTable<ITable> owner) {
+    super(owner);
+  }
+
+  @Override
+  public void execInitSearchForm(PageWithTableInitSearchFormChain<? extends ITable> chain) {
+    super.execInitSearchForm(chain);
+    BEANS.get(IDeviceTransformationService.class).getDeviceTransformer().notifyPageSearchFormInit(getOwner());
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TabletDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TabletDeviceTransformer.java
new file mode 100644
index 0000000..56d1bab
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TabletDeviceTransformer.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.ui.basic.tree.ITree;
+import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
+
+/**
+ * @since 3.9.0
+ */
+@Order(5300)
+public class TabletDeviceTransformer extends AbstractDeviceTransformer {
+
+  @Override
+  public boolean isActive() {
+    return UserAgentUtility.isTabletDevice();
+  }
+
+  @Override
+  public void transformDesktop() {
+    getDesktop().setCacheSplitterPosition(false);
+  }
+
+  @Override
+  public void transformOutline(IOutline outline) {
+    outline.setDisplayStyle(ITree.DISPLAY_STYLE_BREADCRUMB);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TouchDeviceTransformer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TouchDeviceTransformer.java
new file mode 100644
index 0000000..18bd30f
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/transformation/TouchDeviceTransformer.java
@@ -0,0 +1,22 @@
+package org.eclipse.scout.rt.client.transformation;
+
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
+import org.eclipse.scout.rt.client.ui.form.fields.smartfield.IProposalField;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
+
+@Order(5100)
+public class TouchDeviceTransformer extends AbstractDeviceTransformer {
+
+  @Override
+  public boolean isActive() {
+    return UserAgentUtility.isTouchDevice();
+  }
+
+  @Override
+  public void transformFormField(IFormField field) {
+    if (field instanceof IProposalField<?>) {
+      ((IProposalField) field).setAutoCloseChooser(false);
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/ClientUIPreferences.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/ClientUIPreferences.java
index 2a2d45b..af3c47a 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/ClientUIPreferences.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/ClientUIPreferences.java
@@ -762,7 +762,7 @@
     if (value != null) {
       try {
         StringTokenizer tok = new StringTokenizer(value, ",");
-        BoundsSpec r = new BoundsSpec(new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue(), new Integer(tok.nextToken()).intValue());
+        BoundsSpec r = new BoundsSpec(Integer.parseInt(tok.nextToken()), Integer.parseInt(tok.nextToken()), Integer.parseInt(tok.nextToken()), Integer.parseInt(tok.nextToken()));
         return r;
       }
       catch (Exception e) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/AbstractAction.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/AbstractAction.java
index 565308e..15c7c4f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/AbstractAction.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/AbstractAction.java
@@ -417,12 +417,12 @@
 
   @Override
   public double getOrder() {
-    return propertySupport.getPropertyDouble(PROP_VIEW_ORDER);
+    return propertySupport.getPropertyDouble(PROP_ORDER);
   }
 
   @Override
   public void setOrder(double order) {
-    propertySupport.setPropertyDouble(PROP_VIEW_ORDER, order);
+    propertySupport.setPropertyDouble(PROP_ORDER, order);
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/IAction.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/IAction.java
index b737e71..69259de 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/IAction.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/IAction.java
@@ -38,7 +38,7 @@
   String PROP_VISIBLE = "visible";
   String PROP_MNEMONIC = "mnemonic";
   String PROP_KEY_STROKE = "keyStroke";
-  String PROP_VIEW_ORDER = "viewOrder"; // FIXME awe: evtl. nur order renamen (gab früher probleme in CRM) --> MVI fragen
+  String PROP_ORDER = "order";
   String PROP_HORIZONTAL_ALIGNMENT = "horizontalAlignment";
   int HORIZONTAL_ALIGNMENT_LEFT = -1;
   int HORIZONTAL_ALIGNMENT_RIGHT = 1;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/keystroke/IKeyStroke.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/keystroke/IKeyStroke.java
index add528b..7e725f6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/keystroke/IKeyStroke.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/keystroke/IKeyStroke.java
@@ -50,4 +50,7 @@
   String F11 = "f11";
   String F12 = "f12";
 
+  String COMMA = "comma";
+  String POINT = "point";
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/menu/root/internal/TableContextMenu.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/menu/root/internal/TableContextMenu.java
index da4c661..0c36d9a 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/menu/root/internal/TableContextMenu.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/menu/root/internal/TableContextMenu.java
@@ -100,11 +100,13 @@
    * @param ownerValue
    */
   protected void calculateEnableState(List<? extends ITableRow> ownerValue) {
-    boolean enabled = true;
-    for (ITableRow row : ownerValue) {
-      if (!row.isEnabled()) {
-        enabled = false;
-        break;
+    boolean enabled = getContainer().isEnabled();
+    if (enabled) {
+      for (ITableRow row : ownerValue) {
+        if (!row.isEnabled()) {
+          enabled = false;
+          break;
+        }
       }
     }
     final boolean inheritedEnability = enabled;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/AbstractToolButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/AbstractToolButton.java
index 5bf45e5..08b168d 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/AbstractToolButton.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/AbstractToolButton.java
@@ -13,6 +13,7 @@
 import org.eclipse.scout.rt.client.extension.ui.action.tool.IToolButtonExtension;
 import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
 
+@SuppressWarnings("deprecation")
 public abstract class AbstractToolButton extends AbstractMenu implements IToolButton {
 
   public AbstractToolButton() {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/IToolButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/IToolButton.java
index 2a22f50..bd77bdf 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/IToolButton.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/action/tool/IToolButton.java
@@ -14,6 +14,9 @@
 
 /**
  * Interface for menus that appear in the gui as tool-button
+ * 
+ * @deprecated use {@link IMenu} instead
  */
+@Deprecated
 public interface IToolButton extends IMenu {
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/filechooser/FileChooserEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/filechooser/FileChooserEvent.java
index 8891300..3a1a586 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/filechooser/FileChooserEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/filechooser/FileChooserEvent.java
@@ -39,7 +39,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append(getClass().getSimpleName() + "[");
     // decode type
     try {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/AbstractPlanner.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/AbstractPlanner.java
index 4eda36a..78da543 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/AbstractPlanner.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/AbstractPlanner.java
@@ -130,7 +130,6 @@
   @Order(10)
   protected Set<Integer> getConfiguredAvailableDisplayModes() {
     return CollectionUtility.hashSet(
-        IPlannerDisplayMode.INTRADAY,
         IPlannerDisplayMode.DAY,
         IPlannerDisplayMode.WEEK,
         IPlannerDisplayMode.MONTH,
@@ -164,12 +163,6 @@
   }
 
   @ConfigProperty(ConfigProperty.DURATION_MINUTES)
-  @Order(120)
-  protected long getConfiguredIntradayInterval() {
-    return 1800000L;
-  }
-
-  @ConfigProperty(ConfigProperty.DURATION_MINUTES)
   @Order(125)
   protected long getConfiguredMinimumActivityDuration() {
     return 1800000L;
@@ -205,7 +198,6 @@
     Calendar to = Calendar.getInstance();
     DateUtility.truncCalendar(to);
     switch (displayMode) {
-      case IPlannerDisplayMode.INTRADAY:
       case IPlannerDisplayMode.DAY:
         to.add(Calendar.DAY_OF_WEEK, 1);
         break;
@@ -298,7 +290,6 @@
     setHeaderVisible(getConfiguredHeaderVisible());
     setSelectionMode(getConfiguredSelectionMode());
     setFirstHourOfDay(getConfiguredFirstHourOfDay());
-    setIntradayInterval(getConfiguredIntradayInterval());
     setMinimumActivityDuration(getConfiguredMinimumActivityDuration());
     setLastHourOfDay(getConfiguredLastHourOfDay());
     // menus
@@ -580,7 +571,6 @@
 
   @Override
   public void setSelectedActivityCell(Activity<RI, AI> cell) {
-//    cell = resolveActivityCell(cell);
     propertySupport.setProperty(PROP_SELECTED_ACTIVITY, cell);
   }
 
@@ -703,18 +693,6 @@
     return MenuUtility.getMenuByClass(this, menuType);
   }
 
-//  private void fireCellAction(Resource<RI> resource, Activity<RI, AI> activityCell) {
-//    // single observer
-//    try {
-//      interceptCellAction(resource, activityCell);
-//    }
-//    catch (Exception e) {
-//      BEANS.get(ExceptionHandler.class).handle(e);
-//    }
-//    PlannerEvent e = new PlannerEvent(this, PlannerEvent.TYPE_ACTIVITY_ACTION, resource, activityCell);
-//    firePlannerEventInternal(e);
-//  }
-
   private void fireResourcesInserted(List<Resource<RI>> resources) {
     PlannerEvent e = new PlannerEvent(this, PlannerEvent.TYPE_RESOURCES_INSERTED, resources);
     firePlannerEventInternal(e);
@@ -851,24 +829,6 @@
   }
 
   @Override
-  public long getIntradayInterval() {
-    return propertySupport.getPropertyInt(PROP_INTRADAY_INTERVAL);
-  }
-
-  @Override
-  public void setIntradayInterval(long millis) {
-    if (millis < 15L * 60000L || millis > 24L * 3600000L) {
-      throw new IllegalArgumentException("intradayIntervalMinutes must be between 15 minutes and 24 hours");
-    }
-    propertySupport.setPropertyLong(PROP_INTRADAY_INTERVAL, millis);
-  }
-
-  @Override
-  public void setIntradayIntervalInMinutes(long min) {
-    setIntradayInterval(min * 60000L);
-  }
-
-  @Override
   public long getMinimumActivityDuration() {
     return m_minimumActivityDuration;
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlanner.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlanner.java
index cce2e7c..241f5da 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlanner.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlanner.java
@@ -44,10 +44,6 @@
    * {@link Date}
    */
   String PROP_LAST_HOUR_OF_DAY = "lastHourOfDay";
-  /**
-   * {@link Long}
-   */
-  String PROP_INTRADAY_INTERVAL = "intradayInterval";
 
   /**
    * {@link String}
@@ -60,8 +56,7 @@
   String PROP_HEADER_VISIBLE = "headerVisible";
 
   /**
-   * {@link #INTRADAY},{@link #DAY}, {@link #WEEK}, {@link #MONTH},
-   * {@link #WORK_WEEK}
+   * {@link #DAY}, {@link #WEEK}, {@link #MONTH}, {@link #WORK_WEEK}
    */
   String PROP_DISPLAY_MODE = "displayMode";
 
@@ -151,14 +146,12 @@
   void setLastHourOfDay(int i);
 
   /**
-   * {@link #INTRADAY},{@link #DAY}, {@link #WEEK}, {@link #MONTH},
-   * {@link #WORK_WEEK}
+   * {@link #DAY}, {@link #WEEK}, {@link #MONTH}, {@link #WORK_WEEK}
    */
   int getDisplayMode();
 
   /**
-   * {@link #INTRADAY},{@link #DAY}, {@link #WEEK}, {@link #MONTH},
-   * {@link #WORK_WEEK}
+   * {@link #DAY}, {@link #WEEK}, {@link #MONTH}, {@link #WORK_WEEK}
    */
   void setDisplayMode(int mode);
 
@@ -174,15 +167,6 @@
 
   void setSelectionMode(int mode);
 
-  /**
-   * milliseconds
-   */
-  long getIntradayInterval();
-
-  void setIntradayInterval(long millis);
-
-  void setIntradayIntervalInMinutes(long minutes);
-
   long getMinimumActivityDuration();
 
   void setMinimumActivityDuration(long minDuration);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlannerDisplayMode.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlannerDisplayMode.java
index 2b5abe5..102c49a 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlannerDisplayMode.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/IPlannerDisplayMode.java
@@ -18,10 +18,6 @@
 
 public interface IPlannerDisplayMode extends ICalendarDisplayMode {
 
-  // TODO [5.2] awe: (Planner) check with BAP project if INTRADAY is still needed.
-  // If not delete the constant and also the get/setIntradayInterval methods
-  // on IPlanner.
-  int INTRADAY = 0;
   int CALENDAR_WEEK = 5;
   int YEAR = 6;
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerAdapter.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerAdapter.java
index bf69ac2..1c1b104 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerAdapter.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerAdapter.java
@@ -27,5 +27,6 @@
 
   @Override
   public void plannerChanged(PlannerEvent e) {
+    // NOP
   }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEvent.java
index b7f9c78..929d213 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEvent.java
@@ -112,7 +112,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append(getClass().getSimpleName() + "[");
     // decode type
     try {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEventBuffer.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEventBuffer.java
index 698fcf1..8061aa5 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEventBuffer.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/planner/PlannerEventBuffer.java
@@ -240,28 +240,6 @@
     return resources;
   }
 
-//  /**
-//   * If a RESOURCE_ORDER_CHANGED event happens directly after RESOURCES_INSERTED, we may removed the RESOURCE_ORDER_CHANGED event
-//   * and send the new order in the RESOURCES_INSERTED event instead.
-//   */
-//  protected void applyResourceOrderChangedToResourcesInserted(List<PlannerEvent> events) {
-//    for (int j = 0; j < events.size() - 1; j++) {
-//      int i = events.size() - 1 - j;
-//      PlannerEvent event = events.get(i);
-//
-//      if (event.getType() == PlannerEvent.TYPE_RESOURCE_ORDER_CHANGED) {
-//        PlannerEvent previous = findInsertionBeforeResourceOrderChanged(events.subList(0, i));
-//        // Check if previous is RESOURCES_INSERTED and they have the same resources
-//        if (previous != null && previous.getType() == PlannerEvent.TYPE_RESOURCES_INSERTED &&
-//            event.getResourceCount() == previous.getResourceCount() && CollectionUtility.equalsCollection(event.getResources(), previous.getResources(), false)) {
-//          // replace resources and remove RESOURCE_ORDER_CHANGED event
-//          previous.setResources(event.getResources());
-//          events.remove(i);
-//        }
-//      }
-//    }
-//  }
-
   /**
    * Finds previous RESOURCES_INSERTED event while ignoring events that don't change resource order (e.g.
    * COLUMN_HEADERS_UPDATED)
@@ -340,7 +318,6 @@
   protected List<Integer> getResourceRelatedEvents() {
     List<Integer> res = new ArrayList<>();
     res.add(PlannerEvent.TYPE_ALL_RESOURCES_DELETED);
-//    res.add(PlannerEvent.TYPE_RESOURCE_ORDER_CHANGED);
     res.add(PlannerEvent.TYPE_RESOURCES_DELETED);
     res.add(PlannerEvent.TYPE_RESOURCES_INSERTED);
     res.add(PlannerEvent.TYPE_RESOURCES_UPDATED);
@@ -359,7 +336,6 @@
    */
   protected boolean isIgnorePrevious(int type) {
     switch (type) {
-//      case PlannerEvent.TYPE_RESOURCE_ORDER_CHANGED:
       case PlannerEvent.TYPE_RESOURCES_SELECTED:
       case PlannerEvent.TYPE_ALL_RESOURCES_DELETED: {
         return true;
@@ -388,7 +364,6 @@
 
   protected boolean isResourcesRequired(int type) {
     switch (type) {
-//      case PlannerEvent.TYPE_RESOURCE_ORDER_CHANGED:
       case PlannerEvent.TYPE_RESOURCES_DELETED:
       case PlannerEvent.TYPE_RESOURCES_INSERTED:
       case PlannerEvent.TYPE_RESOURCES_UPDATED: {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/AbstractTable.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/AbstractTable.java
index a605d8b..e6a9197 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/AbstractTable.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/AbstractTable.java
@@ -55,13 +55,10 @@
 import org.eclipse.scout.rt.client.ui.IEventHistory;
 import org.eclipse.scout.rt.client.ui.MouseButton;
 import org.eclipse.scout.rt.client.ui.action.ActionUtility;
-import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.IActionVisitor;
 import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
 import org.eclipse.scout.rt.client.ui.action.keystroke.KeyStroke;
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.action.menu.MenuUtility;
-import org.eclipse.scout.rt.client.ui.action.menu.root.IContextMenu;
 import org.eclipse.scout.rt.client.ui.action.menu.root.ITableContextMenu;
 import org.eclipse.scout.rt.client.ui.action.menu.root.internal.TableContextMenu;
 import org.eclipse.scout.rt.client.ui.basic.cell.Cell;
@@ -99,7 +96,6 @@
 import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
 import org.eclipse.scout.rt.platform.classid.ITypeWithClassId;
 import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.holders.Holder;
 import org.eclipse.scout.rt.platform.html.HTML;
 import org.eclipse.scout.rt.platform.reflect.AbstractPropertyObserver;
 import org.eclipse.scout.rt.platform.reflect.ConfigurationUtility;
@@ -449,27 +445,6 @@
   }
 
   /**
-   * Configures the row height hint. This is a hint for the UI if and only if it is not capable of having variable table
-   * row height based on cell contents.
-   * <p>
-   * This property is interpreted in different manner for each GUI port:
-   * <ul>
-   * <li>Swing: The property is ignored.
-   * </ul>
-   * This hint defines the table row height in pixels being used as the fixed row height for all table rows of this
-   * table.
-   * </p>
-   * Subclasses can override this method. Default is {@code -1}.
-   *
-   * @return Table row height hint in pixels.
-   */
-  @ConfigProperty(ConfigProperty.INTEGER)
-  @Order(92)
-  protected int getConfiguredRowHeightHint() {
-    return -1;
-  }
-
-  /**
    * Configures whether the table is checkable.
    * <p>
    * Subclasses can override this method. Default is {@code false}.
@@ -886,7 +861,6 @@
     setMultiSelect(getConfiguredMultiSelect());
     setInitialMultilineText(getConfiguredMultilineText());
     setMultilineText(getConfiguredMultilineText());
-    setRowHeightHint(getConfiguredRowHeightHint());
     setKeyboardNavigation(getConfiguredKeyboardNavigation());
     setDragType(getConfiguredDragType());
     setDropType(getConfiguredDropType());
@@ -1048,7 +1022,6 @@
     ActionUtility.disposeActions(getMenus());
   }
 
-  // FIXME awe, mvi: make TableControls extensible, check copy/paste code in this class
   private void createTableControlsInternal() {
     List<Class<? extends ITableControl>> tcs = getConfiguredTableControls();
     OrderedCollection<ITableControl> tableControls = new OrderedCollection<ITableControl>();
@@ -1489,16 +1462,6 @@
   }
 
   @Override
-  public int getRowHeightHint() {
-    return propertySupport.getPropertyInt(PROP_ROW_HEIGHT_HINT);
-  }
-
-  @Override
-  public void setRowHeightHint(int h) {
-    propertySupport.setPropertyInt(PROP_ROW_HEIGHT_HINT, h);
-  }
-
-  @Override
   public boolean isInitialMultilineText() {
     return m_initialMultiLineText;
   }
@@ -1839,24 +1802,7 @@
   @Deprecated
   @Override
   public <T extends IMenu> T getMenu(final Class<T> menuType) {
-    IContextMenu contextMenu = getContextMenu();
-    if (contextMenu != null) {
-      final Holder<T> resultHolder = new Holder<T>();
-      contextMenu.acceptVisitor(new IActionVisitor() {
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public int visit(IAction action) {
-          if (menuType.isAssignableFrom(action.getClass())) {
-            resultHolder.setValue((T) action);
-            return CANCEL;
-          }
-          return CONTINUE;
-        }
-      });
-      return resultHolder.getValue();
-    }
-    return null;
+    return getMenuByClass(menuType);
   }
 
   @Override
@@ -3392,12 +3338,16 @@
         // This is to support reverse (implicit) sorting of columns, meaning that multiple column sort is done
         // without CTRL-key held. In contrast to explicit multiple column sort, the first clicked column
         // is the least significant sort column.
-        List<IColumn<?>> sortCols = getColumnSet().getSortColumns();
+        LinkedHashSet<IColumn<?>> sortCols = new LinkedHashSet<>(getColumnSet().getSortColumns());
         if (!sortCols.isEmpty() && !getRows().isEmpty()) {
+          // add all visible columns (not already added, thus LinkedHashSet)
+          // as fallback sorting to guarantee same sorting as in JS.
+          sortCols.addAll(getColumnSet().getVisibleColumns());
+
           // first make sure decorations and lookups are up-to-date
           processDecorationBuffer();
           List<ITableRow> a = new ArrayList<ITableRow>(getRows());
-          Collections.sort(a, new TableRowComparator(sortCols));
+          Collections.sort(a, new TableRowComparator(new ArrayList<>(sortCols)));
           sortInternal(a);
         }
       }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ColumnSet.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ColumnSet.java
index 4ef5617..e5b3236 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ColumnSet.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ColumnSet.java
@@ -1461,7 +1461,7 @@
       if (IColumn.PROP_VIEW_COLUMN_INDEX_HINT.equals(e.getPropertyName())) {
         return;
       }
-      if (IColumn.PROP_VIEW_ORDER.equals(e.getPropertyName())) {
+      if (IColumn.PROP_ORDER.equals(e.getPropertyName())) {
         resetColumnsViewOrder();
         return;
       }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/HeaderCell.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/HeaderCell.java
index 65cda70..3e88aea 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/HeaderCell.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/HeaderCell.java
@@ -34,9 +34,6 @@
   private String m_backgroundColor;
   private FontSpec m_font;
 
-  public HeaderCell() {
-  }
-
   @Override
   public int getColumnIndex() {
     return m_columnIndex;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ITable.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ITable.java
index 26937b2..f3120ce 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ITable.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/ITable.java
@@ -78,10 +78,6 @@
    * Boolean
    */
   String PROP_MULTILINE_TEXT = "multilineText";
-  /**
-   * Integer default -1
-   */
-  String PROP_ROW_HEIGHT_HINT = "rowHeightHint";
 
   /**
    * Boolean
@@ -464,28 +460,6 @@
   void setMultilineText(boolean on);
 
   /**
-   * This is a hint for the UI iff it is not capable of having variable table row height based on cell contents.
-   * <p>
-   * This property is interpreted in different manner for each GUI port:
-   * <ul>
-   * <li>Swing: The property is ignored.
-   * </ul>
-   * </p>
-   * <p>
-   * This hint defines the table row height in pixels being used as the row height for all table rows of this table
-   * dependent of the GUI port.
-   * </p>
-   *
-   * @return the hint in pixels, default is -1
-   */
-  int getRowHeightHint();
-
-  /**
-   * see {@link #getRowHeightHint()}
-   */
-  void setRowHeightHint(int h);
-
-  /**
    * other than isMultilineText this property reflects the default multiLine state of the table that is used when
    * wrapping columns become visible or get hidden
    */
@@ -1102,11 +1076,11 @@
    * The reload handler is triggered when the user uses the ui tools to reload the table (reload button, reload
    * keystroke).
    * <p>
-   * The existence of a reload handler controls the availability of these tools, meaning if no reload handler is set
-   * the user may not reload the table.
+   * The existence of a reload handler controls the availability of these tools, meaning if no reload handler is set the
+   * user may not reload the table.
    * <p>
    * Default is null.
-   * 
+   *
    * @since 5.1.0
    */
   IReloadHandler getReloadHandler();
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableRowComparator.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableRowComparator.java
index 81fc433..b5a23fd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableRowComparator.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableRowComparator.java
@@ -29,9 +29,12 @@
   public int compare(ITableRow row1, ITableRow row2) {
     for (IColumn col : m_columns) {
       int c = col.compareTableRows(row1, row2);
-      if (!col.getHeaderCell().isSortAscending()) {
+      if (col.isSortActive() && !col.getHeaderCell().isSortAscending()) {
+        // only consider sortAscending flag when sort is active
+        // columns with !sortActive are always sorted ascending (sortAscending represents last state for those, thus not considered)
         c = -c;
       }
+
       if (c != 0) {
         return c;
       }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableUtility.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableUtility.java
index e8a52ee..793b2ca 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableUtility.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/TableUtility.java
@@ -141,7 +141,7 @@
         cell.setText(result.get(0).getText());
       }
       else if (result.size() > 1) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < result.size(); i++) {
           if (i > 0) {
             if (multilineText) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractColumn.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractColumn.java
index 4c8ff73..4f37cb2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractColumn.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/AbstractColumn.java
@@ -1713,12 +1713,12 @@
 
   @Override
   public double getOrder() {
-    return propertySupport.getPropertyDouble(PROP_VIEW_ORDER);
+    return propertySupport.getPropertyDouble(PROP_ORDER);
   }
 
   @Override
   public void setOrder(double order) {
-    propertySupport.setPropertyDouble(PROP_VIEW_ORDER, order);
+    propertySupport.setPropertyDouble(PROP_ORDER, order);
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/IColumn.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/IColumn.java
index afc671f..a8f057b 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/IColumn.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/columns/IColumn.java
@@ -77,7 +77,7 @@
 
   String PROP_EDITABLE = "editable";
 
-  String PROP_VIEW_ORDER = "viewOrder";
+  String PROP_ORDER = "order";
 
   /**
    * type boolean
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractFormTableControl.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractFormTableControl.java
new file mode 100644
index 0000000..cff68d7
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractFormTableControl.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.ui.basic.table.controls;
+
+import java.util.List;
+
+import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
+import org.eclipse.scout.rt.client.extension.ui.basic.table.controls.IFormTableControlExtension;
+import org.eclipse.scout.rt.client.extension.ui.basic.table.controls.FormTableControlChains.TableControlInitFormChain;
+import org.eclipse.scout.rt.client.ui.action.AbstractAction;
+import org.eclipse.scout.rt.client.ui.form.FormEvent;
+import org.eclipse.scout.rt.client.ui.form.FormListener;
+import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.platform.annotations.ConfigOperation;
+import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
+import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
+
+/**
+ * @since 6.0
+ */
+public abstract class AbstractFormTableControl extends AbstractTableControl implements IFormTableControl {
+
+  public AbstractFormTableControl() {
+    this(true);
+  }
+
+  public AbstractFormTableControl(boolean callInitializer) {
+    if (callInitializer) {
+      callInitializer();
+    }
+  }
+
+  /**
+   * Configures the form to be used with this control. The form is lazily created and started when the control gets
+   * selected.
+   * <p>
+   * Subclasses can override this method. Default is {@code null}.
+   *
+   * @return a form type token
+   * @see {@link #startForm(IForm)} for details how the form gets started
+   */
+  @ConfigProperty(ConfigProperty.FORM)
+  @Order(90)
+  protected Class<? extends IForm> getConfiguredForm() {
+    return null;
+  }
+
+  /**
+   * Initializes the form associated with this button. This method is called before the form is used for the first time.
+   * <p>
+   * Subclasses can override this method. The default does nothing.
+   */
+  @ConfigOperation
+  @Order(120)
+  protected void execInitForm() {
+  }
+
+  protected IForm createForm() {
+    if (getConfiguredForm() == null) {
+      return null;
+    }
+    try {
+      return getConfiguredForm().newInstance();
+    }
+    catch (Exception e) {
+      BEANS.get(ExceptionHandler.class).handle(new ProcessingException("error creating instance of class '" + getConfiguredForm().getName() + "'.", e));
+    }
+    return null;
+  }
+
+  /**
+   * Starts the form.
+   * <p>
+   * The default uses {@link IForm#start()} and therefore expects a form handler to be previously set. Override to call
+   * a custom start method or implement a {@link IForm#start()} on the detail form.
+   */
+  protected void startForm() {
+    getForm().start();
+  }
+
+  @Override
+  public void setForm(IForm form) {
+    propertySupport.setProperty(PROP_FORM, form);
+  }
+
+  @Override
+  public final IForm getForm() {
+    return (IForm) propertySupport.getProperty(PROP_FORM);
+  }
+
+  @Override
+  protected void execSelectionChanged(boolean selected) {
+    super.execSelectionChanged(selected);
+    ensureFormCreated();
+    ensureFormStarted();
+  }
+
+  public void ensureFormCreated() {
+    if (getForm() != null) {
+      return;
+    }
+    IForm form = createForm();
+    if (form != null) {
+      form.addFormListener(new FormListener() {
+        @Override
+        public void formChanged(FormEvent e) {
+          if (e.getType() == FormEvent.TYPE_CLOSED) {
+            setSelected(false);
+            setForm(null);
+          }
+        }
+      });
+      setForm(form);
+      decorateForm();
+      interceptInitForm();
+    }
+  }
+
+  public void ensureFormStarted() {
+    if (getForm() == null || !getForm().isFormStartable()) {
+      return;
+    }
+    startForm();
+  }
+
+  public void decorateForm() {
+    getForm().setShowOnStart(false);
+  }
+
+  @Override
+  protected IActionExtension<? extends AbstractAction> createLocalExtension() {
+    return new LocalTableControlExtension<AbstractFormTableControl>(this);
+  }
+
+  protected final void interceptInitForm() {
+    List<? extends IActionExtension<? extends AbstractAction>> extensions = getAllExtensions();
+    TableControlInitFormChain chain = new TableControlInitFormChain(extensions);
+    chain.execInitForm();
+  }
+
+  /**
+   * The extension delegating to the local methods. This Extension is always at the end of the chain and will not call
+   * any further chain elements.
+   */
+  protected static class LocalTableControlExtension<OWNER extends AbstractFormTableControl> extends AbstractAction.LocalActionExtension<OWNER> implements IFormTableControlExtension<OWNER> {
+
+    public LocalTableControlExtension(OWNER owner) {
+      super(owner);
+    }
+
+    @Override
+    public void execInitForm(TableControlInitFormChain chain) {
+      getOwner().execInitForm();
+    }
+
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractTableControl.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractTableControl.java
index c2d15c3..7cbd8e4 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractTableControl.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/AbstractTableControl.java
@@ -10,22 +10,8 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.ui.basic.table.controls;
 
-import java.util.List;
-
-import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
-import org.eclipse.scout.rt.client.extension.ui.basic.table.control.ITableControlExtension;
-import org.eclipse.scout.rt.client.extension.ui.basic.table.control.TableControlChains.TableControlInitFormChain;
 import org.eclipse.scout.rt.client.ui.action.AbstractAction;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
-import org.eclipse.scout.rt.client.ui.form.FormEvent;
-import org.eclipse.scout.rt.client.ui.form.FormListener;
-import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.annotations.ConfigOperation;
-import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.exception.ProcessingException;
 
 /**
  * @since 5.1.0
@@ -48,69 +34,16 @@
     return true;
   }
 
-  /**
-   * Configures the form to be used with this control. The form is lazily created and started when the control gets
-   * selected.
-   * <p>
-   * Subclasses can override this method. Default is {@code null}.
-   *
-   * @return a form type token
-   * @see {@link #startForm(IForm)} for details how the form gets started
-   */
-  @ConfigProperty(ConfigProperty.FORM)
-  @Order(90)
-  protected Class<? extends IForm> getConfiguredForm() {
-    return null;
-  }
-
-  /**
-   * Initializes the form associated with this button. This method is called before the form is used for the first time.
-   * <p>
-   * Subclasses can override this method. The default does nothing.
-   */
-  @ConfigOperation
-  @Order(120)
-  protected void execInitForm() {
-  }
-
-  protected IForm createForm() {
-    if (getConfiguredForm() == null) {
-      return null;
-    }
-    try {
-      return getConfiguredForm().newInstance();
-    }
-    catch (Exception e) {
-      BEANS.get(ExceptionHandler.class).handle(new ProcessingException("error creating instance of class '" + getConfiguredForm().getName() + "'.", e));
-    }
-    return null;
-  }
-
-  /**
-   * Starts the form.
-   * <p>
-   * The default uses {@link IForm#start()} and therefore expects a form handler to be previously set. Override to call
-   * a custom start method or implement a {@link IForm#start()} on the detail form.
-   */
-  protected void startForm() {
-    getForm().start();
-  }
-
-  @Override
-  public void setForm(IForm form) {
-    propertySupport.setProperty(PROP_FORM, form);
-  }
-
-  @Override
-  public final IForm getForm() {
-    return (IForm) propertySupport.getProperty(PROP_FORM);
-  }
-
   public void setTable(ITable table) {
     m_table = table;
   }
 
   @Override
+  public ITable getTable() {
+    return m_table;
+  }
+
+  @Override
   protected void execSelectionChanged(boolean selected) {
     if (!selected) {
       return;
@@ -121,67 +54,6 @@
         control.setSelected(false);
       }
     }
-    ensureFormCreated();
-    ensureFormStarted();
   }
 
-  public void ensureFormCreated() {
-    if (getForm() != null) {
-      return;
-    }
-    IForm form = createForm();
-    if (form != null) {
-      form.addFormListener(new FormListener() {
-        @Override
-        public void formChanged(FormEvent e) {
-          if (e.getType() == FormEvent.TYPE_CLOSED) {
-            setSelected(false);
-            setForm(null);
-          }
-        }
-      });
-      setForm(form);
-      decorateForm();
-      interceptInitForm();
-    }
-  }
-
-  public void ensureFormStarted() {
-    if (getForm() == null || !getForm().isFormStartable()) {
-      return;
-    }
-    startForm();
-  }
-
-  public void decorateForm() {
-    getForm().setShowOnStart(false);
-  }
-
-  @Override
-  protected IActionExtension<? extends AbstractAction> createLocalExtension() {
-    return new LocalTableControlExtension<AbstractTableControl>(this);
-  }
-
-  protected final void interceptInitForm() {
-    List<? extends IActionExtension<? extends AbstractAction>> extensions = getAllExtensions();
-    TableControlInitFormChain chain = new TableControlInitFormChain(extensions);
-    chain.execInitForm();
-  }
-
-  /**
-   * The extension delegating to the local methods. This Extension is always at the end of the chain and will not call
-   * any further chain elements.
-   */
-  protected static class LocalTableControlExtension<OWNER extends AbstractTableControl> extends AbstractAction.LocalActionExtension<OWNER> implements ITableControlExtension<OWNER> {
-
-    public LocalTableControlExtension(OWNER owner) {
-      super(owner);
-    }
-
-    @Override
-    public void execInitForm(TableControlInitFormChain chain) {
-      getOwner().execInitForm();
-    }
-
-  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/IFormTableControl.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/IFormTableControl.java
new file mode 100644
index 0000000..90cdd8a
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/IFormTableControl.java
@@ -0,0 +1,12 @@
+package org.eclipse.scout.rt.client.ui.basic.table.controls;
+
+import org.eclipse.scout.rt.client.ui.form.IForm;
+
+public interface IFormTableControl extends ITableControl {
+
+  String PROP_FORM = "form";
+
+  void setForm(IForm form);
+
+  IForm getForm();
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/ITableControl.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/ITableControl.java
index 123accc..b3c50da 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/ITableControl.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/ITableControl.java
@@ -11,17 +11,15 @@
 package org.eclipse.scout.rt.client.ui.basic.table.controls;
 
 import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 
 /**
  * @since 5.1.0
  */
 public interface ITableControl extends IAction {
 
-  String PROP_FORM = "form";
-
-  void setForm(IForm form);
-
-  IForm getForm();
-
+  /**
+   * @return associated {@link ITable}
+   */
+  ITable getTable();
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/SearchFormTableControl.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/SearchFormTableControl.java
index 632df9f..db0e609 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/SearchFormTableControl.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/controls/SearchFormTableControl.java
@@ -18,7 +18,7 @@
 /**
  * @since 5.1.0
  */
-public class SearchFormTableControl extends AbstractTableControl {
+public class SearchFormTableControl extends AbstractFormTableControl {
 
   @Override
   protected void initConfig() {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/menus/OrganizeColumnsMenu.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/menus/OrganizeColumnsMenu.java
index 7b302e5..74d788d 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/menus/OrganizeColumnsMenu.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/table/menus/OrganizeColumnsMenu.java
@@ -17,14 +17,13 @@
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.basic.table.organizer.IOrganizeColumnsForm;
 import org.eclipse.scout.rt.client.ui.basic.table.organizer.IOrganizeColumnsFormProvider;
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Platform;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.eclipse.scout.rt.shared.AbstractIcons;
 import org.eclipse.scout.rt.shared.TEXTS;
 
-public class OrganizeColumnsMenu extends AbstractFormToolButton<IOrganizeColumnsForm> {
+public class OrganizeColumnsMenu extends AbstractFormMenu<IOrganizeColumnsForm> {
   private final ITable m_table;
 
   public OrganizeColumnsMenu(ITable table) {
@@ -69,16 +68,6 @@
   }
 
   /**
-   * Whether or not development menus must be displayed (copy columns width).
-   *
-   * @return
-   */
-  public boolean isDevelopment() {
-    // FIXME awe, cgu: (dev-mode) send this flag with JsonSession - global
-    return Platform.get().inDevelopmentMode();
-  }
-
-  /**
    * Whether or not new, delete or modify menus for custom columns must be displayed.
    *
    * @return
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTree.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTree.java
index 453a9a9..d52b334 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTree.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTree.java
@@ -43,7 +43,6 @@
 import org.eclipse.scout.rt.client.ui.AbstractEventBuffer;
 import org.eclipse.scout.rt.client.ui.IEventHistory;
 import org.eclipse.scout.rt.client.ui.MouseButton;
-import org.eclipse.scout.rt.client.ui.action.ActionFinder;
 import org.eclipse.scout.rt.client.ui.action.ActionUtility;
 import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
 import org.eclipse.scout.rt.client.ui.action.keystroke.KeyStroke;
@@ -87,7 +86,7 @@
   private ITreeUIFacade m_uiFacade;
   private boolean m_initialized;
 
-  // enabled is defined as: enabledGranted && enabledProperty && enabledSlave
+  // enabled is defined as: enabledGranted && enabledProperty && enabledSlave // NOSONAR
   private boolean m_enabledGranted;
   private boolean m_enabledProperty;
 
@@ -322,17 +321,11 @@
   }
 
   /**
-   * Moved from AbstractTreeBox to AbstractTree Checks / unchecks all visible child nodes if the parent node gets
-   * checked / unchecked.
+   * Checks / unchecks all visible child nodes if the parent node gets checked / unchecked.
    * <p>
-   * Makes only sense if
+   * Only has an effect if the tree is checkable.
    *
-   * <pre>
-   * {@link #getConfiguredCheckable()}
-   * </pre>
-   *
-   * is set to true.
-   *
+   * @see {@link #getConfiguredCheckable()}
    * @since 5.1
    */
   @ConfigProperty(ConfigProperty.BOOLEAN)
@@ -341,6 +334,55 @@
     return false;
   }
 
+  /**
+   * Configures whether it should be possible that child nodes may added lazily to the tree when expanding the node.
+   * This property controls whether the feature is available at all. If set to true you need to define which nodes are
+   * affected by using {@link ITreeNode#setLazyExpandingEnabled(boolean)}
+   * <p>
+   * Subclasses can override this method. Default is {@code true}.
+   *
+   * @see ITreeNode#isLazyExpandingEnabled()
+   * @see ITreeNode#isExpandedLazy()
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(110)
+  protected boolean getConfiguredLazyExpandingEnabled() {
+    return true;
+  }
+
+  /**
+   * Configures the display style of the tree.
+   * <p>
+   * The available styles are:
+   * <ul>
+   * <li>{@link ITree#DISPLAY_STYLE_DEFAULT}</li>
+   * <li>{@link ITree#DISPLAY_STYLE_BREADCRUMB}</li>
+   * </ul>
+   * <p>
+   * Subclasses can override this method. The default is {@link ITree#DISPLAY_STYLE_DEFAULT}.
+   *
+   * @see #getConfiguredAutoToggleBreadcrumbStyle()
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(140)
+  protected String getConfiguredDisplayStyle() {
+    return DISPLAY_STYLE_DEFAULT;
+  }
+
+  /**
+   * Configures whether the outline should automatically switch to the bread crumb style when getting smaller and back
+   * when getting bigger. The threshold is determined by the GUI.
+   * <p>
+   * Subclasses can override this method. The default is false.
+   *
+   * @see #getConfiguredDisplayStyle()
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(145)
+  protected boolean getConfiguredAutoToggleBreadcrumbStyle() {
+    return false;
+  }
+
   private List<Class<? extends IKeyStroke>> getConfiguredKeyStrokes() {
     Class<?>[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
     List<Class<IKeyStroke>> fca = ConfigurationUtility.filterClasses(dca, IKeyStroke.class);
@@ -544,6 +586,9 @@
     setScrollToSelection(getConfiguredScrollToSelection());
     setSaveAndRestoreScrollbars(getConfiguredSaveAndRestoreScrollbars());
     setAutoCheckChildNodes(getConfiguredAutoCheckChildNodes());
+    setLazyExpandingEnabled(getConfiguredLazyExpandingEnabled());
+    setDisplayStyle(getConfiguredDisplayStyle());
+    setAutoToggleBreadcrumbStyle(getConfiguredAutoToggleBreadcrumbStyle());
     setRootNode(new AbstractTreeNode() {
     });
     // add Convenience observer for drag & drop callbacks and event history
@@ -739,8 +784,7 @@
   @Deprecated
   @Override
   public <T extends IMenu> T getMenu(Class<T> menuType) {
-    // ActionFinder performs instance-of checks. Hence the menu replacement mapping is not required
-    return new ActionFinder().findAction(getMenus(), menuType);
+    return getMenuByClass(menuType);
   }
 
   @Override
@@ -997,6 +1041,36 @@
   }
 
   @Override
+  public boolean isLazyExpandingEnabled() {
+    return propertySupport.getPropertyBool(PROP_LAZY_EXPANDING_ENABLED);
+  }
+
+  @Override
+  public void setLazyExpandingEnabled(boolean lazyExpandingEnabled) {
+    propertySupport.setPropertyBool(PROP_LAZY_EXPANDING_ENABLED, lazyExpandingEnabled);
+  }
+
+  @Override
+  public String getDisplayStyle() {
+    return propertySupport.getPropertyString(PROP_DISPLAY_STYLE);
+  }
+
+  @Override
+  public void setDisplayStyle(String style) {
+    propertySupport.setPropertyString(PROP_DISPLAY_STYLE, style);
+  }
+
+  @Override
+  public boolean isAutoToggleBreadcrumbStyle() {
+    return propertySupport.getPropertyBool(PROP_AUTO_TOGGLE_BREADCRUMB_STYLE);
+  }
+
+  @Override
+  public void setAutoToggleBreadcrumbStyle(boolean b) {
+    propertySupport.setPropertyBool(PROP_AUTO_TOGGLE_BREADCRUMB_STYLE, b);
+  }
+
+  @Override
   public String getPathText(ITreeNode selectedNode) {
     return getPathText(selectedNode, " - ");
   }
@@ -1005,7 +1079,7 @@
   public String getPathText(ITreeNode selectedNode, String delimiter) {
     // construct the path to the data
     ITreeNode root = getRootNode();
-    StringBuffer pathStr = new StringBuffer("");
+    StringBuilder pathStr = new StringBuilder("");
     ITreeNode node = selectedNode;
     while (node != null) {
       if (node != root || isRootNodeVisible()) {
@@ -1151,6 +1225,11 @@
 
   @Override
   public void setNodeExpanded(ITreeNode node, boolean b, boolean lazy) {
+    // Never do lazy expansion if it is disabled on the tree
+    if (!isLazyExpandingEnabled()) {
+      lazy = false;
+    }
+
     node = resolveNode(node);
     if (node != null) {
       if (node.isExpanded() != b || node.isExpandedLazy() != lazy) {
@@ -1794,33 +1873,12 @@
 
   @Override
   public boolean visitTree(ITreeVisitor v) {
-    return visitNodeRec(getRootNode(), v);
+    return TreeUtility.visitNodeRec(getRootNode(), v);
   }
 
   @Override
   public boolean visitNode(ITreeNode node, ITreeVisitor v) {
-    return visitNodeRec(node, v);
-  }
-
-  private boolean visitNodeRec(ITreeNode node, ITreeVisitor v) {
-    if (node == null) {
-      return true;
-    }
-    boolean b = v.visit(node);
-    if (!b) {
-      return b;
-    }
-    List<ITreeNode> a = node.getChildNodes();
-    for (ITreeNode childNode : a) {
-      // it might be that the visit of a node detached the node from the tree
-      if (childNode.getTree() != null) {
-        b = visitNodeRec(childNode, v);
-        if (!b) {
-          return b;
-        }
-      }
-    }
-    return true;
+    return TreeUtility.visitNode(node, v);
   }
 
   @Override
@@ -3100,6 +3158,11 @@
       }
     }
 
+    @Override
+    public void setDisplayStyleFromUI(String style) {
+      setDisplayStyle(style);
+    }
+
   }// end private class
 
   /**
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTreeNode.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTreeNode.java
index 27269e9..b81d3dd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTreeNode.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/AbstractTreeNode.java
@@ -571,7 +571,7 @@
 
     // Also set state of expandedLazy as well -> if lazy expanding gets disabled, it is not expected that expandedLazy is still set to true
     // See also Tree.js _applyUpdatedNodeProperties
-    m_expandedLazy = lazyExpandingEnabled;
+    m_expandedLazy = lazyExpandingEnabled && getTree() != null && getTree().isLazyExpandingEnabled();
 
     boolean changed = lazyExpandingEnabled != m_lazyExpandingEnabled;
     if (changed && getTree() != null) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITree.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITree.java
index 3230309..1b82d35 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITree.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITree.java
@@ -43,6 +43,7 @@
   String PROP_MULTI_CHECK = "multiCheck";
   String PROP_CHECKABLE = "checkable";
   String PROP_AUTO_CHECK_CHILDREN = "autoCheckChildren";
+  String PROP_LAZY_EXPANDING_ENABLED = "lazyExpandingEnabled";
   /**
    * Integer default -1
    */
@@ -51,6 +52,12 @@
   String PROP_ROOT_HANDLES_VISIBLE = "rootHandlesVisible";
   String PROP_KEY_STROKES = "keyStrokes";
   String PROP_SCROLL_TO_SELECTION = "scrollToSelection";
+  String PROP_DISPLAY_STYLE = "displayStyle";
+  String PROP_AUTO_TOGGLE_BREADCRUMB_STYLE = "autoToggleBreadcrumbStyle";
+
+  String DISPLAY_STYLE_DEFAULT = "default";
+  String DISPLAY_STYLE_BREADCRUMB = "breadcrumb";
+
   /**
    * Object
    * <p>
@@ -224,6 +231,10 @@
 
   void setEnabledPermission(Permission p);
 
+  boolean isLazyExpandingEnabled();
+
+  void setLazyExpandingEnabled(boolean lazyExpandingEnabled);
+
   int getSelectedNodeCount();
 
   ITreeNode getSelectedNode();
@@ -531,6 +542,17 @@
    */
   void setSaveAndRestoreScrollbars(boolean b);
 
+  String getDisplayStyle();
+
+  /**
+   * @see {@link #DISPLAY_STYLE_DEFAULT}, {@link #DISPLAY_STYLE_BREADCRUMB}
+   */
+  void setDisplayStyle(String style);
+
+  boolean isAutoToggleBreadcrumbStyle();
+
+  void setAutoToggleBreadcrumbStyle(boolean b);
+
   /**
    * informs the attached UI that a node has changed in a way that may affect its presentation (e.g. text, font,
    * color...) but no structural changes occurred
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITreeUIFacade.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITreeUIFacade.java
index 2183d04..610ff7b 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITreeUIFacade.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/ITreeUIFacade.java
@@ -56,4 +56,6 @@
   void fireNodeDropTargetChangedFromUI(ITreeNode node);
 
   void fireAppLinkActionFromUI(String ref);
+
+  void setDisplayStyleFromUI(String style);
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeEvent.java
index 7397939..1f41010 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeEvent.java
@@ -327,7 +327,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append(getClass().getSimpleName() + "[");
     buf.append(getTypeName());
     // nodes
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeUtility.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeUtility.java
index 8205716..8762df3 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeUtility.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/tree/TreeUtility.java
@@ -134,4 +134,35 @@
     }
     return node;
   }
+
+  public static void visitNodes(Collection<ITreeNode> nodes, ITreeVisitor v) {
+    for (ITreeNode node : nodes) {
+      visitNode(node, v);
+    }
+  }
+
+  public static boolean visitNode(ITreeNode node, ITreeVisitor v) {
+    return visitNodeRec(node, v);
+  }
+
+  public static boolean visitNodeRec(ITreeNode node, ITreeVisitor v) {
+    if (node == null) {
+      return true;
+    }
+    boolean b = v.visit(node);
+    if (!b) {
+      return b;
+    }
+    List<ITreeNode> a = node.getChildNodes();
+    for (ITreeNode childNode : a) {
+      // it might be that the visit of a node detached the node from the tree
+      if (childNode.getTree() != null) {
+        b = visitNodeRec(childNode, v);
+        if (!b) {
+          return b;
+        }
+      }
+    }
+    return true;
+  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/userfilter/AbstractUserFilterState.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/userfilter/AbstractUserFilterState.java
index 9884dae..10a9674 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/userfilter/AbstractUserFilterState.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/basic/userfilter/AbstractUserFilterState.java
@@ -15,7 +15,7 @@
 /**
  * @since 5.1
  */
-public class AbstractUserFilterState implements IUserFilterState {
+public abstract class AbstractUserFilterState implements IUserFilterState {
   private static final long serialVersionUID = 1L;
   private String m_type;
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktop.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktop.java
index 244da29..07bdcf2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktop.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktop.java
@@ -28,10 +28,12 @@
 import org.eclipse.scout.rt.client.ModelContextProxy;
 import org.eclipse.scout.rt.client.ModelContextProxy.ModelContext;
 import org.eclipse.scout.rt.client.context.ClientRunContexts;
-import org.eclipse.scout.rt.client.extension.ui.action.tree.MoveActionNodesHandler;
-import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopAddTrayMenusChain;
+import org.eclipse.scout.rt.client.deeplink.DeepLinkException;
+import org.eclipse.scout.rt.client.deeplink.IDeepLinks;
+import org.eclipse.scout.rt.client.deeplink.OutlineDeepLinkHandler;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopBeforeClosingChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopClosingChain;
+import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopDefaultViewChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopFormAboutToShowChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiAttachedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopGuiDetachedChain;
@@ -43,7 +45,9 @@
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopPageSearchFormChangedChain;
 import org.eclipse.scout.rt.client.extension.ui.desktop.DesktopChains.DesktopTablePageLoadedChain;
 import org.eclipse.scout.rt.client.services.common.bookmark.internal.BookmarkUtility;
+import org.eclipse.scout.rt.client.services.common.icon.IIconProviderService;
 import org.eclipse.scout.rt.client.session.ClientSessionProvider;
+import org.eclipse.scout.rt.client.transformation.IDeviceTransformationService;
 import org.eclipse.scout.rt.client.ui.DataChangeListener;
 import org.eclipse.scout.rt.client.ui.IDisplayParent;
 import org.eclipse.scout.rt.client.ui.action.ActionFinder;
@@ -60,16 +64,17 @@
 import org.eclipse.scout.rt.client.ui.basic.tree.TreeEvent;
 import org.eclipse.scout.rt.client.ui.desktop.notification.IDesktopNotification;
 import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractOutlineViewButton;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.ISearchForm;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 import org.eclipse.scout.rt.client.ui.form.IFormHandler;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 import org.eclipse.scout.rt.client.ui.form.fields.button.IButton;
 import org.eclipse.scout.rt.client.ui.messagebox.IMessageBox;
+import org.eclipse.scout.rt.client.ui.messagebox.MessageBoxes;
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.Order;
 import org.eclipse.scout.rt.platform.OrderedComparator;
@@ -86,8 +91,10 @@
 import org.eclipse.scout.rt.platform.util.Assertions;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.eclipse.scout.rt.platform.util.EventListenerList;
+import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
 import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
+import org.eclipse.scout.rt.shared.TEXTS;
 import org.eclipse.scout.rt.shared.extension.AbstractExtension;
 import org.eclipse.scout.rt.shared.extension.ContributionComposite;
 import org.eclipse.scout.rt.shared.extension.ExtensionUtility;
@@ -115,6 +122,7 @@
  * </ul>
  * The Eclipse Scout SDK creates a subclass of this class that can be used as initial desktop.
  */
+@SuppressWarnings("deprecation")
 public abstract class AbstractDesktop extends AbstractPropertyObserver implements IDesktop, IContributionOwner, IExtensibleObject {
 
   private static final Logger LOG = LoggerFactory.getLogger(AbstractDesktop.class);
@@ -138,10 +146,8 @@
   private final FileChooserStore m_fileChooserStore;
   private List<IMenu> m_menus;
   private List<IViewButton> m_viewButtons;
-  private List<IToolButton> m_toolButtons;
   private boolean m_autoPrefixWildcardForTextSearch;
-  private boolean m_desktopInited;
-  private boolean m_trayVisible;
+  private boolean m_desktopInitialized;
   private boolean m_isForcedClosing = false;
   private final List<Object> m_addOns;
   private IContributionOwner m_contributionHolder;
@@ -213,22 +219,6 @@
   }
 
   /**
-   * Configures whether this Scout application should be represented within the OS system tray. Representations in the
-   * system tray might differ for different operating systems or different UI. A system tray may not be available at
-   * all.
-   * <p>
-   * Subclasses can override this method. Default is {@code false}.
-   *
-   * @return {@code true} if this application should be visible in the system tray, {@code false} otherwise
-   * @see #interceptAddTrayMenus(List)
-   */
-  @ConfigProperty(ConfigProperty.BOOLEAN)
-  @Order(15)
-  protected boolean getConfiguredTrayVisible() {
-    return false;
-  }
-
-  /**
    * Configures the outlines associated with this desktop. If multiple outlines are configured, there is typically a
    * need to provide some means of switching between different outlines, such as a {@link AbstractOutlineViewButton}.
    * <p>
@@ -267,15 +257,28 @@
   }
 
   /**
-   * Configures the desktop style which defines the basic layout of the application in the UI. Currently the desktop
-   * style cannot be changed at runtime.
+   * Configures the desktop style which defines the basic layout of the application in the UI.
    * <p>
-   * Subclasses can override this method. Default is {@code DesktopStyle.DEFAULT}.
+   * Subclasses can override this method. Default is {@link IDesktop#DISPLAY_STYLE_DEFAULT}
    */
-  @ConfigProperty(ConfigProperty.OBJECT)
+  @ConfigProperty(ConfigProperty.STRING)
   @Order(50)
-  protected DesktopStyle getConfiguredDesktopStyle() {
-    return DesktopStyle.DEFAULT;
+  protected String getConfiguredDisplayStyle() {
+    return DISPLAY_STYLE_DEFAULT;
+  }
+
+  /**
+   * Configures the logo id.
+   * <p>
+   * If specified, the logo will be displayed on the top right corner of the desktop.
+   * <p>
+   * Subclasses can override this method. Default is {@code null}.
+   *
+   * @since 6.0
+   * @see IIconProviderService
+   */
+  protected String getConfiguredLogoId() {
+    return null;
   }
 
   /**
@@ -290,6 +293,30 @@
     return true;
   }
 
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(70)
+  protected boolean getConfiguredNavigationVisible() {
+    return true;
+  }
+
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(75)
+  protected boolean getConfiguredNavigationHandleVisible() {
+    return true;
+  }
+
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(80)
+  protected boolean getConfiguredHeaderVisible() {
+    return true;
+  }
+
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(90)
+  protected boolean getConfiguredBenchVisible() {
+    return true;
+  }
+
   private List<Class<? extends IAction>> getConfiguredActions() {
     Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
     List<Class<IAction>> fca = ConfigurationUtility.filterClasses(dca, IAction.class);
@@ -339,7 +366,9 @@
   }
 
   /**
-   * Called after a UI has been attached to this desktop. This desktop must not necessarily be open.
+   * Called after a UI has been attached to this desktop. The desktop is opened at this point. This method may be called
+   * more than once. It is called immediately after the desktop has been opened and also in case of a reload, when a new
+   * UiSession has been created.
    * <p>
    * Subclasses can override this method. The default does nothing.
    */
@@ -457,20 +486,12 @@
   }
 
   /**
-   * Called while the tray popup is being built. This method may call {@link #getMenu(Class)} to find an existing menu
-   * on this desktop by class type.
-   * <p>
-   * The (potential) menus added to the {@code menus} list will be post processed. {@link IMenu#prepareAction()} is
-   * called on each and then checked if the menu is visible.
-   * <p>
-   * Subclasses can override this method. The default does nothing.
-   *
-   * @param menus
-   *          a live list to add menus to the tray
+   * Called by activateDefaultView when Scout application was not started with a deep-link or when deep-link could not
+   * be executed. The default implementation does nothing.
    */
   @Order(130)
   @ConfigOperation
-  protected void execAddTrayMenus(List<IMenu> menus) {
+  protected void execDefaultView() {
   }
 
   public List<IDesktopExtension> getDesktopExtensions() {
@@ -508,17 +529,23 @@
   }
 
   protected void initConfig() {
+    BEANS.get(IDeviceTransformationService.class).install(this);
     initDesktopExtensions();
     setTitle(getConfiguredTitle());
-    setTrayVisible(getConfiguredTrayVisible());
     setSelectViewTabsKeyStrokesEnabled(getConfiguredSelectViewTabsKeyStrokesEnabled());
     setSelectViewTabsKeyStrokeModifier(getConfiguredSelectViewTabsKeyStrokeModifier());
-    setDesktopStyle(getConfiguredDesktopStyle());
+    setLogoId(getConfiguredLogoId());
+    setNavigationVisible(getConfiguredNavigationVisible());
+    setNavigationHandleVisible(getConfiguredNavigationHandleVisible());
+    setBenchVisible(getConfiguredBenchVisible());
+    setHeaderVisible(getConfiguredHeaderVisible());
+    setDisplayStyle(getConfiguredDisplayStyle());
+    initDisplayStyle(getDisplayStyle());
     setCacheSplitterPosition(getConfiguredCacheSplitterPosition());
     List<IDesktopExtension> extensions = getDesktopExtensions();
     m_contributionHolder = new ContributionComposite(this);
 
-    //outlines
+    // outlines
     OrderedCollection<IOutline> outlines = new OrderedCollection<IOutline>();
     for (IDesktopExtension ext : extensions) {
       try {
@@ -535,7 +562,7 @@
     ExtensionUtility.moveModelObjects(outlines);
     m_availableOutlines = outlines.getOrderedList();
 
-    //actions (keyStroke, menu, viewButton, toolButton)
+    // actions (keyStroke, menu, viewButton, toolButton)
     List<IAction> actionList = new ArrayList<IAction>();
     for (IDesktopExtension ext : extensions) {
       try {
@@ -545,34 +572,23 @@
         LOG.error("contributing actions by {}", ext, t);
       }
     }
-
     List<IAction> contributedActions = m_contributionHolder.getContributionsByClass(IAction.class);
     actionList.addAll(contributedActions);
-    //build completed menu, viewButton, toolButton lists
-    // only top level menus
-    OrderedCollection<IMenu> menus = new OrderedCollection<IMenu>();
-    List<IMenu> allMenus = new ActionFinder().findActions(actionList, IMenu.class, false);
-    for (IMenu menu : allMenus) {
-      if (!(menu instanceof IToolButton)) {
-        menus.addOrdered(menu);
-      }
-    }
-//    menus.addAllOrdered(allMenus);
-    new MoveActionNodesHandler<IMenu>(menus).moveModelObjects();
-    m_menus = menus.getOrderedList();
 
+    // build complete menu and viewButton lists
+    // only top level menus
     OrderedComparator orderedComparator = new OrderedComparator();
+    List<IMenu> menuList = new ActionFinder().findActions(actionList, IMenu.class, false);
+    ExtensionUtility.moveModelObjects(menuList);
+    Collections.sort(menuList, orderedComparator);
+    m_menus = menuList;
+
     List<IViewButton> viewButtonList = new ActionFinder().findActions(actionList, IViewButton.class, false);
     ExtensionUtility.moveModelObjects(viewButtonList);
     Collections.sort(viewButtonList, orderedComparator);
     m_viewButtons = viewButtonList;
 
-    List<IToolButton> toolButtonList = new ActionFinder().findActions(actionList, IToolButton.class, false);
-    ExtensionUtility.moveModelObjects(toolButtonList);
-    Collections.sort(toolButtonList, orderedComparator);
-    m_toolButtons = toolButtonList;
-
-    //add dynamic keyStrokes
+    // add dynamic keyStrokes
     List<IKeyStroke> ksList = new ActionFinder().findActions(actionList, IKeyStroke.class, true);
     for (IKeyStroke ks : ksList) {
       try {
@@ -584,7 +600,7 @@
     }
     addKeyStrokes(ksList.toArray(new IKeyStroke[ksList.size()]));
 
-    //init outlines
+    // init outlines
     for (IOutline o : m_availableOutlines) {
       try {
         o.initTree();
@@ -593,6 +609,7 @@
         LOG.error("Could not init outline {}", o, e);
       }
     }
+    addPropertyChangeListener(new P_LocalPropertyChangeListener());
   }
 
   protected final void interceptInit() {
@@ -630,35 +647,44 @@
 
   @Override
   public void initDesktop() {
-    if (!m_desktopInited) {
-      m_desktopInited = true;
-      // extensions
-      for (IDesktopExtension ext : getDesktopExtensions()) {
-        try {
-          ContributionCommand cc = ext.initDelegate();
-          if (cc == ContributionCommand.Stop) {
-            break;
-          }
-        }
-        catch (Exception t) {
-          LOG.error("extension {} failed", ext, t);
+    if (m_desktopInitialized) {
+      return;
+    }
+    // extensions
+    for (IDesktopExtension ext : getDesktopExtensions()) {
+      try {
+        ContributionCommand cc = ext.initDelegate();
+        if (cc == ContributionCommand.Stop) {
+          break;
         }
       }
-      // init actions
-      ActionUtility.initActions(getMenus());
-      ActionUtility.initActions(getToolButtons());
-      ActionUtility.initActions(getViewButtons());
+      catch (Exception t) {
+        LOG.error("extension {} failed", ext, t);
+      }
     }
+    ActionUtility.initActions(getActions());
+    m_desktopInitialized = true;
   }
 
-  @Override
-  public boolean isTrayVisible() {
-    return m_trayVisible;
-  }
-
-  @Override
-  public void setTrayVisible(boolean b) {
-    m_trayVisible = b;
+  protected void initDisplayStyle(String style) {
+    if (DISPLAY_STYLE_BENCH.equals(style)) {
+      setNavigationVisible(false);
+      setNavigationHandleVisible(false);
+      setHeaderVisible(false);
+      setBenchVisible(true);
+    }
+    else if (DISPLAY_STYLE_COMPACT.equals(style)) {
+      setNavigationVisible(true);
+      setNavigationHandleVisible(false);
+      setHeaderVisible(false);
+      setBenchVisible(false);
+    }
+    else {
+      setNavigationVisible(true);
+      setNavigationHandleVisible(true);
+      setHeaderVisible(true);
+      setBenchVisible(true);
+    }
   }
 
   @Override
@@ -682,9 +708,9 @@
       return true;
     }
 
-    // active tool-button Form
-    for (IToolButton toolButton : getToolButtons()) {
-      if (toolButton instanceof IFormToolButton && toolButton.isSelected() && ((IFormToolButton) toolButton).getForm() == form) {
+    // active menu Form
+    for (IMenu menu : getMenus()) {
+      if (menu instanceof IFormMenu && menu.isSelected() && ((IFormMenu) menu).getForm() == form) {
         return true;
       }
     }
@@ -742,22 +768,39 @@
   }
 
   @Override
+  @Deprecated
   public <T extends IToolButton> T findToolButton(Class<T> toolButtonType) {
     return findAction(toolButtonType);
   }
 
   @Override
+  public <T extends IMenu> T findMenu(Class<T> menuType) {
+    return findAction(menuType);
+  }
+
+  @Override
   public <T extends IViewButton> T findViewButton(Class<T> viewButtonType) {
     return findAction(viewButtonType);
   }
 
   @Override
-  public DesktopStyle getDesktopStyle() {
-    return (DesktopStyle) propertySupport.getProperty(PROP_DESKTOP_STYLE);
+  public String getDisplayStyle() {
+    return propertySupport.getPropertyString(PROP_DISPLAY_STYLE);
   }
 
-  protected void setDesktopStyle(DesktopStyle desktopStyle) {
-    propertySupport.setProperty(PROP_DESKTOP_STYLE, desktopStyle);
+  @Override
+  public void setDisplayStyle(String displayStyle) {
+    propertySupport.setProperty(PROP_DISPLAY_STYLE, displayStyle);
+  }
+
+  @Override
+  public String getLogoId() {
+    return propertySupport.getPropertyString(PROP_LOGO_ID);
+  }
+
+  @Override
+  public void setLogoId(String id) {
+    propertySupport.setPropertyString(PROP_LOGO_ID, id);
   }
 
   @Override
@@ -775,17 +818,10 @@
   }
 
   @Override
-  public <T extends IMenu> T getMenu(Class<? extends T> searchType) {
-    // ActionFinder performs instance-of checks. Hence the menu replacement mapping is not required
-    return new ActionFinder().findAction(getMenus(), searchType);
-  }
-
-  @Override
   public List<IForm> getForms(IDisplayParent displayParent) {
     return m_formStore.getByDisplayParent(displayParent);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IForm> getViewStack() {
     return getViews();
@@ -833,7 +869,6 @@
     return CollectionUtility.firstElement(findAllOpenViews(formClass, handlerClass, exclusiveKey));
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IForm> getDialogStack() {
     return getDialogs();
@@ -861,7 +896,6 @@
     return dialogs;
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IMessageBox> getMessageBoxStack() {
     return getMessageBoxes();
@@ -925,7 +959,7 @@
   }
 
   @Override
-  @SuppressWarnings("deprecation")
+
   public void ensureVisible(IForm form) {
     activateForm(form);
   }
@@ -1003,6 +1037,7 @@
       m_activeOutlineListener = new P_ActiveOutlineListener();
       m_outline.addTreeListener(m_activeOutlineListener);
       m_outline.addPropertyChangeListener(m_activeOutlineListener);
+      setBrowserHistoryEntry(BEANS.get(OutlineDeepLinkHandler.class).createBrowserHistoryEntry(m_outline));
     }
     // <bsh 2010-10-15>
     // Those three "setXyz(null)" statements used to be called unconditionally. Now, they
@@ -1015,10 +1050,30 @@
       setPageSearchForm(null, true);
     }
     // </bsh>
+    updateActiveFormOnOutlineChanged();
     fireOutlineChanged(oldOutline, m_outline);
     onOutlineChangedInternal();
   }
 
+  // FIXME awe: review with C.GU - is it sufficient to set the active form to null?
+  // or do we have to find another suitable active form? I guess the UI will send
+  // the new active form later...
+  protected void updateActiveFormOnOutlineChanged() {
+    // If active form is not set or parent of active form is desktop
+    // we must do nothing
+    IForm activeForm = getActiveForm();
+    if (activeForm == null || activeForm.getDisplayParent() == this) {
+      return;
+    }
+
+    // Does the active form belong to the current outline?
+    // if not, we must set the active form to null otherwise we do nothing
+    List<IForm> formsByOutline = m_formStore.getByDisplayParent(m_outline);
+    if (!formsByOutline.contains(activeForm)) {
+      setActiveForm(null);
+    }
+  }
+
   /**
    * Called after the outline has been changed
    */
@@ -1042,7 +1097,6 @@
     m_outline.makeActivePageToContextPage();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addForm(IForm form) {
     showForm(form);
@@ -1089,7 +1143,6 @@
     fireFormShow(form);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void removeForm(IForm form) {
     hideForm(form);
@@ -1110,7 +1163,6 @@
     fireFormHide(form);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addMessageBox(final IMessageBox messageBox) {
     showMessageBox(messageBox);
@@ -1129,7 +1181,6 @@
     fireMessageBoxShow(messageBox);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void removeMessageBox(IMessageBox messageBox) {
     hideMessageBox(messageBox);
@@ -1171,7 +1222,6 @@
     return m_outlineChanging;
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void setOutline(IOutline outline) {
     activateOutline(outline);
@@ -1266,19 +1316,25 @@
     result.addAll(getKeyStrokes());
     result.addAll(getMenus());
     result.addAll(getViewButtons());
-    result.addAll(getToolButtons());
     return result;
   }
 
   @Override
+  public <T extends IMenu> T getMenu(Class<? extends T> searchType) {
+    // ActionFinder performs instance-of checks. Hence the menu replacement mapping is not required
+    return new ActionFinder().findAction(getMenus(), searchType);
+  }
+
+  @Deprecated
+  @Override
   public <T extends IToolButton> T getToolButton(Class<? extends T> searchType) {
     // ActionFinder performs instance-of checks. Hence the toolbutton replacement mapping is not required
-    return new ActionFinder().findAction(getToolButtons(), searchType);
+    return new ActionFinder().findAction(getMenus(), searchType);
   }
 
   @Override
-  public List<IToolButton> getToolButtons() {
-    return CollectionUtility.arrayList(m_toolButtons);
+  public List<IMenu> getToolButtons() {
+    return getMenus();
   }
 
   @Override
@@ -1412,6 +1468,16 @@
   }
 
   @Override
+  public BrowserHistoryEntry getBrowserHistoryEntry() {
+    return (BrowserHistoryEntry) propertySupport.getProperty(PROP_BROWSER_HISTORY_ENTRY);
+  }
+
+  @Override
+  public void setBrowserHistoryEntry(BrowserHistoryEntry browserHistory) {
+    propertySupport.setProperty(PROP_BROWSER_HISTORY_ENTRY, browserHistory);
+  }
+
+  @Override
   public boolean isCacheSplitterPosition() {
     return propertySupport.getPropertyBool(PROP_CACHE_SPLITTER_POSITION);
   }
@@ -1421,7 +1487,6 @@
     propertySupport.setPropertyBool(PROP_CACHE_SPLITTER_POSITION, b);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IFileChooser> getFileChooserStack() {
     return getFileChoosers();
@@ -1437,7 +1502,6 @@
     return m_fileChooserStore.getByDisplayParent(displayParent);
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addFileChooser(final IFileChooser fileChooser) {
     showFileChooser(fileChooser);
@@ -1625,7 +1689,7 @@
     if (dataTypes != null && dataTypes.length > 0) {
       // Important: Use LinkedHashMaps to make event firing deterministic!
       // (If listeners would be called in random order, bugs may not be reproduced very well.)
-      HashMap<DataChangeListener, Set<Object>> map = new LinkedHashMap<DataChangeListener, Set<Object>>();
+      HashMap<DataChangeListener, Set<Object>> map = new LinkedHashMap<>();
       for (Object dataType : dataTypes) {
         if (dataType != null) {
           EventListenerList list = m_dataChangeListenerList.get(dataType);
@@ -1654,14 +1718,6 @@
     fireDesktopEvent(e);
   }
 
-  private List<IMenu> fireTrayPopup() {
-    DesktopEvent e = new DesktopEvent(this, DesktopEvent.TYPE_TRAY_POPUP);
-    // single observer for exec callback
-    addLocalPopupMenus(e);
-    fireDesktopEvent(e);
-    return e.getPopupMenus();
-  }
-
   private void fireOutlineChanged(IOutline oldOutline, IOutline newOutline) {
     if (oldOutline != newOutline) {
       //extensions
@@ -1753,32 +1809,6 @@
     }
   }
 
-  private void addLocalPopupMenus(DesktopEvent event) {
-    try {
-      List<IMenu> list = new ArrayList<IMenu>();
-      //extensions
-      for (IDesktopExtension ext : getDesktopExtensions()) {
-        try {
-          ContributionCommand cc = ext.addTrayMenusDelegate(list);
-          if (cc == ContributionCommand.Stop) {
-            break;
-          }
-        }
-        catch (Exception ex) {
-          LOG.error("extension {}", ext, ex);
-        }
-      }
-      for (IMenu m : list) {
-        if (m != null && m.isVisible()) {
-          event.addPopupMenu(m);
-        }
-      }
-    }
-    catch (RuntimeException ex) {
-      BEANS.get(ExceptionHandler.class).handle(ex);
-    }
-  }
-
   @Override
   public void activateBookmark(Bookmark bm) {
     activateBookmark(bm, true);
@@ -1887,13 +1917,13 @@
     fireDesktopClosed();
   }
 
-  private void attachGui() {
+  private void attachGui(String deepLinkPath) {
     if (isGuiAvailable()) {
       return;
     }
     setGuiAvailableInternal(true);
 
-    //extensions
+    // extensions
     for (IDesktopExtension ext : getDesktopExtensions()) {
       try {
         ContributionCommand cc = ext.guiAttachedDelegate();
@@ -1905,6 +1935,83 @@
         BEANS.get(ExceptionHandler.class).handle(e);
       }
     }
+
+    activateDefaultView(deepLinkPath);
+  }
+
+  /**
+   * Activates the initial, default view of the Desktop. This method checks whether the Scout application has been
+   * started with a deep-link. If this applies, the deep-link is executed. Otherwise or if the deep-link has caused an
+   * error execDefaultView is called.
+   *
+   * @param deepLinkPath
+   *          The deep-link path which was passed as URL parameter to the Scout application (if available). This
+   *          parameter may be null. See: {@link IDeepLinks}.
+   */
+  protected void activateDefaultView(String deepLinkPath) {
+    try {
+      if (!handleDeepLink(deepLinkPath)) {
+        interceptDefaultView();
+      }
+    }
+    catch (DeepLinkException e) {
+      LOG.warn("Failed to execute deep-link '{}', reason: {}", deepLinkPath, e.getMessage());
+      interceptDefaultView();
+      showDeepLinkError(e);
+    }
+  }
+
+  /**
+   * Checks whether the given path is a valid deep-link. If that is the case the deep-link is handled. When an error
+   * occurs while handling the deep-link a {@link DeepLinkException} is thrown, usually this exception is thrown when
+   * the business-logic failed to find the resource addressed by the deep-link (similar to the 404 HTTP error status).
+   *
+   * @param deepLinkPath
+   * @return
+   * @throws DeepLinkException
+   *           when deep-link could not be executed
+   */
+  protected boolean handleDeepLink(String deepLinkPath) throws DeepLinkException {
+    if (hasApplicationModalElement()) {
+      LOG.debug("Could not handle deep-link because modal element prevents changes on UI state. deepLinkPath={}", deepLinkPath);
+      return false;
+    }
+
+    if (StringUtility.isNullOrEmpty(deepLinkPath)) {
+      return false;
+    }
+
+    boolean handled = false;
+    IDeepLinks deepLinks = BEANS.get(IDeepLinks.class);
+    if (deepLinks.canHandleDeepLink(deepLinkPath)) {
+      handled = deepLinks.handleDeepLink(deepLinkPath);
+    }
+    return handled;
+  }
+
+  protected boolean hasApplicationModalElement() {
+    if (m_messageBoxStore.containsApplicationModalMessageBoxes()) {
+      return true;
+    }
+    if (m_formStore.containsApplicationModalDialogs()) {
+      return true;
+    }
+    return m_fileChooserStore.containsApplicationModalFileChoosers();
+  }
+
+  /**
+   * Displays a message box showing a generic message that the deep-link could not be executed.
+   */
+  protected void showDeepLinkError(DeepLinkException e) {
+    if (e.getCause() instanceof VetoException) {
+      // permission problems
+      BEANS.get(ExceptionHandler.class).handle(e.getCause());
+    }
+    else {
+      // other problems
+      String errorMessage = TEXTS.get("DeepLinkError");
+      MessageBoxes.createOk().withBody(errorMessage).show();
+    }
   }
 
   private void detachGui() {
@@ -1913,7 +2020,7 @@
     }
     setGuiAvailableInternal(false);
 
-    //extensions
+    // extensions
     for (IDesktopExtension ext : getDesktopExtensions()) {
       try {
         ContributionCommand cc = ext.guiDetachedDelegate();
@@ -1978,6 +2085,46 @@
     m_isForcedClosing = forcedClosing;
   }
 
+  @Override
+  public void setNavigationVisible(boolean visible) {
+    propertySupport.setProperty(PROP_NAVIGATION_VISIBLE, visible);
+  }
+
+  @Override
+  public boolean isNavigationVisible() {
+    return (boolean) propertySupport.getProperty(PROP_NAVIGATION_VISIBLE);
+  }
+
+  @Override
+  public void setNavigationHandleVisible(boolean visible) {
+    propertySupport.setProperty(PROP_NAVIGATION_HANDLE_VISIBLE, visible);
+  }
+
+  @Override
+  public boolean isNavigationHandleVisible() {
+    return (boolean) propertySupport.getProperty(PROP_NAVIGATION_HANDLE_VISIBLE);
+  }
+
+  @Override
+  public void setBenchVisible(boolean visible) {
+    propertySupport.setProperty(PROP_BENCH_VISIBLE, visible);
+  }
+
+  @Override
+  public boolean isBenchVisible() {
+    return (boolean) propertySupport.getProperty(PROP_BENCH_VISIBLE);
+  }
+
+  @Override
+  public void setHeaderVisible(boolean visible) {
+    propertySupport.setProperty(PROP_HEADER_VISIBLE, visible);
+  }
+
+  @Override
+  public boolean isHeaderVisible() {
+    return (boolean) propertySupport.getProperty(PROP_HEADER_VISIBLE);
+  }
+
   /**
    * local desktop extension that calls local exec methods and returns local contributions in this class itself
    */
@@ -1989,7 +2136,7 @@
 
     @Override
     public void setCoreDesktop(IDesktop desktop) {
-      //nop
+      // NOP
     }
 
     @Override
@@ -2086,19 +2233,23 @@
       interceptTablePageLoaded(tablePage);
       return ContributionCommand.Continue;
     }
-
-    @Override
-    public ContributionCommand addTrayMenusDelegate(List<IMenu> menus) {
-      interceptAddTrayMenus(menus);
-      return ContributionCommand.Continue;
-    }
   }
 
   protected class P_UIFacade implements IDesktopUIFacade {
 
     @Override
-    public void fireGuiAttached() {
-      attachGui();
+    public void historyEntryActivatedFromUI(String deepLinkPath) {
+      try {
+        handleDeepLink(deepLinkPath);
+      }
+      catch (DeepLinkException e) {
+        showDeepLinkError(e);
+      }
+    }
+
+    @Override
+    public void fireGuiAttached(String deepLinkPath) {
+      attachGui(deepLinkPath);
     }
 
     @Override
@@ -2107,7 +2258,7 @@
     }
 
     @Override
-    public void fireDesktopOpenedFromUI() {
+    public void openFromUI() {
       setOpenedInternal(true);
       //extensions
       for (IDesktopExtension ext : getDesktopExtensions()) {
@@ -2124,7 +2275,7 @@
     }
 
     @Override
-    public void fireDesktopClosingFromUI(boolean forcedClosing) {
+    public void closeFromUI(boolean forcedClosing) {
       setForcedClosing(forcedClosing);
       // necessary so that no forms can be opened anymore.
       if (forcedClosing) {
@@ -2134,8 +2285,18 @@
     }
 
     @Override
-    public List<IMenu> fireTrayPopupFromUI() { // XXX AWE: ausbauen, auch event
-      return fireTrayPopup();
+    public void setNavigationVisibleFromUI(boolean visible) {
+      setNavigationVisible(visible);
+    }
+
+    @Override
+    public void setHeaderVisibleFromUI(boolean visible) {
+      setHeaderVisible(visible);
+    }
+
+    @Override
+    public void setBenchVisibleFromUI(boolean visible) {
+      setBenchVisible(visible);
     }
   }
 
@@ -2272,11 +2433,6 @@
     }
 
     @Override
-    public void execAddTrayMenus(DesktopAddTrayMenusChain chain, List<IMenu> menus) {
-      getOwner().execAddTrayMenus(menus);
-    }
-
-    @Override
     public void execBeforeClosing(DesktopBeforeClosingChain chain) {
       getOwner().execBeforeClosing();
     }
@@ -2326,6 +2482,11 @@
       getOwner().execGuiDetached();
     }
 
+    @Override
+    public void execDefaultView(DesktopDefaultViewChain chain) {
+      getOwner().execDefaultView();
+    }
+
   }
 
   protected final void interceptOpened() {
@@ -2334,12 +2495,6 @@
     chain.execOpened();
   }
 
-  protected final void interceptAddTrayMenus(List<IMenu> menus) {
-    List<? extends org.eclipse.scout.rt.client.extension.ui.desktop.IDesktopExtension<? extends AbstractDesktop>> extensions = getAllExtensions();
-    DesktopAddTrayMenusChain chain = new DesktopAddTrayMenusChain(extensions);
-    chain.execAddTrayMenus(menus);
-  }
-
   protected final void interceptBeforeClosing() {
     List<? extends org.eclipse.scout.rt.client.extension.ui.desktop.IDesktopExtension<? extends AbstractDesktop>> extensions = getAllExtensions();
     DesktopBeforeClosingChain chain = new DesktopBeforeClosingChain(extensions);
@@ -2400,4 +2555,20 @@
     chain.execGuiDetached();
   }
 
+  protected final void interceptDefaultView() {
+    List<? extends org.eclipse.scout.rt.client.extension.ui.desktop.IDesktopExtension<? extends AbstractDesktop>> extensions = getAllExtensions();
+    DesktopDefaultViewChain chain = new DesktopDefaultViewChain(extensions);
+    chain.execDefaultView();
+  }
+
+  protected class P_LocalPropertyChangeListener implements PropertyChangeListener {
+
+    @Override
+    public void propertyChange(PropertyChangeEvent evt) {
+      if (evt.getPropertyName() == PROP_DISPLAY_STYLE) {
+        initDisplayStyle((String) evt.getNewValue());
+      }
+    }
+
+  }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopExtension.java
index 8001a89..adad4cd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/AbstractDesktopExtension.java
@@ -14,7 +14,6 @@
 import java.util.List;
 
 import org.eclipse.scout.rt.client.ui.action.IAction;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPageWithTable;
@@ -100,11 +99,6 @@
   }
 
   @Override
-  public ContributionCommand addTrayMenusDelegate(List<IMenu> menus) {
-    return execAddTrayMenus(menus);
-  }
-
-  @Override
   public void contributeOutlines(OrderedCollection<IOutline> outlines) {
     List<Class<? extends IOutline>> contributedOutlines = getConfiguredOutlines();
     if (contributedOutlines == null) {
@@ -332,26 +326,6 @@
   }
 
   /**
-   * Called while the tray popup is being built. This method may call {@code getMenu(Class)} on the core desktop to find
-   * an existing menu on the core desktop by class type.
-   * <p>
-   * The (potential) menus added to the {@code menus} list will be post processed. {@link IMenu#prepareAction()} is
-   * called on each and then checked if the menu is visible.
-   * <p>
-   * Subclasses can override this method. The default simply returns {@link ContributionCommand.Continue}.
-   *
-   * @param menus
-   *          a live list to add menus to the tray
-   * @return {@code ContributionCommand.Continue} if further extensions should be processed,
-   *         {@code ContributionCommand.Stop} otherwise
-   */
-  @Order(70)
-  @ConfigOperation
-  protected ContributionCommand execAddTrayMenus(List<IMenu> menus) {
-    return ContributionCommand.Continue;
-  }
-
-  /**
    * Configures the outlines contributed by this desktop extension. These outlines are automatically added to the core
    * desktop which holds this extension.
    * <p>
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/BrowserHistoryEntry.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/BrowserHistoryEntry.java
new file mode 100644
index 0000000..9eb19ae
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/BrowserHistoryEntry.java
@@ -0,0 +1,99 @@
+package org.eclipse.scout.rt.client.ui.desktop;
+
+import java.net.URI;
+
+/**
+ * This class is used to populate the browser history with history entries.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/History
+ * @since 6.0
+ */
+public class BrowserHistoryEntry {
+
+  private final String m_title;
+
+  private final URI m_path;
+
+  private final String m_deepLinkPath;
+
+  /**
+   * @param path
+   *          relative path which is displayed in the address bar of the browser. Example
+   *          <code>./?deeplink=outline-12345</code>
+   * @param title
+   *          displayed in the browser window
+   * @param deepLinkPath
+   *          stored in the History.state object of the browser. This path is sent back to the UI server when the user
+   *          clicks on the navigate buttons in the browser. Example <code>outline-12345</code>
+   */
+  public BrowserHistoryEntry(URI path, String title, String deepLinkPath) {
+    m_path = path;
+    m_title = title;
+    m_deepLinkPath = deepLinkPath;
+  }
+
+  public String getTitle() {
+    return m_title;
+  }
+
+  public String getPath() {
+    if (m_path == null) {
+      return null;
+    }
+    return m_path.toString();
+  }
+
+  public String getDeepLinkPath() {
+    return m_deepLinkPath;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((m_deepLinkPath == null) ? 0 : m_deepLinkPath.hashCode());
+    result = prime * result + ((m_path == null) ? 0 : m_path.hashCode());
+    result = prime * result + ((m_title == null) ? 0 : m_title.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    BrowserHistoryEntry other = (BrowserHistoryEntry) obj;
+    if (m_deepLinkPath == null) {
+      if (other.m_deepLinkPath != null) {
+        return false;
+      }
+    }
+    else if (!m_deepLinkPath.equals(other.m_deepLinkPath)) {
+      return false;
+    }
+    if (m_path == null) {
+      if (other.m_path != null) {
+        return false;
+      }
+    }
+    else if (!m_path.equals(other.m_path)) {
+      return false;
+    }
+    if (m_title == null) {
+      if (other.m_title != null) {
+        return false;
+      }
+    }
+    else if (!m_title.equals(other.m_title)) {
+      return false;
+    }
+    return true;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/DesktopEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/DesktopEvent.java
index 95cce58..8a01a1f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/DesktopEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/DesktopEvent.java
@@ -12,12 +12,9 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
 import java.util.EventObject;
-import java.util.List;
 
 import org.eclipse.scout.rt.client.ui.IModelEvent;
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.basic.filechooser.IFileChooser;
 import org.eclipse.scout.rt.client.ui.desktop.notification.IDesktopNotification;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
@@ -26,7 +23,6 @@
 import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 import org.eclipse.scout.rt.client.ui.messagebox.IMessageBox;
 import org.eclipse.scout.rt.platform.resource.BinaryResource;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
 
 public class DesktopEvent extends EventObject implements IModelEvent {
   private static final long serialVersionUID = 1L;
@@ -100,10 +96,6 @@
    * 2000 ms)
    */
   public static final int TYPE_FIND_FOCUS_OWNER = 1000;
-  /**
-   * Broadcast request to add all popup menus for the tray menu collector: popupMenus
-   */
-  public static final int TYPE_TRAY_POPUP = 1010;
 
   /**
    * Event type indicates that a notification has been added to the desktop.
@@ -123,7 +115,6 @@
   private IMessageBox m_messageBox;
   private IFileChooser m_fileChooser;
   private String m_uri;
-  private List<IMenu> m_popupMenus;
   private IOpenUriAction m_openUriAction;
   private BinaryResource m_binaryResource;
   private IDesktopNotification m_notification;
@@ -224,49 +215,6 @@
     m_focusedField = f;
   }
 
-  /**
-   * used by TYPE_TRAY_POPUP to add menus
-   */
-  public void addPopupMenu(IMenu menu) {
-    if (menu != null) {
-      if (m_popupMenus == null) {
-        m_popupMenus = new ArrayList<IMenu>();
-      }
-      m_popupMenus.add(menu);
-    }
-  }
-
-  /**
-   * used by TYPE_TRAY_POPUP to add menus
-   */
-  public void addPopupMenus(List<IMenu> menus) {
-    if (menus != null) {
-      if (m_popupMenus == null) {
-        m_popupMenus = new ArrayList<IMenu>();
-      }
-      m_popupMenus.addAll(menus);
-    }
-  }
-
-  /**
-   * used by TYPE_TRAY_POPUP to add menus
-   */
-  public List<IMenu> getPopupMenus() {
-    return CollectionUtility.arrayList(m_popupMenus);
-  }
-
-  /**
-   * used by TYPE_TRAY_POPUP to add menus
-   */
-  public int getPopupMenuCount() {
-    if (m_popupMenus != null) {
-      return m_popupMenus.size();
-    }
-    else {
-      return 0;
-    }
-  }
-
   public IForm getActiveForm() {
     return m_activeForm;
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktop.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktop.java
index 1c731eb..8636fa7 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktop.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktop.java
@@ -19,7 +19,6 @@
 import org.eclipse.scout.rt.client.IClientSession;
 import org.eclipse.scout.rt.client.ui.DataChangeListener;
 import org.eclipse.scout.rt.client.ui.IDisplayParent;
-import org.eclipse.scout.rt.client.ui.action.ActionFinder;
 import org.eclipse.scout.rt.client.ui.action.IAction;
 import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
@@ -58,6 +57,7 @@
  * <li>top-level menus (menu tree)
  * </ul>
  */
+@SuppressWarnings("deprecation")
 public interface IDesktop extends IPropertyObserver, IDisplayParent {
 
   /**
@@ -69,6 +69,12 @@
    * String
    */
   String PROP_TITLE = "title";
+
+  /**
+   * String
+   */
+  String PROP_LOGO_ID = "logoId";
+
   /**
    * {@link IStatus}
    */
@@ -99,23 +105,36 @@
    */
   String PROP_CACHE_SPLITTER_POSITION = "cacheSplitterPosition";
 
-  String PROP_DESKTOP_STYLE = "desktopStyle";
+  String PROP_DISPLAY_STYLE = "displayStyle";
 
   String PROP_ACTIVE_FORM = "activeForm";
 
   String PROP_THEME = "theme";
 
-  public enum DesktopStyle {
-    /**
-     * Default desktop style with header, navigation (tree) and bench (forms).
-     */
-    DEFAULT,
+  String PROP_BROWSER_HISTORY_ENTRY = "browserHistoryEntry";
 
-    /**
-     * Reduced desktop style. Only bench is visible.
-     */
-    BENCH
-  }
+  String PROP_NAVIGATION_VISIBLE = "navigationVisible";
+
+  String PROP_NAVIGATION_HANDLE_VISIBLE = "navigationHandleVisible";
+
+  String PROP_HEADER_VISIBLE = "headerVisible";
+
+  String PROP_BENCH_VISIBLE = "benchVisible";
+
+  /**
+   * Default style with header, navigation (tree) and bench (forms).
+   */
+  String DISPLAY_STYLE_DEFAULT = "default";
+
+  /**
+   * Reduced style. Only bench is visible.
+   */
+  String DISPLAY_STYLE_BENCH = "bench";
+
+  /**
+   * Compact style. Navigation and bench are never visible simultaneously.
+   */
+  String DISPLAY_STYLE_COMPACT = "compact";
 
   void initDesktop();
 
@@ -134,14 +153,17 @@
    */
   <T extends IOutline> T findOutline(Class<T> outlineType);
 
-  /**
-   * Find a toolButton or a viewButton in the desktop
-   */
   <T extends IAction> T findAction(Class<T> actionType);
 
   /**
    * Convenience alias for {@link #findAction(Class)}
    */
+  <T extends IMenu> T findMenu(Class<T> menuType);
+
+  /**
+   * @deprecated use {@link #getMenuByClass(Class)} instead
+   */
+  @Deprecated
   <T extends IToolButton> T findToolButton(Class<T> toolButtonType);
 
   /**
@@ -149,10 +171,6 @@
    */
   <T extends IViewButton> T findViewButton(Class<T> viewButtonType);
 
-  boolean isTrayVisible();
-
-  void setTrayVisible(boolean b);
-
   /**
    * Returns all registered Views of the same class and with the same exclusive key, except the current Search- or
    * Detail Form.
@@ -502,9 +520,6 @@
    */
   List<IMenu> getMenus();
 
-  /**
-   * Convenience to find a menu in the desktop, uses {@link ActionFinder}
-   */
   <T extends IMenu> T getMenu(Class<? extends T> searchType);
 
   /**
@@ -513,18 +528,17 @@
   List<IAction> getActions();
 
   /**
-   * Convenience to find a toolbutton in the desktop, uses {@link ActionFinder}
+   * @deprecated use {@link #getMenu(Class)} instead
    */
+  @Deprecated
   <T extends IToolButton> T getToolButton(Class<? extends T> searchType);
 
   /**
-   * @return all {@link IToolButton} actions
+   * @deprecated use {@link #getMenus()} instead
    */
-  List<IToolButton> getToolButtons();
+  @Deprecated
+  List<IMenu> getToolButtons();
 
-  /**
-   * Convenience to find a menu in the desktop, uses {@link ActionFinder}
-   */
   <T extends IViewButton> T getViewButton(Class<? extends T> searchType);
 
   /**
@@ -756,7 +770,13 @@
   Collection<Object> getAddOns();
 
   /**
-   * Adds an untyped add-on to the Desktop.
+   * Adds an untyped add-on to the Desktop. Add-ons are required when you want to extend your Desktop with something
+   * that needs to add elements to the DOM of the user interface. Typically these DOM elements are not visible, so the
+   * add-ons are not meant for clickable UI-elements but rather for technical features, like interfaces built with
+   * browser-technologies.
+   * <p>
+   * In order to render the add-ons in the UI you must extend your <code>JsonObjectFactory</code> and provide a
+   * <i>Json[AddOn].java</i> and an <i>[AddOn].js</i>.
    *
    * @since 5.1.0
    */
@@ -771,10 +791,22 @@
   boolean isOutlineChanging();
 
   /**
-   * @return the desktop style. Default value is <code>DesktopStyle.DEFAULT</code>.
+   * @return the display style. Default value is <code>DISPLAY_STYLE_DEFAULT</code>.
    * @since 5.2.0
    */
-  DesktopStyle getDesktopStyle();
+  String getDisplayStyle();
+
+  void setDisplayStyle(String displayStyle);
+
+  /***
+   * @since 6.0
+   */
+  String getLogoId();
+
+  /**
+   * @since 6.0
+   */
+  void setLogoId(String id);
 
   /**
    * @return the name of the current theme or null when default theme is active.
@@ -789,4 +821,57 @@
    */
   void setTheme(String theme);
 
+  /**
+   * @return the current browser history item
+   * @since 6.0
+   */
+  BrowserHistoryEntry getBrowserHistoryEntry();
+
+  /**
+   * Sets the browser history item. Calling this method will change the URL in the address bar of the browser.
+   *
+   * @since 6.0
+   */
+  void setBrowserHistoryEntry(BrowserHistoryEntry browserHistory);
+
+  /**
+   * @since 6.0
+   */
+  void setNavigationVisible(boolean visible);
+
+  /**
+   * @since 6.0
+   */
+  boolean isNavigationVisible();
+
+  /**
+   * @since 6.0
+   */
+  void setNavigationHandleVisible(boolean visible);
+
+  /**
+   * @since 6.0
+   */
+  boolean isNavigationHandleVisible();
+
+  /**
+   * @since 6.0
+   */
+  void setBenchVisible(boolean visible);
+
+  /**
+   * @since 6.0
+   */
+  boolean isBenchVisible();
+
+  /**
+   * @since 6.0
+   */
+  void setHeaderVisible(boolean visible);
+
+  /**
+   * @since 6.0
+   */
+  boolean isHeaderVisible();
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopExtension.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopExtension.java
index 4e9d35a..b1794e5 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopExtension.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopExtension.java
@@ -11,7 +11,6 @@
 package org.eclipse.scout.rt.client.ui.desktop;
 
 import java.util.Collection;
-import java.util.List;
 
 import org.eclipse.scout.rt.client.ui.action.IAction;
 import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
@@ -36,6 +35,7 @@
  * <li>actions (menu, keyStroke, toolButton, viewButton)</li>
  * </ul>
  */
+@SuppressWarnings("deprecation")
 @Bean
 public interface IDesktopExtension {
 
@@ -175,20 +175,6 @@
   ContributionCommand tablePageLoadedDelegate(IPageWithTable<?> tablePage);
 
   /**
-   * Called while the tray popup is being built. This method may call {@code getMenu(Class)} on the core desktop to find
-   * an existing menu on the core desktop by class type.
-   * <p>
-   * The (potential) menus added to the {@code menus} list will be post processed. {@link IMenu#prepareAction()} is
-   * called on each and then checked if the menu is visible.
-   *
-   * @param menus
-   *          a live list to add menus to the tray
-   * @return {@code ContributionCommand.Continue} if further extensions should be processed,
-   *         {@code ContributionCommand.Stop} otherwise
-   */
-  ContributionCommand addTrayMenusDelegate(List<IMenu> menus);
-
-  /**
    * Adds the outlines configured with this extension to the {@code outlines} collection. This is a live list of
    * contributed outlines. They are NOT yet initialized.
    * <p>
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopUIFacade.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopUIFacade.java
index e17184a..3a85f00 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopUIFacade.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/IDesktopUIFacade.java
@@ -10,10 +10,6 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.ui.desktop;
 
-import java.util.List;
-
-import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
-
 /**
  * The desktop model (may) consist of
  * <ul>
@@ -32,7 +28,7 @@
   /**
    * GUI fires this event as soon as the desktop was completely setup and displayed
    */
-  void fireDesktopOpenedFromUI();
+  void openFromUI();
 
   /**
    * GUI fires this event when it is in the process of closing the workbench / application
@@ -44,12 +40,17 @@
    *          {@link AbstractDesktop#doBeforeClosingInternal()} will be ignored. Otherwise if set to <code>false</code>
    *          vetos are accepted.
    */
-  void fireDesktopClosingFromUI(boolean forcedClosing);
+  void closeFromUI(boolean forcedClosing);
 
   /**
-   * GUI fires this event as soon as a gui is available
+   * GUI fires this event when a UiSession has been attached to the desktop. The desktop is open at this point. The
+   * event occurs after openFromUI().
+   *
+   * @param deepLinkPath
+   *          The deep-link path which was passed as URL parameter to the Scout application (if available). This
+   *          parameter may be null.
    */
-  void fireGuiAttached();
+  void fireGuiAttached(String deepLinkPath);
 
   /**
    * GUI fires this event when the application/workbench is closing
@@ -57,7 +58,16 @@
   void fireGuiDetached();
 
   /**
-   * GUI fires this event to collect the tray popup menus
+   * GUI fires this event when user clicks on back/forward button in the navigation history of the browser.
+   *
+   * @param deepLinkPath
+   *          The deep-link path which belongs to the activated history entry. This parameter may be null.
    */
-  List<IMenu> fireTrayPopupFromUI();
+  void historyEntryActivatedFromUI(String deepLinkPath);
+
+  void setNavigationVisibleFromUI(boolean visible);
+
+  void setHeaderVisibleFromUI(boolean visible);
+
+  void setBenchVisibleFromUI(boolean visible);
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/OpenUriAction.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/OpenUriAction.java
index 0821d98..8d9ffaa 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/OpenUriAction.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/OpenUriAction.java
@@ -44,7 +44,7 @@
    * opened to show this content. The application's location does not change. Note that this action may be prevented by
    * the browser's popup blocker mechanism.
    */
-  NEW_WINDOW("new-window");
+  NEW_WINDOW("newWindow");
 
   private final String m_identifier;
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/internal/VirtualDesktop.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/internal/VirtualDesktop.java
index b9be9b6..d6935ef 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/internal/VirtualDesktop.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/internal/VirtualDesktop.java
@@ -28,6 +28,7 @@
 import org.eclipse.scout.rt.client.ui.action.view.IViewButton;
 import org.eclipse.scout.rt.client.ui.basic.filechooser.IFileChooser;
 import org.eclipse.scout.rt.client.ui.basic.table.ITable;
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
 import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktopUIFacade;
@@ -55,6 +56,8 @@
  * forms, fields, pages that must be done while the desktop is loading. This pattern solves the bird/egg problem in
  * initialization of an object with self-references.
  */
+
+@SuppressWarnings("deprecation")
 public class VirtualDesktop implements IDesktop {
 
   private final EventListenerList m_listenerList;
@@ -195,15 +198,6 @@
    */
 
   @Override
-  public boolean isTrayVisible() {
-    return false;
-  }
-
-  @Override
-  public void setTrayVisible(boolean b) {
-  }
-
-  @Override
   public boolean isAutoPrefixWildcardForTextSearch() {
     throw createUnsupportedOperationException();
   }
@@ -248,7 +242,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IFileChooser> getFileChooserStack() {
     throw createUnsupportedOperationException();
@@ -264,7 +257,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addFileChooser(IFileChooser fc) {
     throw createUnsupportedOperationException();
@@ -290,7 +282,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addForm(IForm form) {
     throw createUnsupportedOperationException();
@@ -301,7 +292,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void removeForm(IForm form) {
     throw createUnsupportedOperationException();
@@ -317,7 +307,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void addMessageBox(IMessageBox mb) {
     throw createUnsupportedOperationException();
@@ -328,7 +317,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void removeMessageBox(IMessageBox messageBox) {
     throw createUnsupportedOperationException();
@@ -375,7 +363,7 @@
   }
 
   @Override
-  @SuppressWarnings("deprecation")
+
   public void ensureVisible(IForm form) {
     throw createUnsupportedOperationException();
   }
@@ -435,7 +423,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IForm> getDialogStack() {
     throw createUnsupportedOperationException();
@@ -476,7 +463,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IMessageBox> getMessageBoxStack() {
     throw createUnsupportedOperationException();
@@ -552,13 +538,14 @@
     throw createUnsupportedOperationException();
   }
 
+  @Deprecated
   @Override
   public <T extends IToolButton> T getToolButton(Class<? extends T> searchType) {
     throw createUnsupportedOperationException();
   }
 
   @Override
-  public List<IToolButton> getToolButtons() {
+  public List<IMenu> getToolButtons() {
     throw createUnsupportedOperationException();
   }
 
@@ -577,7 +564,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public List<IForm> getViewStack() {
     throw createUnsupportedOperationException();
@@ -648,7 +634,6 @@
     throw createUnsupportedOperationException();
   }
 
-  @SuppressWarnings("deprecation")
   @Override
   public void setOutline(IOutline outline) {
     throw createUnsupportedOperationException();
@@ -661,10 +646,12 @@
 
   @Override
   public void addNotification(IDesktopNotification notification) {
+    // NOP
   }
 
   @Override
   public void removeNotification(IDesktopNotification notification) {
+    // NOP
   }
 
   @Override
@@ -703,8 +690,23 @@
   }
 
   @Override
-  public DesktopStyle getDesktopStyle() {
-    return DesktopStyle.DEFAULT;
+  public String getDisplayStyle() {
+    return DISPLAY_STYLE_DEFAULT;
+  }
+
+  @Override
+  public void setDisplayStyle(String displayStyle) {
+    // NOP
+  }
+
+  @Override
+  public String getLogoId() {
+    return null;
+  }
+
+  @Override
+  public void setLogoId(String id) {
+    // NOP
   }
 
   @Override
@@ -714,6 +716,7 @@
 
   @Override
   public void setCacheSplitterPosition(boolean b) {
+    // NOP
   }
 
   @Override
@@ -723,5 +726,60 @@
 
   @Override
   public void setTheme(String theme) {
+    // NOP
   }
+
+  @Override
+  public BrowserHistoryEntry getBrowserHistoryEntry() {
+    return null;
+  }
+
+  @Override
+  public void setBrowserHistoryEntry(BrowserHistoryEntry browserHistory) {
+  }
+
+  @Override
+  public void setNavigationVisible(boolean visible) {
+    // NOP
+  }
+
+  @Override
+  public boolean isNavigationVisible() {
+    return false;
+  }
+
+  @Override
+  public void setBenchVisible(boolean visible) {
+  }
+
+  @Override
+  public boolean isBenchVisible() {
+    return false;
+  }
+
+  @Override
+  public void setHeaderVisible(boolean visible) {
+    // NOP
+  }
+
+  @Override
+  public boolean isHeaderVisible() {
+    return false;
+  }
+
+  @Override
+  public <T extends IMenu> T findMenu(Class<T> menuType) {
+    return null;
+  }
+
+  @Override
+  public void setNavigationHandleVisible(boolean visible) {
+    // NOP
+  }
+
+  @Override
+  public boolean isNavigationHandleVisible() {
+    return false;
+  }
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractFormToolButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractFormToolButton.java
index 2bb048f..b4f2ee6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractFormToolButton.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractFormToolButton.java
@@ -10,167 +10,17 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.ui.desktop.outline;
 
-import java.util.List;
-
-import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
-import org.eclipse.scout.rt.client.extension.ui.desktop.outline.FormToolButtonChains.FormToolButtonInitFormChain;
-import org.eclipse.scout.rt.client.extension.ui.desktop.outline.IFormToolButtonExtension;
-import org.eclipse.scout.rt.client.ui.action.AbstractAction;
-import org.eclipse.scout.rt.client.ui.action.tool.AbstractToolButton;
+import org.eclipse.scout.rt.client.ui.action.tool.IToolButton;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.form.FormEvent;
-import org.eclipse.scout.rt.client.ui.form.FormListener;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
 import org.eclipse.scout.rt.client.ui.form.IForm;
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
-import org.eclipse.scout.rt.platform.annotations.ConfigOperation;
-import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
-import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
-import org.eclipse.scout.rt.platform.exception.ProcessingException;
 
 /**
  * A tool button that can be used in the {@link IDesktop} to toggle a form in the tools area.
+ *
+ * @deprecated use AbstractFormMenu instead.
  */
-public abstract class AbstractFormToolButton<FORM extends IForm> extends AbstractToolButton implements IFormToolButton<FORM> {
-
-  @Override
-  protected boolean getConfiguredToggleAction() {
-    return true;
-  }
-
-  @SuppressWarnings("unchecked")
-  @Override
-  public FORM getForm() {
-    return (FORM) propertySupport.getProperty(PROP_FORM);
-  }
-
-  @Override
-  public void setForm(FORM f) {
-    propertySupport.setProperty(PROP_FORM, f);
-  }
-
-  /**
-   * Configures the form to be used with this button. The form is lazily created and started when the button gets
-   * selected.
-   * <p>
-   * Subclasses can override this method. Default is {@code null}.
-   *
-   * @return a form type token
-   * @see {@link #startForm(IForm)} for details how the form gets started
-   */
-  @ConfigProperty(ConfigProperty.FORM)
-  @Order(90)
-  protected Class<FORM> getConfiguredForm() {
-    return null;
-  }
-
-  /**
-   * Initializes the {@link IForm} associated with this button, and is invoked once the {@link IForm} is showed for the
-   * first time.
-   *
-   * @param form
-   *          the {@link IForm} to be initialized.
-   */
-  @ConfigOperation
-  @Order(120)
-  protected void execInitForm(IForm form) {
-  }
-
-  @Override
-  protected void execSelectionChanged(boolean selected) {
-    if (!selected) {
-      return;
-    }
-    ensureFormCreated();
-    ensureFormStarted();
-  }
-
-  public void ensureFormCreated() {
-    if (getForm() != null) {
-      return;
-    }
-    FORM form = createForm();
-    if (form != null) {
-      form.addFormListener(new FormListener() {
-        @Override
-        public void formChanged(FormEvent e) {
-          if (e.getType() == FormEvent.TYPE_CLOSED) {
-            setSelected(false);
-            setForm(null);
-          }
-        }
-      });
-      decorateForm(form);
-      interceptInitForm(form);
-      setForm(form);
-    }
-  }
-
-  public void ensureFormStarted() {
-    if (getForm() == null || !getForm().isFormStartable()) {
-      return;
-    }
-    startForm();
-  }
-
-  protected FORM createForm() {
-    if (getConfiguredForm() == null) {
-      return null;
-    }
-    try {
-      return getConfiguredForm().newInstance();
-    }
-    catch (Exception e) {
-      BEANS.get(ExceptionHandler.class).handle(new ProcessingException("error creating instance of class '" + getConfiguredForm().getName() + "'.", e));
-    }
-    return null;
-  }
-
-  /**
-   * Starts the form.
-   * <p>
-   * The default uses {@link IForm#start()} and therefore expects a form handler to be previously set. Override to call
-   * a custom start method.
-   */
-  protected void startForm() {
-    getForm().start();
-  }
-
-  protected void decorateForm(IForm form) {
-    form.setShowOnStart(false);
-    form.setDisplayHint(IForm.DISPLAY_HINT_VIEW); // FIXME dwi: set in UI instead
-    form.setDisplayViewId(IForm.VIEW_ID_E); // FIXME dwi: set in UI instead
-  }
-
-  protected final void interceptInitForm(FORM form) {
-    List<? extends IActionExtension<? extends AbstractAction>> extensions = getAllExtensions();
-    FormToolButtonInitFormChain<FORM> chain = new FormToolButtonInitFormChain<>(extensions);
-    chain.execInitForm(form);
-  }
-
-  @Override
-  public void disposeInternal() {
-    super.disposeInternal();
-    FORM form = getForm();
-    if (form != null) {
-      form.doClose();
-    }
-  }
-
-  protected static class LocalFormToolButtonExtension<FORM extends IForm, OWNER extends AbstractFormToolButton<FORM>> extends LocalToolButtonExtension<OWNER> implements IFormToolButtonExtension<FORM, OWNER> {
-
-    public LocalFormToolButtonExtension(OWNER owner) {
-      super(owner);
-    }
-
-    @Override
-    public void execInitForm(FormToolButtonInitFormChain<FORM> chain, FORM form) {
-      getOwner().execInitForm(form);
-    }
-  }
-
-  @Override
-  protected IFormToolButtonExtension<FORM, ? extends AbstractFormToolButton<FORM>> createLocalExtension() {
-    return new LocalFormToolButtonExtension<FORM, AbstractFormToolButton<FORM>>(this);
-  }
+@SuppressWarnings("deprecation")
+@Deprecated
+public abstract class AbstractFormToolButton<FORM extends IForm> extends AbstractFormMenu<FORM> implements IToolButton {
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractOutline.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractOutline.java
index 1c7d253..b8199c4 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractOutline.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractOutline.java
@@ -166,14 +166,16 @@
   }
 
   /**
-   * Configures whether the outline should be displayed in bread crumb mode or not. It is currently not possible to have
-   * outlines with different modes. The mode of the outline which gets activated first is used for the other outlines as
-   * well.
+   * Configures whether the outline should automatically switch to the bread crumb style when getting smaller and back
+   * when getting bigger. The threshold is determined by the GUI.
+   * <p>
+   * Subclasses can override this method. The default is true.
+   *
+   * @see #getConfiguredDisplayStyle()
    */
-  @ConfigProperty(ConfigProperty.BOOLEAN)
-  @Order(140)
-  protected boolean getConfiguredBreadcrumbEnabled() {
-    return false;
+  @Override
+  protected boolean getConfiguredAutoToggleBreadcrumbStyle() {
+    return true;
   }
 
   /**
@@ -182,11 +184,23 @@
    * The folder icon {@link AbstractIcons#Folder} is used as default.
    */
   @Override
+  @Order(150)
   protected String getConfiguredIconId() {
     return AbstractIcons.Folder;
   }
 
   /**
+   * Configures whether the navigate buttons are visible.
+   * <p>
+   * Navigation buttons give the possibility to navigate down or up the tree.
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(160)
+  protected boolean getConfiguredNavigateButtonsVisible() {
+    return true;
+  }
+
+  /**
    * Called during initialization of this outline. Creates the root node of this outline.
    * <p>
    * Subclasses should overwrite either this method or {@link AbstractOutline#execCreateChildPages(List)}.
@@ -266,7 +280,7 @@
     setEnabled(getConfiguredEnabled());
     setVisible(getConfiguredVisible());
     setOrder(calculateViewOrder());
-    setBreadcrumbEnabled(getConfiguredBreadcrumbEnabled());
+    setNavigateButtonsVisible(getConfiguredNavigateButtonsVisible());
     ensureDefaultDetailFormCreated();
     ensureDefaultDetailFormStarted();
   }
@@ -459,13 +473,13 @@
   }
 
   @Override
-  public boolean isBreadcrumbEnabled() {
-    return propertySupport.getPropertyBool(PROP_BREADCRUMB_ENABLED);
+  public boolean isNavigateButtonsVisible() {
+    return propertySupport.getPropertyBool(PROP_NAVIGATE_BUTTONS_VISIBLE);
   }
 
   @Override
-  public void setBreadcrumbEnabled(boolean b) {
-    propertySupport.setPropertyBool(PROP_BREADCRUMB_ENABLED, b);
+  public void setNavigateButtonsVisible(boolean b) {
+    propertySupport.setPropertyBool(PROP_NAVIGATE_BUTTONS_VISIBLE, b);
   }
 
   @Override
@@ -509,12 +523,12 @@
 
   @Override
   public double getOrder() {
-    return propertySupport.getPropertyDouble(PROP_VIEW_ORDER);
+    return propertySupport.getPropertyDouble(PROP_ORDER);
   }
 
   @Override
   public void setOrder(double order) {
-    propertySupport.setPropertyDouble(PROP_VIEW_ORDER, order);
+    propertySupport.setPropertyDouble(PROP_ORDER, order);
   }
 
   @Override
@@ -602,7 +616,7 @@
    * @see IOutline#getMenusForPage(IPage)
    */
   protected List<IMenu> computeInheritedMenusOfPage(IPage<?> activePage) {
-    List<IMenu> menus = new ArrayList<IMenu>();
+    List<IMenu> menus = new ArrayList<>();
     if (activePage instanceof IPageWithTable<?>) {
       // in case of a page with table the empty space actions of the table will be added to the context menu of the tree.
       IPageWithTable<?> pageWithTable = (IPageWithTable<?>) activePage;
@@ -620,7 +634,7 @@
   }
 
   protected void addMenusOfActivePageToContextMenu(IPage<?> activePage) {
-    List<IMenu> wrappedMenus = new ArrayList<IMenu>();
+    List<IMenu> wrappedMenus = new ArrayList<>();
     for (IMenu m : computeInheritedMenusOfPage(activePage)) {
       wrappedMenus.add(new OutlineMenuWrapper(m, TABLE_MENU_TYPE_MAPPER));
     }
@@ -676,6 +690,7 @@
     }
   }
 
+  @Override
   public void setDefaultDetailForm(IForm form) {
     if (form != null) {
       if (form.getDisplayHint() != IForm.DISPLAY_HINT_VIEW) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractSearchOutline.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractSearchOutline.java
index e878d9f..2cd339b 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractSearchOutline.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/AbstractSearchOutline.java
@@ -15,7 +15,7 @@
 import org.eclipse.scout.rt.shared.AbstractIcons;
 import org.eclipse.scout.rt.shared.TEXTS;
 
-public class AbstractSearchOutline extends AbstractOutline implements ISearchOutline {
+public abstract class AbstractSearchOutline extends AbstractOutline implements ISearchOutline {
 
   @Override
   protected String getConfiguredTitle() {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IFormToolButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IFormToolButton.java
index 14687aa..903bcaa 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IFormToolButton.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IFormToolButton.java
@@ -10,21 +10,13 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.client.ui.desktop.outline;
 
-import org.eclipse.scout.rt.client.ui.action.tool.IToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 
 /**
  * @since 3.8.1
+ * @deprecated use IFormMenu instead.
  */
-public interface IFormToolButton<FORM extends IForm> extends IToolButton {
-  String PROP_FORM = "form";
-
-  FORM getForm();
-
-  /**
-   * Set a new <b>started</b> form to the tool.
-   * <p>
-   * The form is shown whenever the tool button is activated.
-   */
-  void setForm(FORM f);
+@Deprecated
+public interface IFormToolButton<FORM extends IForm> extends IFormMenu<FORM> {
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutline.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutline.java
index 2b492a6..643cfb2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutline.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutline.java
@@ -63,9 +63,9 @@
    */
   String PROP_SEARCH_FORM = "searchForm";
 
-  String PROP_VIEW_ORDER = "viewOrder";
+  String PROP_ORDER = "order";
 
-  String PROP_BREADCRUMB_ENABLED = "breadcrumbEnabled";
+  String PROP_NAVIGATE_BUTTONS_VISIBLE = "navigateButtonsVisible";
 
   /**
    * alias to {@link ITree#getSelectedNode()}
@@ -117,15 +117,17 @@
 
   void setVisiblePermission(Permission p);
 
-  boolean isBreadcrumbEnabled();
+  boolean isNavigateButtonsVisible();
 
-  void setBreadcrumbEnabled(boolean b);
+  void setNavigateButtonsVisible(boolean b);
 
   /**
    * @return the default detail form if no page is active (selected)
    */
   IForm getDefaultDetailForm();
 
+  void setDefaultDetailForm(IForm form);
+
   /**
    * @return the detail form of the active (selected) page {@link IPage#getDetailForm()}
    */
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutlineViewButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutlineViewButton.java
index e212448..17ff5d0 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutlineViewButton.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/IOutlineViewButton.java
@@ -15,7 +15,7 @@
 
 public interface IOutlineViewButton extends IViewButton {
 
-  IDesktop getDesktop();
+  IDesktop getDesktop(); // FIXME AWE: remove? makes no sense...
 
   IOutline getOutline();
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/ISearchFormToolButton.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/ISearchFormToolButton.java
deleted file mode 100644
index 8c90edd..0000000
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/ISearchFormToolButton.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.client.ui.desktop.outline;
-
-import org.eclipse.scout.rt.client.ui.desktop.outline.pages.ISearchForm;
-
-/**
- * @since 3.8.1
- */
-public interface ISearchFormToolButton<FORM extends ISearchForm> extends IFormToolButton<FORM> {
-}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AbstractPageWithTable.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AbstractPageWithTable.java
index 30ff6ea..062b750 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AbstractPageWithTable.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AbstractPageWithTable.java
@@ -84,6 +84,7 @@
   private boolean m_searchRequired;
   private boolean m_searchActive;
   private boolean m_limitedResult;
+  private boolean m_alwaysCreateChildPage;
 
   public AbstractPageWithTable() {
     this(true, null);
@@ -164,7 +165,7 @@
    * <p>
    * Subclasses can override this method. Default is {@code true}.
    *
-   * @since 5.1.0
+   * @since 5.1
    * @see ITable#setTableStatusVisible(boolean)
    */
   @ConfigProperty(ConfigProperty.BOOLEAN)
@@ -180,6 +181,22 @@
   }
 
   /**
+   * Configures whether a default child page should be created for each table row if no page is created by
+   * {@link #execCreateChildPage(ITableRow)}.
+   * <p>
+   * Subclasses can override this method. Default is {@code false}.
+   *
+   * @since 6.0
+   * @see #execCreateChildPage(ITableRow)
+   * @see #createDefaultChildPage(ITableRow)
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(140)
+  protected boolean getConfiguredAlwaysCreateChildPage() {
+    return false;
+  }
+
+  /**
    * Fetches data and loads them into the page's table.
    * <p/>
    * Typically subclasses override this method if this table page is using a bean-based table page data (i.e. an
@@ -276,6 +293,10 @@
     return null;
   }
 
+  protected IPage<?> createDefaultChildPage(ITableRow row) {
+    return new AutoLeafPageWithNodes(row);
+  }
+
   protected IPage<?> createChildPageInternal(final ITableRow row) {
     return ClientRunContexts.copyCurrent()
         .withOutline(getOutline(), true)
@@ -283,7 +304,11 @@
 
           @Override
           public IPage<?> call() throws Exception {
-            return interceptCreateChildPage(row);
+            IPage<?> childPage = interceptCreateChildPage(row);
+            if (childPage == null && isAlwaysCreateChildPage()) {
+              childPage = createDefaultChildPage(row);
+            }
+            return childPage;
           }
         });
   }
@@ -308,12 +333,24 @@
   @ConfigOperation
   @Order(111)
   protected IPage<?> execCreateVirtualChildPage(ITableRow row) {
-    if (ConfigurationUtility.isMethodOverwrite(AbstractPageWithTable.class, "execCreateChildPage", new Class[]{ITableRow.class}, AbstractPageWithTable.this.getClass())) {
-      return new VirtualPage();
+    if (!isLeaf()) {
+      return createVirtualChildPage(row);
     }
     return null;
   }
 
+  protected IPage<?> createVirtualChildPageInternal(ITableRow row) {
+    IPage<?> virtualPage = interceptCreateVirtualChildPage(row);
+    if (virtualPage == null && isAlwaysCreateChildPage()) {
+      virtualPage = createVirtualChildPage(row);
+    }
+    return virtualPage;
+  }
+
+  protected IPage<?> createVirtualChildPage(ITableRow row) {
+    return new VirtualPage();
+  }
+
   /**
    * Resolves a virtual tree node and returns the real tree node.
    * <p>
@@ -360,6 +397,7 @@
     super.initConfig();
     m_searchActive = true;
     setSearchRequired(getConfiguredSearchRequired());
+    setAlwaysCreateChildPage(getConfiguredAlwaysCreateChildPage());
   }
 
   @Override
@@ -663,6 +701,16 @@
   }
 
   @Override
+  public boolean isAlwaysCreateChildPage() {
+    return m_alwaysCreateChildPage;
+  }
+
+  @Override
+  public void setAlwaysCreateChildPage(boolean alwaysCreateChildPage) {
+    m_alwaysCreateChildPage = alwaysCreateChildPage;
+  }
+
+  @Override
   public void pageActivatedNotify() {
     ensureInitialized();
     ensureSearchFormCreated();
@@ -923,7 +971,7 @@
             List<ITableRow> tableRows = e.getRows();
             for (ITableRow element : tableRows) {
               try {
-                IPage<?> childPage = interceptCreateVirtualChildPage(element);
+                IPage<?> childPage = createVirtualChildPageInternal(element);
                 if (childPage != null) {
                   ICell tableCell = getTable().getSummaryCell(element);
                   updateCellFromTableCell(childPage.getCellForUpdate(), tableCell);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AutoLeafPageWithNodes.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AutoLeafPageWithNodes.java
index 282828a..5f48673 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AutoLeafPageWithNodes.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/AutoLeafPageWithNodes.java
@@ -14,28 +14,21 @@
 import org.eclipse.scout.rt.client.ui.basic.table.ITableRow;
 import org.eclipse.scout.rt.client.ui.basic.table.columns.IColumn;
 
-// FIXME cgu: is AutoLeafPageWithNodes still needed? currently not used by CRM or somewhere else.
 public class AutoLeafPageWithNodes extends AbstractPageWithNodes {
   private ITableRow m_tableRow;
-  private IPage<?> m_actualParentPage;
 
-  public AutoLeafPageWithNodes(ITableRow row, IPage<?> parentPage) {
+  public AutoLeafPageWithNodes(ITableRow row) {
     if (row == null) {
       throw new IllegalArgumentException("Row must not be null");
     }
 
     m_tableRow = row;
-    m_actualParentPage = parentPage;
   }
 
   public ITableRow getTableRow() {
     return m_tableRow;
   }
 
-  public IPage<?> getActualParentPage() {
-    return m_actualParentPage;
-  }
-
   @Override
   protected void execInitPage() {
     Cell cell = getCellForUpdate();
@@ -47,7 +40,7 @@
     }
   }
 
-  private String findAppropriateTitle() {
+  protected String findAppropriateTitle() {
     for (IColumn<?> column : m_tableRow.getTable().getColumns()) {
       if (column.isVisible()) {
         return m_tableRow.getTable().getCell(m_tableRow, column).getText();
@@ -63,6 +56,11 @@
   }
 
   @Override
+  protected boolean getConfiguredDetailFormVisible() {
+    return false;
+  }
+
+  @Override
   protected boolean getConfiguredLeaf() {
     return true;
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/IPageWithTable.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/IPageWithTable.java
index 85a42e9..ca7f360 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/IPageWithTable.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/IPageWithTable.java
@@ -50,6 +50,16 @@
   void setSearchActive(boolean b);
 
   /**
+   * @since 6.0
+   */
+  boolean isAlwaysCreateChildPage();
+
+  /**
+   * @since 6.0
+   */
+  void setAlwaysCreateChildPage(boolean autoCreateLeafPage);
+
+  /**
    * Convenience for getting the search filter from the page's search form
    *
    * @return life reference to the filter (never null)
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/VirtualPage.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/VirtualPage.java
index e37d78d..8bf6dbd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/VirtualPage.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/desktop/outline/pages/VirtualPage.java
@@ -36,11 +36,9 @@
  */
 public class VirtualPage extends VirtualTreeNode implements IPage, IVirtualTreeNode {
 
-  public VirtualPage() {
-  }
-
   @Override
   public void initPage() {
+    // NOP
   }
 
   @Override
@@ -70,10 +68,12 @@
 
   @Override
   public void pageActivatedNotify() {
+    // NOP
   }
 
   @Override
   public void pageDeactivatedNotify() {
+    // NOP
   }
 
   @Override
@@ -83,14 +83,17 @@
 
   @Override
   public void setDetailForm(IForm form) {
+    // NOP
   }
 
   @Override
   public void dataChanged(Object... dataTypes) {
+    // NOP
   }
 
   @Override
   public final void reloadPage() {
+    // NOP
   }
 
   @Override
@@ -105,6 +108,7 @@
 
   @Override
   public void setTableVisible(boolean b) {
+    // NOP
   }
 
   @Override
@@ -114,6 +118,7 @@
 
   @Override
   public void setTableStatus(IStatus tableStatus) {
+    // NOP
   }
 
   @Override
@@ -123,6 +128,7 @@
 
   @Override
   public void setTableStatusVisible(boolean tableStatusVisible) {
+    // NOP
   }
 
   /**
@@ -140,6 +146,7 @@
 
   @Override
   public void setDetailFormVisible(boolean visible) {
+    // NOP
   }
 
   @Override
@@ -179,5 +186,6 @@
 
   @Override
   public void setLazyExpandingEnabled(boolean lazyAddChildPagesToOutline) {
+    // NOP
   }
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractForm.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractForm.java
index 1a9aad9..bf53d1a 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractForm.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractForm.java
@@ -65,7 +65,6 @@
 import org.eclipse.scout.rt.client.ui.IDisplayParent;
 import org.eclipse.scout.rt.client.ui.IEventHistory;
 import org.eclipse.scout.rt.client.ui.WeakDataChangeListener;
-import org.eclipse.scout.rt.client.ui.action.tool.IToolButton;
 import org.eclipse.scout.rt.client.ui.basic.filechooser.FileChooser;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
@@ -128,8 +127,6 @@
 import org.eclipse.scout.rt.shared.data.form.AbstractFormData;
 import org.eclipse.scout.rt.shared.data.form.IPropertyHolder;
 import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
-import org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData;
-import org.eclipse.scout.rt.shared.data.form.fields.tablefield.AbstractTableFieldData;
 import org.eclipse.scout.rt.shared.data.form.properties.AbstractPropertyData;
 import org.eclipse.scout.rt.shared.extension.AbstractExtension;
 import org.eclipse.scout.rt.shared.extension.ContributionComposite;
@@ -194,8 +191,6 @@
 
   private String m_classId;
 
-  private int m_toolbarLocation;
-
   private final PreferredValue<IDisplayParent> m_displayParent = new PreferredValue<>(null, false);
   private ClientRunContext m_initialClientRunContext; // ClientRunContext of the calling context during initialization.
 
@@ -429,17 +424,6 @@
     return null;
   }
 
-  /**
-   * {@link IForm#TOOLBAR_VIEW_PART}. In all other cases the fallback {@link IForm#TOOLBAR_FORM_HEADER} is taken.
-   *
-   * @return {@link IForm#TOOLBAR_FORM_HEADER} | {@link IForm#TOOLBAR_VIEW_PART}
-   */
-  @ConfigProperty(ConfigProperty.TOOLBAR_LOCATION)
-  @Order(160)
-  protected int getConfiguredToolbarLocation() {
-    return TOOLBAR_FORM_HEADER;
-  }
-
   @ConfigProperty(ConfigProperty.INTEGER)
   @Order(170)
   protected int/* seconds */ getConfiguredCloseTimer() {
@@ -604,11 +588,6 @@
     return ConfigurationUtility.filterClassesWithInjectFieldAnnotation(dca, IFormField.class);
   }
 
-  protected List<Class<IToolButton>> getConfiguredToolButtons() {
-    Class<?>[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
-    return ConfigurationUtility.filterClasses(dca, IToolButton.class);
-  }
-
   protected final void interceptInitConfig() {
     final Holder<RuntimeException> exceptionHolder = new Holder<>(RuntimeException.class, null);
     m_objectExtensions.initConfig(createLocalExtension(), new Runnable() {
@@ -629,11 +608,9 @@
 
   protected void initConfig() {
     m_uiFacade = BEANS.get(ModelContextProxy.class).newProxy(new P_UIFacade(), ModelContext.copyCurrent().withForm(this));
-
     m_timerFutureMap = new HashMap<>();
     setShowOnStart(getConfiguredShowOnStart());
     m_contributionHolder = new ContributionComposite(this);
-    setToolbarLocation(getConfiguredToolbarLocation());
 
     // prepare injected fields
     List<Class<IFormField>> fieldArray = getConfiguredInjectedFields();
@@ -801,28 +778,6 @@
     propertySupport.setPropertyString(PROP_ICON_ID, iconId);
   }
 
-  @Override
-  public String getPerspectiveId() {
-    return propertySupport.getPropertyString(PROP_PERSPECTIVE_ID);
-  }
-
-  @Override
-  public void setPerspectiveId(String perspectiveId) {
-    propertySupport.setPropertyString(PROP_PERSPECTIVE_ID, perspectiveId);
-  }
-
-  /**
-   * @param configuredToolbuttonLocation
-   */
-  private void setToolbarLocation(int toolbarLocation) {
-    m_toolbarLocation = toolbarLocation;
-  }
-
-  @Override
-  public int getToolbarLocation() {
-    return m_toolbarLocation;
-  }
-
   /**
    * Register a {@link DataChangeListener} on the desktop for these dataTypes<br>
    * Example:
@@ -1185,15 +1140,10 @@
   }
 
   private static Class<?> getFieldStopClass(Object data) {
-    if (data instanceof AbstractTableFieldData) {
-      return AbstractTableFieldData.class;
+    if (data instanceof AbstractFormFieldData) {
+      return ((AbstractFormFieldData) data).getFieldStopClass();
     }
-    else if (data instanceof AbstractValueFieldData) {
-      return AbstractValueFieldData.class;
-    }
-    else {
-      return AbstractFormFieldData.class;
-    }
+    return AbstractFormFieldData.class;
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractFormMenu.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractFormMenu.java
new file mode 100644
index 0000000..4ae31b3
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/AbstractFormMenu.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.client.ui.form;
+
+import java.util.List;
+
+import org.eclipse.scout.rt.client.extension.ui.action.IActionExtension;
+import org.eclipse.scout.rt.client.extension.ui.form.FormMenuChains.FormMenuInitFormChain;
+import org.eclipse.scout.rt.client.extension.ui.form.IFormMenuExtension;
+import org.eclipse.scout.rt.client.ui.action.AbstractAction;
+import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.Order;
+import org.eclipse.scout.rt.platform.annotations.ConfigOperation;
+import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
+import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
+
+/**
+ * A tool button that can be used in the {@link IDesktop} to toggle a form in the tools area.
+ */
+public abstract class AbstractFormMenu<FORM extends IForm> extends AbstractMenu implements IFormMenu<FORM> {
+
+  @Override
+  protected boolean getConfiguredToggleAction() {
+    return true;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public FORM getForm() {
+    return (FORM) propertySupport.getProperty(PROP_FORM);
+  }
+
+  @Override
+  public void setForm(FORM f) {
+    propertySupport.setProperty(PROP_FORM, f);
+  }
+
+  /**
+   * Configures the form to be used with this button. The form is lazily created and started when the button gets
+   * selected.
+   * <p>
+   * Subclasses can override this method. Default is {@code null}.
+   *
+   * @return a form type token
+   * @see {@link #startForm(IForm)} for details how the form gets started
+   */
+  @ConfigProperty(ConfigProperty.FORM)
+  @Order(90)
+  protected Class<FORM> getConfiguredForm() {
+    return null;
+  }
+
+  /**
+   * Initializes the {@link IForm} associated with this button, and is invoked once the {@link IForm} is showed for the
+   * first time.
+   *
+   * @param form
+   *          the {@link IForm} to be initialized.
+   */
+  @ConfigOperation
+  @Order(120)
+  protected void execInitForm(IForm form) {
+  }
+
+  @Override
+  protected void execSelectionChanged(boolean selected) {
+    if (!selected) {
+      return;
+    }
+    ensureFormCreated();
+    ensureFormStarted();
+  }
+
+  public void ensureFormCreated() {
+    if (getForm() != null) {
+      return;
+    }
+    FORM form = createForm();
+    if (form != null) {
+      form.addFormListener(new FormListener() {
+        @Override
+        public void formChanged(FormEvent e) {
+          if (e.getType() == FormEvent.TYPE_CLOSED) {
+            setSelected(false);
+            setForm(null);
+          }
+        }
+      });
+      decorateForm(form);
+      interceptInitForm(form);
+      setForm(form);
+    }
+  }
+
+  public void ensureFormStarted() {
+    if (getForm() == null || !getForm().isFormStartable()) {
+      return;
+    }
+    startForm();
+  }
+
+  protected FORM createForm() {
+    if (getConfiguredForm() == null) {
+      return null;
+    }
+    try {
+      return getConfiguredForm().newInstance();
+    }
+    catch (Exception e) {
+      BEANS.get(ExceptionHandler.class).handle(new ProcessingException("error creating instance of class '" + getConfiguredForm().getName() + "'.", e));
+    }
+    return null;
+  }
+
+  /**
+   * Starts the form.
+   * <p>
+   * The default uses {@link IForm#start()} and therefore expects a form handler to be previously set. Override to call
+   * a custom start method.
+   */
+  protected void startForm() {
+    getForm().start();
+  }
+
+  protected void decorateForm(IForm form) {
+    form.setShowOnStart(false);
+    form.setDisplayHint(IForm.DISPLAY_HINT_VIEW); // FIXME dwi: set in UI instead
+    form.setDisplayViewId(IForm.VIEW_ID_E); // FIXME dwi: set in UI instead
+  }
+
+  protected final void interceptInitForm(FORM form) {
+    List<? extends IActionExtension<? extends AbstractAction>> extensions = getAllExtensions();
+    FormMenuInitFormChain<FORM> chain = new FormMenuInitFormChain<>(extensions);
+    chain.execInitForm(form);
+  }
+
+  @Override
+  public void disposeInternal() {
+    super.disposeInternal();
+    FORM form = getForm();
+    if (form != null) {
+      form.doClose();
+    }
+  }
+
+  protected static class LocalFormMenuExtension<FORM extends IForm, OWNER extends AbstractFormMenu<FORM>> extends LocalMenuExtension<OWNER> implements IFormMenuExtension<FORM, OWNER> {
+
+    public LocalFormMenuExtension(OWNER owner) {
+      super(owner);
+    }
+
+    @Override
+    public void execInitForm(FormMenuInitFormChain<FORM> chain, FORM form) {
+      getOwner().execInitForm(form);
+    }
+  }
+
+  @Override
+  protected IFormMenuExtension<FORM, ? extends AbstractFormMenu<FORM>> createLocalExtension() {
+    return new LocalFormMenuExtension<FORM, AbstractFormMenu<FORM>>(this);
+  }
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IForm.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IForm.java
index a440e33..906a7e9 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IForm.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IForm.java
@@ -62,7 +62,6 @@
   String PROP_EMPTY = "empty";
   String PROP_SAVE_NEEDED = "saveNeeded";
   String PROP_ICON_ID = "iconId";
-  String PROP_PERSPECTIVE_ID = "perspectiveId";
 
   /**
    * Hint to render an {@link IForm} as dialog in a separate window. A dialog can be modal or non-modal.
@@ -97,9 +96,6 @@
    */
   int MODALITY_HINT_MODELESS = 20;
 
-  int TOOLBAR_FORM_HEADER = 30;
-  int TOOLBAR_VIEW_PART = 31;
-
   String VIEW_ID_N = "N";
   String VIEW_ID_NE = "NE";
   String VIEW_ID_E = "E";
@@ -174,10 +170,6 @@
 
   void setIconId(String s);
 
-  String getPerspectiveId();
-
-  void setPerspectiveId(String s);
-
   /**
    * @return the {@link IWizard} that contains the step that started this form using startWizardStep
    */
@@ -694,9 +686,4 @@
 
   IFormUIFacade getUIFacade();
 
-  /**
-   * @return
-   */
-  int getToolbarLocation();
-
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IFormMenu.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IFormMenu.java
new file mode 100644
index 0000000..86113e1
--- /dev/null
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/IFormMenu.java
@@ -0,0 +1,19 @@
+package org.eclipse.scout.rt.client.ui.form;
+
+import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
+
+/**
+ * @since 6.0
+ */
+public interface IFormMenu<FORM extends IForm> extends IMenu {
+  String PROP_FORM = "form";
+
+  FORM getForm();
+
+  /**
+   * Set a new <b>started</b> form to the menu.
+   * <p>
+   * The form is shown whenever the menu is selected.
+   */
+  void setForm(FORM f);
+}
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/ScoutInfoForm.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/ScoutInfoForm.java
index 7d52b24..7a81455 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/ScoutInfoForm.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/ScoutInfoForm.java
@@ -75,7 +75,7 @@
         createLogoHtml(),
         createTitleHtml(),
         createHtmlTable(getProperties()));
-    return html.toEncodedHtml();
+    return html.toHtml();
   }
 
   protected IHtmlElement createLogoHtml() {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java
index b488297..c4e734c 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java
@@ -464,14 +464,21 @@
   }
 
   /**
-   * Sets the property on the field and on every child.
+   * Sets the property on the field and on every child. <br>
+   * During the initialization phase the children are not informed.
    *
    * @see #getConfiguredStatusVisible()
    */
   @Override
   public void setStatusVisible(boolean statusVisible) {
+    setStatusVisible(statusVisible, isInitialized());
+  }
+
+  @Override
+  public void setStatusVisible(boolean statusVisible, boolean recursive) {
     super.setStatusVisible(statusVisible);
-    if (isInitialized()) {
+
+    if (recursive) {
       for (IFormField f : m_fields) {
         f.setStatusVisible(statusVisible);
       }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
index e667e9e..dc3e93d 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractFormField.java
@@ -685,6 +685,19 @@
     return true;
   }
 
+  /**
+   * Configures the position of the status.
+   * <p>
+   * Subclasses can override this method. Default is {@value IFormField#STATUS_POSITION_DEFAULT}.
+   *
+   * @since 6.0
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(200)
+  protected String getConfiguredStatusPosition() {
+    return STATUS_POSITION_DEFAULT;
+  }
+
   private List<Class<? extends IKeyStroke>> getConfiguredKeyStrokes() {
     Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
     List<Class<IKeyStroke>> fca = ConfigurationUtility.filterClasses(dca, IKeyStroke.class);
@@ -795,6 +808,7 @@
     setLabelHorizontalAlignment(getConfiguredLabelHorizontalAlignment());
     setLabelVisible(getConfiguredLabelVisible());
     setStatusVisible(getConfiguredStatusVisible());
+    setStatusPosition(getConfiguredStatusPosition());
     setCssClass((getConfiguredCssClass()));
     if (getConfiguredBackgroundColor() != null) {
       setBackgroundColor((getConfiguredBackgroundColor()));
@@ -1297,7 +1311,7 @@
 
   @Override
   public String getFullyQualifiedLabel(String separator) {
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     IFormField p = getParentField();
     if (p != null) {
       String s = p.getFullyQualifiedLabel(separator);
@@ -1603,12 +1617,12 @@
 
   @Override
   public double getOrder() {
-    return propertySupport.getPropertyDouble(PROP_VIEW_ORDER);
+    return propertySupport.getPropertyDouble(PROP_ORDER);
   }
 
   @Override
   public void setOrder(double order) {
-    propertySupport.setPropertyDouble(PROP_VIEW_ORDER, order);
+    propertySupport.setPropertyDouble(PROP_ORDER, order);
   }
 
   @Override
@@ -1944,6 +1958,16 @@
   }
 
   @Override
+  public String getStatusPosition() {
+    return propertySupport.getPropertyString(PROP_STATUS_POSITION);
+  }
+
+  @Override
+  public void setStatusPosition(String statusPosition) {
+    propertySupport.setPropertyString(PROP_STATUS_POSITION, statusPosition);
+  }
+
+  @Override
   public void setLoading(boolean loading) {
     propertySupport.setPropertyBool(PROP_LOADING, loading);
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/ICompositeField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/ICompositeField.java
index ecdd0bb..071f070 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/ICompositeField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/ICompositeField.java
@@ -63,6 +63,13 @@
   <T extends IFormField> T getFieldByClass(Class<T> c);
 
   /**
+   * @param statusVisible
+   * @param recursive
+   *          true, if statusVisible property of the children should be changed as well
+   */
+  void setStatusVisible(boolean statusVisible, boolean recursive);
+
+  /**
    * for recursion
    */
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/IFormField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/IFormField.java
index 4e13cd2..38ec8e1 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/IFormField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/IFormField.java
@@ -71,7 +71,7 @@
   String PROP_VISIBLE = "visible";
   String PROP_ENABLED = "enabled";
   String PROP_MANDATORY = "mandatory";
-  String PROP_VIEW_ORDER = "viewOrder";
+  String PROP_ORDER = "order";
   String PROP_ERROR_STATUS = "errorStatus";
   String PROP_TOOLTIP_TEXT = "tooltipText";
   String PROP_FOREGROUND_COLOR = "foregroundColor";
@@ -86,6 +86,7 @@
   String PROP_LABEL_VISIBLE = "labelVisible";
   String PROP_KEY_STROKES = "keyStrokes";
   String PROP_STATUS_VISIBLE = "statusVisible";
+  String PROP_STATUS_POSITION = "statusPosition";
   String PROP_GRID_DATA = "gridData";
 
   /**
@@ -147,6 +148,10 @@
    */
   int LABEL_HORIZONTAL_ALIGNMENT_DEFAULT = 1000;
 
+  String STATUS_POSITION_DEFAULT = "default";
+
+  String STATUS_POSITION_TOP = "top";
+
   IForm getForm();
 
   /**
@@ -612,6 +617,10 @@
    */
   void setStatusVisible(boolean statusVisible);
 
+  String getStatusPosition();
+
+  void setStatusPosition(String statusPosition);
+
   /**
    * @return true, if the mandatory property is fulfilled (a value set or not mandatory)
    */
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/beanfield/AbstractBeanField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/beanfield/AbstractBeanField.java
index 6a22125..b3d14e4 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/beanfield/AbstractBeanField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/beanfield/AbstractBeanField.java
@@ -26,7 +26,7 @@
 /**
  * This field may be used if the value is relevant for the gui, and not just the display text.
  */
-public class AbstractBeanField<VALUE> extends AbstractValueField<VALUE> implements IBeanField<VALUE> {
+public abstract class AbstractBeanField<VALUE> extends AbstractValueField<VALUE> implements IBeanField<VALUE> {
   private IBeanFieldUIFacade m_uiFacade;
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
index 71cd08a..14a82ec 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/AbstractBrowserField.java
@@ -34,8 +34,10 @@
 import org.eclipse.scout.rt.platform.annotations.Internal;
 import org.eclipse.scout.rt.platform.classid.ClassId;
 import org.eclipse.scout.rt.platform.resource.BinaryResource;
+import org.eclipse.scout.rt.platform.util.Assertions;
 import org.eclipse.scout.rt.platform.util.CompareUtility;
 import org.eclipse.scout.rt.platform.util.EventListenerList;
+import org.eclipse.scout.rt.shared.data.form.fields.AbstractFormFieldData;
 import org.eclipse.scout.rt.shared.data.form.fields.browserfield.AbstractBrowserFieldData;
 import org.eclipse.scout.rt.shared.services.common.jdbc.SearchFilter;
 import org.slf4j.Logger;
@@ -123,6 +125,30 @@
   }
 
   @Override
+  public void importFormFieldData(AbstractFormFieldData source, boolean valueChangeTriggersEnabled) {
+    Assertions.assertNotNull(source);
+    AbstractBrowserFieldData fd = (AbstractBrowserFieldData) source;
+
+    if (source.isValueSet()) {
+      try {
+        if (!valueChangeTriggersEnabled) {
+          setValueChangeTriggerEnabled(false);
+        }
+
+        setLocationInternal(fd.getLocation());
+        setBinaryResourceInternal(fd.getBinaryResource());
+        setAttachmentsInternal(fd.getAttachments());
+        fireContentChanged();
+      }
+      finally {
+        if (!valueChangeTriggersEnabled) {
+          setValueChangeTriggerEnabled(true);
+        }
+      }
+    }
+  }
+
+  @Override
   protected void applySearchInternal(SearchFilter search) {
     //nop
   }
@@ -250,12 +276,12 @@
   }
 
   protected void setScrollBarEnabled(boolean scrollBarEnabled) {
-    propertySupport.setProperty(PROP_SCROLLBARS_ENABLED, scrollBarEnabled);
+    propertySupport.setProperty(PROP_SCROLL_BAR_ENABLED, scrollBarEnabled);
   }
 
   @Override
   public boolean isScrollBarEnabled() {
-    return propertySupport.getPropertyBool(PROP_SCROLLBARS_ENABLED);
+    return propertySupport.getPropertyBool(PROP_SCROLL_BAR_ENABLED);
   }
 
   protected BinaryResource resolveBinaryResource(String filename) {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
index b56dd1a..0700544 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/BrowserFieldEvent.java
@@ -39,7 +39,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append(getClass().getSimpleName() + "[");
     // decode type
     try {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
index 4c21a99..ea82c45 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/browserfield/IBrowserField.java
@@ -57,8 +57,7 @@
   String PROP_LOCATION = "location";
   String PROP_BINARY_RESOURCE = "binaryResource";
   String PROP_ATTACHMENTS = "attachments";
-  // FIXME awe: fix name-inconsistency, constant-name VS property-name VS method-name SCROLLBARS, scrollBars, scrollBar
-  String PROP_SCROLLBARS_ENABLED = "scrollBarsEnabled";
+  String PROP_SCROLL_BAR_ENABLED = "scrollBarEnabled";
   String PROP_SANDBOX_ENABLED = "sandboxEnabled";
   String PROP_SANDBOX_PERMISSIONS = "sandboxPermissions";
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/composer/node/EntityNode.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/composer/node/EntityNode.java
index 067c002..d99250f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/composer/node/EntityNode.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/composer/node/EntityNode.java
@@ -58,7 +58,7 @@
 
   @Override
   protected void execDecorateCell(Cell cell) {
-    StringBuffer label = new StringBuffer();
+    StringBuilder label = new StringBuilder();
     if (getSiblingBefore() != null) {
       label.append(ScoutTexts.get("ExtendedSearchAnd") + " ");
     }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/AbstractDateField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/AbstractDateField.java
index 390086d..b5f46e7 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/AbstractDateField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/AbstractDateField.java
@@ -12,7 +12,10 @@
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 
 import org.eclipse.scout.rt.client.ModelContextProxy;
 import org.eclipse.scout.rt.client.ModelContextProxy.ModelContext;
@@ -23,11 +26,15 @@
 import org.eclipse.scout.rt.platform.Order;
 import org.eclipse.scout.rt.platform.annotations.ConfigProperty;
 import org.eclipse.scout.rt.platform.classid.ClassId;
+import org.eclipse.scout.rt.platform.exception.ProcessingStatus;
+import org.eclipse.scout.rt.platform.exception.VetoException;
 import org.eclipse.scout.rt.platform.nls.NlsLocale;
+import org.eclipse.scout.rt.platform.status.IStatus;
 import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.eclipse.scout.rt.platform.util.date.DateFormatProvider;
 import org.eclipse.scout.rt.platform.util.date.DateUtility;
 import org.eclipse.scout.rt.shared.ScoutTexts;
+import org.eclipse.scout.rt.shared.TEXTS;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -165,6 +172,7 @@
     setDateFormatPattern(getConfiguredDateFormatPattern());
     setTimeFormatPattern(getConfiguredTimeFormatPattern());
     setFormat(getConfiguredFormat());
+    setAllowedDates(Collections.<Date> emptyList());
   }
 
   @Override
@@ -288,15 +296,45 @@
     return m_uiFacade;
   }
 
-  // format value for display
   @Override
   protected String formatValueInternal(Date validValue) {
     if (validValue == null) {
       return "";
     }
-    DateFormat df = getDateFormat();
-    String displayValue = df.format(validValue);
-    return displayValue;
+    DateFormat dateFormat;
+    StringBuilder sb = new StringBuilder();
+    dateFormat = getIsolatedDateFormat();
+    sb.append(dateFormat == null ? "" : dateFormat.format(validValue));
+    sb.append("\n");
+    dateFormat = getIsolatedTimeFormat();
+    sb.append(dateFormat == null ? "" : dateFormat.format(validValue));
+    return sb.toString();
+  }
+
+  @Override
+  protected Date validateValueInternal(Date rawValue) {
+    rawValue = super.validateValueInternal(rawValue);
+
+    if (rawValue == null) {
+      return null;
+    }
+
+    // Check if date is allowed (if allowed dates are set)
+    if (getAllowedDates().size() > 0) {
+      Date truncDate = DateUtility.truncDate(rawValue);
+      boolean found = false;
+      for (Date allowedDate : getAllowedDates()) {
+        if (allowedDate.compareTo(truncDate) == 0) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        throw new VetoException(new ProcessingStatus(TEXTS.get("DateIsNotAllowed"), IStatus.ERROR));
+      }
+    }
+
+    return rawValue;
   }
 
   @Override
@@ -309,15 +347,6 @@
     setValue(DateUtility.convertDoubleTimeToDate(d));
   }
 
-  /**
-   * Should only be used by scout itself. Setting the display text does not trigger a change in the UI. Only the value
-   * is used and formatted in the UI.
-   */
-  @Override
-  public void setDisplayText(String s) {
-    super.setDisplayText(s); // NOSONAR override for javadoc
-  }
-
   protected Date applyAutoDate(Date d) {
     if (d != null) {
       return d;
@@ -375,6 +404,29 @@
     return null;
   }
 
+  @Override
+  public void setAllowedDates(List<Date> allowedDates) {
+    if (allowedDates == null) {
+      allowedDates = Collections.emptyList();
+    }
+    else {
+      // Make sure each date is truncated and the list of dates is ordered by date
+      List<Date> sortedTruncatedDates = new ArrayList<>(allowedDates.size());
+      for (Date date : allowedDates) {
+        sortedTruncatedDates.add(DateUtility.truncDate(date));
+      }
+      Collections.sort(sortedTruncatedDates);
+      allowedDates = sortedTruncatedDates;
+    }
+    propertySupport.setProperty(PROP_ALLOWED_DATES, allowedDates);
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public List<Date> getAllowedDates() {
+    return new ArrayList<>((List<Date>) propertySupport.getProperty(PROP_ALLOWED_DATES));
+  }
+
   protected class P_UIFacade implements IDateFieldUIFacade {
 
     @Override
@@ -386,11 +438,18 @@
     }
 
     @Override
-    public void setParseErrorFromUI(String invalidDisplayText, String invalidDateText, String invalidTimeText) {
-      String invalidText = StringUtility.nvl(invalidDisplayText, StringUtility.join(" ", invalidDateText, invalidTimeText));
-      ParsingFailedStatus status = new ParsingFailedStatus(ScoutTexts.get("InvalidValueMessageX", invalidText), StringUtility.nvl(invalidDateText, "") + "\n" + StringUtility.nvl(invalidTimeText, "")); // don't use join()!
+    public void setDisplayTextFromUI(String text) {
+      if (!isEnabled() || !isVisible()) {
+        return;
+      }
+      setDisplayText(text);
+    }
+
+    @Override
+    public void setParseErrorFromUI() {
+      String invalidMessage = getDisplayText().replace("\n", " ");
+      ParsingFailedStatus status = new ParsingFailedStatus(ScoutTexts.get("InvalidValueMessageX", invalidMessage), getDisplayText());
       addErrorStatus(status);
-      setDisplayText(invalidText);
     }
 
     @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateField.java
index de9eff2..c8e829d 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateField.java
@@ -12,6 +12,7 @@
 
 import java.text.DateFormat;
 import java.util.Date;
+import java.util.List;
 
 import org.eclipse.scout.rt.client.ui.form.fields.IValueField;
 
@@ -22,6 +23,7 @@
   String PROP_DATE_FORMAT_PATTERN = "dateFormatPattern";
   String PROP_TIME_FORMAT_PATTERN = "timeFormatPattern";
   String PROP_AUTO_DATE = "autoDate";
+  String PROP_ALLOWED_DATES = "allowedDates";
 
   IDateFieldUIFacade getUIFacade();
 
@@ -76,12 +78,22 @@
   Date getAutoDate();
 
   /**
-   * @return the time value as a double in the range from [0..1[ for 00:00 - 23:59:59
+   * @return the time value as a double in the range from [0..1[ for 00:00 - 23:59:59.
    */
   Double getTimeValue();
 
   /**
-   * set the time value as a double in the range from [0..1[ for 00:00 - 23:59:59
+   * Set the time value as a double in the range from [0..1[ for 00:00 - 23:59:59.
    */
   void setTimeValue(Double d);
+
+  /**
+   * Sets a list of allowed dates. When the given list is not empty or null only the dates contained in the list can be
+   * chosen in the date-picker or entered manually in the date-field. All other dates are disabled. When the list is
+   * empty or null all dates are available again.
+   */
+  void setAllowedDates(List<Date> allowedDates);
+
+  List<Date> getAllowedDates();
+
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateFieldUIFacade.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateFieldUIFacade.java
index 54aee4f..85abc0f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateFieldUIFacade.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/datefield/IDateFieldUIFacade.java
@@ -16,7 +16,9 @@
 
   void setDateTimeFromUI(Date d);
 
-  void setParseErrorFromUI(String invalidDisplayText, String invalidDateText, String invalidTimeText);
+  void setDisplayTextFromUI(String text);
+
+  void setParseErrorFromUI();
 
   void removeParseErrorFromUI();
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/groupbox/internal/GridCell.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/groupbox/internal/GridCell.java
index ae457ba..aa117c5 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/groupbox/internal/GridCell.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/groupbox/internal/GridCell.java
@@ -183,7 +183,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append(getClass().getSimpleName());
     buf.append("[");
     buf.append(data);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/AbstractHtmlField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/AbstractHtmlField.java
index 917a08c..37bd228 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/AbstractHtmlField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/AbstractHtmlField.java
@@ -12,6 +12,7 @@
 
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
@@ -115,8 +116,8 @@
 
   public void setValueFromURL(URL url, String encoding) {
     if (url != null) {
-      try {
-        setValue(IOUtility.getContent(new InputStreamReader(url.openStream(), encoding)));
+      try (Reader in = new InputStreamReader(url.openStream(), encoding)) {
+        setValue(IOUtility.readString(in));
       }
       catch (IOException e) {
         throw new ProcessingException("URL " + url, e);
@@ -176,13 +177,12 @@
 
   @Override
   public void setScrollBarEnabled(boolean scrollBarEnabled) {
-    // TODO [5.2] bsh, awe: Cleanup scroll[bB]ar[s] confusion
-    propertySupport.setPropertyBool(PROP_SCROLLBARS_ENABLED, scrollBarEnabled);
+    propertySupport.setPropertyBool(PROP_SCROLL_BAR_ENABLED, scrollBarEnabled);
   }
 
   @Override
   public boolean isScrollBarEnabled() {
-    return propertySupport.getPropertyBool(PROP_SCROLLBARS_ENABLED);
+    return propertySupport.getPropertyBool(PROP_SCROLL_BAR_ENABLED);
   }
 
   protected class P_UIFacade implements IHtmlFieldUIFacade {
@@ -195,17 +195,17 @@
 
   @Override
   public void setScrollToAnchor(String anchorName) {
-    propertySupport.setPropertyString(PROP_SCROLLBAR_SCROLL_TO_ANCHOR, anchorName);
+    propertySupport.setPropertyString(PROP_SCROLL_TO_ANCHOR, anchorName);
   }
 
   @Override
   public String getScrollToAnchor() {
-    return propertySupport.getPropertyString(PROP_SCROLLBAR_SCROLL_TO_ANCHOR);
+    return propertySupport.getPropertyString(PROP_SCROLL_TO_ANCHOR);
   }
 
   @Override
   public void scrollToEnd() {
-    propertySupport.setPropertyAlwaysFire(PROP_SCROLLBAR_SCROLL_TO_END, null);
+    propertySupport.setPropertyAlwaysFire(PROP_SCROLL_TO_END, null);
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/IHtmlField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/IHtmlField.java
index 202dd4a..a9f5023 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/IHtmlField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/htmlfield/IHtmlField.java
@@ -33,9 +33,9 @@
  */
 public interface IHtmlField extends IValueField<String>, IAppLinkCapable, IHtmlCapable {
 
-  String PROP_SCROLLBARS_ENABLED = "scrollBarsEnabled";
-  String PROP_SCROLLBAR_SCROLL_TO_END = "scrollToEnd";
-  String PROP_SCROLLBAR_SCROLL_TO_ANCHOR = "scrollToPosition";
+  String PROP_SCROLL_BAR_ENABLED = "scrollBarEnabled";
+  String PROP_SCROLL_TO_END = "scrollToEnd";
+  String PROP_SCROLL_TO_ANCHOR = "scrollToAnchor";
 
   void setScrollToAnchor(String anchorName);
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
index 2eb9db9..890ded8 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/listbox/AbstractListBox.java
@@ -857,6 +857,28 @@
  * Implementation of ICompositeField
  */
 
+  /**
+   * Sets the property on the field and on every child. <br>
+   * During the initialization phase the children are not informed.
+   *
+   * @see #getConfiguredStatusVisible()
+   */
+  @Override
+  public void setStatusVisible(boolean statusVisible) {
+    setStatusVisible(statusVisible, isInitialized());
+  }
+
+  @Override
+  public void setStatusVisible(boolean statusVisible, boolean recursive) {
+    super.setStatusVisible(statusVisible);
+
+    if (recursive) {
+      for (IFormField f : m_fields) {
+        f.setStatusVisible(statusVisible);
+      }
+    }
+  }
+
   @Override
   public <F extends IFormField> F getFieldByClass(Class<F> c) {
     return CompositeFieldUtility.getFieldByClass(this, c);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/radiobuttongroup/AbstractRadioButtonGroup.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/radiobuttongroup/AbstractRadioButtonGroup.java
index d43e204..7af6292 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/radiobuttongroup/AbstractRadioButtonGroup.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/radiobuttongroup/AbstractRadioButtonGroup.java
@@ -482,6 +482,28 @@
    */
 
   /**
+   * Sets the property on the field and on every child. <br>
+   * During the initialization phase the children are not informed.
+   *
+   * @see #getConfiguredStatusVisible()
+   */
+  @Override
+  public void setStatusVisible(boolean statusVisible) {
+    setStatusVisible(statusVisible, isInitialized());
+  }
+
+  @Override
+  public void setStatusVisible(boolean statusVisible, boolean recursive) {
+    super.setStatusVisible(statusVisible);
+
+    if (recursive) {
+      for (IFormField f : m_fields) {
+        f.setStatusVisible(statusVisible);
+      }
+    }
+  }
+
+  /**
    * broadcast this change to all children
    */
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/AbstractSequenceBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/AbstractSequenceBox.java
index 7cd886f..8d1b120 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/AbstractSequenceBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/sequencebox/AbstractSequenceBox.java
@@ -431,7 +431,7 @@
 
   @Override
   public String getFullyQualifiedLabel(String separator) {
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     IFormField p = getParentField();
     if (p != null) {
       String s = p.getFullyQualifiedLabel(separator);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractContentAssistField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractContentAssistField.java
index 3ce5be1..6dab23c 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractContentAssistField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractContentAssistField.java
@@ -13,6 +13,7 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -59,6 +60,7 @@
 import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
 import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedException;
 import org.eclipse.scout.rt.shared.ScoutTexts;
+import org.eclipse.scout.rt.shared.TEXTS;
 import org.eclipse.scout.rt.shared.data.basic.FontSpec;
 import org.eclipse.scout.rt.shared.services.common.code.ICodeType;
 import org.eclipse.scout.rt.shared.services.lookup.CodeLookupCall;
@@ -103,6 +105,14 @@
   private int m_proposalFormHeight;
   private String m_wildcard;
 
+  /**
+   * Provides the label-texts for the radio-buttons of the active-filter.
+   */
+  private String[] m_activeFilterLabels = {
+      TEXTS.get("ui.All"),
+      TEXTS.get("ui.Inactive"),
+      TEXTS.get("ui.Active")};
+
   private ILookupRow<LOOKUP_KEY> m_currentLookupRow;
 
   private volatile IFuture<?> m_lookupFuture;
@@ -490,6 +500,28 @@
   }
 
   @Override
+  public void setActiveFilterLabel(TriState state, String label) {
+    m_activeFilterLabels[getIndexForTriState(state)] = label;
+  }
+
+  @Override
+  public String[] getActiveFilterLabels() {
+    return Arrays.copyOf(m_activeFilterLabels, m_activeFilterLabels.length);
+  }
+
+  private int getIndexForTriState(TriState state) {
+    if (state.isUndefined()) {
+      return 0;
+    }
+    else if (state.isFalse()) {
+      return 1;
+    }
+    else {
+      return 2;
+    }
+  }
+
+  @Override
   public void setProposalFormHeight(int proposalFormHeight) {
     m_proposalFormHeight = proposalFormHeight;
   }
@@ -995,7 +1027,7 @@
   @Override
   public void doSearch(IContentAssistSearchParam<LOOKUP_KEY> param, boolean synchronous) {
     if (isProposalChooserRegistered()) {
-      getProposalChooser().setStatus(new Status(ScoutTexts.get("searchingProposals"), IStatus.WARNING));
+      getProposalChooser().setStatus(new Status(ScoutTexts.get("searchingProposals"), IStatus.OK));
     }
     getLookupRowFetcher().update(param, synchronous);
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractMixedSmartField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractMixedSmartField.java
index 1590f6b..9c69149 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractMixedSmartField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractMixedSmartField.java
@@ -34,6 +34,7 @@
 import org.eclipse.scout.rt.platform.job.Jobs;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.eclipse.scout.rt.platform.util.TriState;
 import org.eclipse.scout.rt.shared.ScoutTexts;
 import org.eclipse.scout.rt.shared.TEXTS;
 import org.eclipse.scout.rt.shared.services.lookup.ILookupRow;
@@ -142,7 +143,14 @@
       return true;
     }
     else if (lookupRows.size() == 1) {
-      acceptProposal(lookupRows.get(0));
+      lookupRow = lookupRows.get(0);
+      if (lookupRowAccepted(lookupRow)) {
+        acceptProposal(lookupRow);
+      }
+      else {
+        setValidationError(text, TEXTS.get("SmartFieldInactiveRow", text), NO_RESULTS_ERROR_CODE);
+        return true;
+      }
     }
     else if (lookupRows.size() > 1) {
       setValidationError(text, TEXTS.get("SmartFieldNotUnique", text), NOT_UNIQUE_ERROR_CODE);
@@ -151,6 +159,32 @@
     return false;
   }
 
+  private boolean lookupRowAccepted(ILookupRow<LOOKUP_KEY> lookupRow) {
+    if (!lookupRow.isEnabled()) {
+      // when row is disabled, dont allow
+      return false;
+    }
+    if (lookupRow.isActive()) {
+      // when row is active, allow
+      return true;
+    }
+    else if (!isProposalChooserRegistered()) {
+      // when proposal chooser is not opened, only allow active rows
+      return false;
+    }
+    else if (!getProposalChooser().isActiveFilterEnabled()) {
+      // when proposal chooser is openend, it depends on the settings of the active filter
+      // whether or not the row is allowed
+      return false;
+    }
+    else {
+      // when we active-filter is enabled, inactive rows are only allowed when filter
+      // is set to ALL (undefined) or INACTIVE (false)
+      TriState activeFilter = getProposalChooser().getActiveFilter();
+      return !activeFilter.isTrue();
+    }
+  }
+
   private boolean textEquals(String displayText, String lookupRowText) {
     return StringUtility.equalsIgnoreNewLines(StringUtility.emptyIfNull(displayText), StringUtility.emptyIfNull(lookupRowText));
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalChooser.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalChooser.java
index 2ff004f..61ef4c2 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalChooser.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalChooser.java
@@ -172,6 +172,11 @@
   }
 
   @Override
+  public String[] getActiveFilterLabels() {
+    return m_contentAssistField.getActiveFilterLabels();
+  }
+
+  @Override
   public void updateActiveFilter(TriState activeState) {
     m_contentAssistField.setActiveFilter(activeState);
     m_contentAssistField.doSearch(false, false);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalField.java
index 44b5924..7026880 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/AbstractProposalField.java
@@ -45,6 +45,7 @@
   @Override
   protected void initConfig() {
     super.initConfig();
+    setAutoCloseChooser(getConfiguredAutoCloseChooser());
     m_uiFacade = BEANS.get(ModelContextProxy.class).newProxy(new ContentAssistFieldUIFacade<LOOKUP_KEY>(this), ModelContext.copyCurrent());
   }
 
@@ -53,6 +54,17 @@
     return m_uiFacade;
   }
 
+  /**
+   * Configures whether the proposal chooser should automatically be closed when there are no proposals available.
+   * <p>
+   * Subclasses can override this method. Default is true.
+   *
+   * @since 6.0
+   */
+  protected boolean getConfiguredAutoCloseChooser() {
+    return true;
+  }
+
   @Override
   public void applyLazyStyles() {
   }
@@ -63,6 +75,16 @@
   }
 
   @Override
+  public void setAutoCloseChooser(boolean autoCloseChooser) {
+    propertySupport.setProperty(PROP_AUTO_CLOSE_CHOOSER, autoCloseChooser);
+  }
+
+  @Override
+  public boolean isAutoCloseChooser() {
+    return propertySupport.getPropertyBool(PROP_AUTO_CLOSE_CHOOSER);
+  }
+
+  @Override
   public void acceptProposal(ILookupRow<LOOKUP_KEY> row) {
     setCurrentLookupRow(row);
     setValue(row.getText());
@@ -164,7 +186,7 @@
     }
     IProposalChooser<?, LOOKUP_KEY> proposalChooser = getProposalChooser();
     Collection<? extends ILookupRow<LOOKUP_KEY>> rows = result.getLookupRows();
-    if (rows == null || rows.isEmpty()) {
+    if (isAutoCloseChooser() && (rows == null || rows.isEmpty())) {
       unregisterProposalChooserInternal();
     }
     else {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/ContentAssistFieldUIFacade.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/ContentAssistFieldUIFacade.java
index 4134845..5123171 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/ContentAssistFieldUIFacade.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/ContentAssistFieldUIFacade.java
@@ -100,6 +100,12 @@
 
     if (chooser) {
 
+      // last line of defense: normally the UI prevents this kind of request, but you never know...
+      if (!m_field.isProposalChooserRegistered()) {
+        LOG.debug("acceptProposalFromUI: UI says chooser is open, but the chooser has been unregistered on the model");
+        return;
+      }
+
       // When the proposal chooser is open, we must check if the display-text has changed
       // since the last search. When it has changed, we cannot use the accepted proposal
       // and must perform the lookup again instead. This prevents issues as described in
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IContentAssistField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IContentAssistField.java
index 2a8baaf..8394eef 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IContentAssistField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IContentAssistField.java
@@ -63,7 +63,22 @@
   /**
    * see {@link #isActiveFilterEnabled()}
    */
-  void setActiveFilterEnabled(boolean b);
+  void setActiveFilterEnabled(boolean enabled);
+
+  /**
+   * Changes the default-label text for the active-filter radio-button with the given state.
+   */
+  void setActiveFilterLabel(TriState state, String label);
+
+  /**
+   * Returns the label-texts of the active-filter radio-button in this order:
+   * <ol>
+   * <li>UNDEFINED</li>
+   * <li>FALSE</li>
+   * <li>TRUE</li>
+   * </ol>
+   */
+  String[] getActiveFilterLabels();
 
   /**
    * This has only an effect if {@link #isActiveFilterEnabled()} is set to true. true: include only active values false:
@@ -74,7 +89,7 @@
   /**
    * see {@link #getActiveFilter()}
    */
-  void setActiveFilter(TriState t);
+  void setActiveFilter(TriState state);
 
   String getBrowseIconId();
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalChooser.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalChooser.java
index a6bb7cc..85c92a6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalChooser.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalChooser.java
@@ -68,7 +68,13 @@
   TriState getActiveFilter();
 
   /**
-   * Delegates to contentAssistField to set the given activeState filter and triggers a new search.
+   * @return Delegates to {@link IContentAssistField#getActiveFilterLabels()}
+   */
+  String[] getActiveFilterLabels();
+
+  /**
+   * Delegates to {@link IContentAssistField#getActiveFilter()} to set the given activeState filter and triggers a new
+   * search.
    */
   void updateActiveFilter(TriState activeState);
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalField.java
index 376311f..c3ca259 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/smartfield/IProposalField.java
@@ -11,5 +11,18 @@
 package org.eclipse.scout.rt.client.ui.form.fields.smartfield;
 
 public interface IProposalField<LOOKUP_KEY> extends IContentAssistField<String, LOOKUP_KEY> {
+  /**
+   * {@link Boolean}
+   */
+  String PROP_AUTO_CLOSE_CHOOSER = "autoCloseChooser";
 
+  /**
+   * @since 6.0
+   */
+  void setAutoCloseChooser(boolean autoCloseChooser);
+
+  /**
+   * @since 6.0
+   */
+  boolean isAutoCloseChooser();
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/AbstractSplitBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/AbstractSplitBox.java
index 1bbd539..80be803 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/AbstractSplitBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/AbstractSplitBox.java
@@ -14,6 +14,7 @@
 import org.eclipse.scout.rt.client.ModelContextProxy.ModelContext;
 import org.eclipse.scout.rt.client.extension.ui.form.fields.splitbox.ISplitBoxExtension;
 import org.eclipse.scout.rt.client.ui.form.fields.AbstractCompositeField;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 import org.eclipse.scout.rt.client.ui.form.fields.splitbox.internal.SplitBoxGrid;
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.Order;
@@ -89,6 +90,24 @@
     return getClass().getName();
   }
 
+  @ConfigProperty(ConfigProperty.OBJECT)
+  @Order(370)
+  protected Class<? extends IFormField> getConfiguredCollapsibleField() {
+    return null;
+  }
+
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(380)
+  protected boolean getConfiguredFieldCollapsed() {
+    return false;
+  }
+
+  @ConfigProperty(ConfigProperty.STRING)
+  @Order(390)
+  protected String getConfiguredCollapseKeyStroke() {
+    return null;
+  }
+
   @Override
   protected void initConfig() {
     m_uiFacade = BEANS.get(ModelContextProxy.class).newProxy(new P_UIFacade(), ModelContext.copyCurrent());
@@ -100,6 +119,11 @@
     setSplitterPositionType(getConfiguredSplitterPositionType());
     setCacheSplitterPosition(getConfiguredCacheSplitterPosition());
     setCacheSplitterPositionPropertyName(getConfiguredCacheSplitterPositionPropertyName());
+    if (getConfiguredCollapsibleField() != null) {
+      setCollapsibleField(getFieldByClass(getConfiguredCollapsibleField()));
+    }
+    setFieldCollapsed(getConfiguredFieldCollapsed());
+    setCollapseKeyStroke(getConfiguredCollapseKeyStroke());
   }
 
   @Override
@@ -191,6 +215,36 @@
   }
 
   @Override
+  public void setCollapsibleField(IFormField field) {
+    propertySupport.setProperty(PROP_COLLAPSIBLE_FIELD, field);
+  }
+
+  @Override
+  public IFormField getCollapsibleField() {
+    return (IFormField) propertySupport.getProperty(PROP_COLLAPSIBLE_FIELD);
+  }
+
+  @Override
+  public void setFieldCollapsed(boolean collapsed) {
+    propertySupport.setProperty(PROP_FIELD_COLLAPSED, collapsed);
+  }
+
+  @Override
+  public boolean isFieldCollapsed() {
+    return propertySupport.getPropertyBool(PROP_FIELD_COLLAPSED);
+  }
+
+  @Override
+  public void setCollapseKeyStroke(String keyStroke) {
+    propertySupport.setProperty(PROP_COLLAPSE_KEY_STROKE, keyStroke);
+  }
+
+  @Override
+  public String getCollapseKeyStroke() {
+    return propertySupport.getPropertyString(PROP_COLLAPSE_KEY_STROKE);
+  }
+
+  @Override
   public ISplitBoxUIFacade getUIFacade() {
     return m_uiFacade;
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/ISplitBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/ISplitBox.java
index 3236af7..94336a8 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/ISplitBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/splitbox/ISplitBox.java
@@ -11,6 +11,7 @@
 package org.eclipse.scout.rt.client.ui.form.fields.splitbox;
 
 import org.eclipse.scout.rt.client.ui.form.fields.ICompositeField;
+import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 
 /**
  * <h3>ISplitBox</h3> ...
@@ -24,6 +25,9 @@
   String PROP_SPLIT_HORIZONTAL = "splitHorizontal";
   String PROP_SPLITTER_POSITION = "splitterPosition";
   String PROP_SPLITTER_POSITION_TYPE = "splitterPositionType";
+  String PROP_COLLAPSIBLE_FIELD = "collapsibleField";
+  String PROP_FIELD_COLLAPSED = "fieldCollapsed";
+  String PROP_COLLAPSE_KEY_STROKE = "collapseKeyStroke";
 
   /**
    * The splitter position is the size of the <b>first</b> inner box relative to full size of the split box, i.e. it is
@@ -96,5 +100,49 @@
 
   void setCacheSplitterPositionPropertyName(String propName);
 
+  /**
+   * Marks the first or the second field of the split box as collapsible, which displays the according button. Only one
+   * field of the split box can be collapsible.
+   *
+   * @since 6.0
+   */
+  void setCollapsibleField(IFormField field);
+
+  /**
+   * Returns the first or second form-field of the split box which is marked as collapsible or null when no part of the
+   * split box is collapsible.
+   *
+   * @since 6.0
+   */
+  IFormField getCollapsibleField();
+
+  /**
+   * Sets the collapsed state of the collapsible field. When no field is collapsible, the method does nothing.
+   *
+   * @since 6.0
+   */
+  void setFieldCollapsed(boolean collapsed);
+
+  /**
+   * Returns the collapsed state of the collapsible field. When no field is collapsible, the method returns false.
+   *
+   * @since 6.0
+   */
+  boolean isFieldCollapsed();
+
+  /**
+   * Sets the key-stroke used to trigger the collapse button.
+   *
+   * @since 6.0
+   */
+  void setCollapseKeyStroke(String keyStroke);
+
+  /**
+   * Returns the key-stroke used to trigger the collapse button.
+   *
+   * @since 6.0
+   */
+  String getCollapseKeyStroke();
+
   ISplitBoxUIFacade getUIFacade();
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
index d87ea4e..aa3d598 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/treebox/AbstractTreeBox.java
@@ -615,7 +615,7 @@
     if (validValue == null || validValue.size() == 0) {
       return "";
     }
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     Collection<ITreeNode> nodes = getTree().findNodes(validValue);
     if (nodes != null && !nodes.isEmpty()) {
       Iterator<ITreeNode> nodeIt = nodes.iterator();
@@ -981,6 +981,28 @@
  * Implementation of ICompositeField
  */
 
+  /**
+   * Sets the property on the field and on every child. <br>
+   * During the initialization phase the children are not informed.
+   *
+   * @see #getConfiguredStatusVisible()
+   */
+  @Override
+  public void setStatusVisible(boolean statusVisible) {
+    setStatusVisible(statusVisible, isInitialized());
+  }
+
+  @Override
+  public void setStatusVisible(boolean statusVisible, boolean recursive) {
+    super.setStatusVisible(statusVisible);
+
+    if (recursive) {
+      for (IFormField f : m_fields) {
+        f.setStatusVisible(statusVisible);
+      }
+    }
+  }
+
   @Override
   public <F extends IFormField> F getFieldByClass(Class<F> c) {
     return CompositeFieldUtility.getFieldByClass(this, c);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/AbstractWrappedFormField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/AbstractWrappedFormField.java
index 9d579c4..0c7e06f 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/AbstractWrappedFormField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/AbstractWrappedFormField.java
@@ -69,6 +69,16 @@
     return null;
   }
 
+  /**
+   * @return {@code true} if the inner form should request the initial focus once loaded, {@code false} otherwise.
+   *         Default is {@code false}.
+   */
+  @ConfigProperty(ConfigProperty.BOOLEAN)
+  @Order(210)
+  protected boolean getConfiguredInitialFocusEnabled() {
+    return false;
+  }
+
   @Override
   protected double getConfiguredGridWeightY() {
     return 1;
@@ -91,6 +101,7 @@
     m_innerFormPropertyListener = new P_InnerFormPropertyChangeListener();
     m_innerFormSubtreePropertyListener = new P_InnerFormSubtreePropertyChangeListener();
     m_innerFormListener = new P_InnerFormListener();
+    setInitialFocusEnabled(getConfiguredInitialFocusEnabled());
     if (getConfiguredInnerForm() != null) {
       try {
         setInnerForm((FORM) getConfiguredInnerForm().newInstance(), true);
@@ -168,6 +179,16 @@
     interceptInnerFormChanged(oldInnerForm, m_innerForm);
   }
 
+  @Override
+  public boolean isInitialFocusEnabled() {
+    return propertySupport.getPropertyBool(PROP_INITIAL_FOCUS_ENABLED);
+  }
+
+  @Override
+  public void setInitialFocusEnabled(boolean initialFocusEnabled) {
+    propertySupport.setPropertyBool(PROP_INITIAL_FOCUS_ENABLED, initialFocusEnabled);
+  }
+
   protected void installInnerForm() {
     if (m_innerForm == null) {
       return;
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/IWrappedFormField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/IWrappedFormField.java
index d2b83e4..11f12bd 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/IWrappedFormField.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/wrappedform/IWrappedFormField.java
@@ -25,6 +25,7 @@
    * {@link IForm}
    */
   String PROP_INNER_FORM = "innerForm";
+  String PROP_INITIAL_FOCUS_ENABLED = "initialFocusEnabled";
 
   /**
    * @return the current inner form.
@@ -54,5 +55,12 @@
    */
   void setInnerForm(T form, boolean manageFormLifeCycle);
 
+  /**
+   * @return {@code true} if the inner form should request the initial focus once loaded, {@code false} otherwise.
+   */
+  boolean isInitialFocusEnabled();
+
+  void setInitialFocusEnabled(boolean initialFocusEnabled);
+
   boolean visitFields(IFormFieldVisitor visitor, int startLevel);
 }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBox.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBox.java
index 89115cc..e4a90aa 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBox.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBox.java
@@ -261,7 +261,7 @@
       m_copyPasteTextInternal = StringUtility.join("\n\n",
           m_header,
           m_body,
-          m_html == null ? null : BEANS.get(HtmlHelper.class).toPlainText(m_html.toEncodedHtml()),
+          m_html == null ? null : BEANS.get(HtmlHelper.class).toPlainText(m_html.toHtml()),
           m_hiddenText);
     }
   }
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxEvent.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxEvent.java
index 7335f65..7ae403c 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxEvent.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/messagebox/MessageBoxEvent.java
@@ -39,7 +39,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append("MessageBoxEvent[");
     // decode type
     try {
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/AbstractWizardStep.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/AbstractWizardStep.java
index 975c7f2..6a6eca1 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/AbstractWizardStep.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/AbstractWizardStep.java
@@ -487,12 +487,12 @@
 
   @Override
   public double getOrder() {
-    return propertySupport.getPropertyDouble(PROP_VIEW_ORDER);
+    return propertySupport.getPropertyDouble(PROP_ORDER);
   }
 
   @Override
   public void setOrder(double order) {
-    propertySupport.setPropertyDouble(PROP_VIEW_ORDER, order);
+    propertySupport.setPropertyDouble(PROP_ORDER, order);
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/DefaultWizardStatusHtmlProvider.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/DefaultWizardStatusHtmlProvider.java
index ce77860..9d667d8 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/DefaultWizardStatusHtmlProvider.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/DefaultWizardStatusHtmlProvider.java
@@ -11,6 +11,7 @@
 package org.eclipse.scout.rt.client.ui.wizard;
 
 import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -44,8 +45,8 @@
 
   @Override
   public String initHtmlTemplate() {
-    try {
-      return new String(IOUtility.getContent(org.eclipse.scout.rt.client.ResourceBase.class.getResource("html/defaultWizardStatus.html").openStream()), "iso-8859-1");
+    try (InputStream in = org.eclipse.scout.rt.client.ResourceBase.class.getResource("html/defaultWizardStatus.html").openStream()) {
+      return IOUtility.readString(in, "iso-8859-1");
     }
     catch (Exception t) {
       throw new ProcessingException("Unexpected", t);
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/IWizardStep.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/IWizardStep.java
index 8782c8a..fd0af1d 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/IWizardStep.java
+++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/wizard/IWizardStep.java
@@ -27,7 +27,7 @@
   String PROP_ICON_ID = "iconId";
   String PROP_ENABLED = "enabled";
   String PROP_VISIBLE = "visible";
-  String PROP_VIEW_ORDER = "viewOrder";
+  String PROP_ORDER = "order";
   String PROP_ACTION_ENABLED = "actionEnabled";
 
   /**
diff --git a/org.eclipse.scout.rt.platform.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.platform.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.platform.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.platform.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.platform.test/pom.xml b/org.eclipse.scout.rt.platform.test/pom.xml
index 1ddaa0e..6aeca9d 100644
--- a/org.eclipse.scout.rt.platform.test/pom.xml
+++ b/org.eclipse.scout.rt.platform.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/runner/JUnitExceptionHandler.java b/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/runner/JUnitExceptionHandler.java
index 46d9e72..53f888d 100644
--- a/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/runner/JUnitExceptionHandler.java
+++ b/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/runner/JUnitExceptionHandler.java
@@ -10,7 +10,9 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.testing.platform.runner;
 
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import org.eclipse.scout.rt.platform.IgnoreBean;
 import org.eclipse.scout.rt.platform.Replace;
@@ -34,7 +36,7 @@
 
   private static final Logger LOG = LoggerFactory.getLogger(JUnitExceptionHandler.class);
 
-  private final AtomicReference<Throwable> m_error = new AtomicReference<>(null);
+  private final List<Throwable> m_errors = Collections.synchronizedList(new ArrayList<Throwable>());
 
   @Override
   public void handle(final Throwable t) {
@@ -42,23 +44,33 @@
       LOG.info("Exception will not be re-thrown for JUnit assertion because already consumed. [exception={}]", t.getMessage());
     }
     else {
-      if (m_error.compareAndSet(null, t)) {
+      m_errors.add(t);
+      if (m_errors.size() == 1) {
         LOG.info("Exception will be re-thrown for JUnit assertion. [exception={}]", t.getMessage());
       }
       else {
-        LOG.info("Exception will not be re-thrown for JUnit assertion because another exception was already handled. [current exception={}, other exception={}]", t, m_error.get().getMessage());
+        LOG.info("Exception will not be re-thrown for JUnit assertion because another exception was already handled. [current exception={}, other exception={}]", t, m_errors.get(0).getMessage());
       }
     }
   }
 
   /**
+   * @return the mutable list of collected errors. The list may by modified before {@link #throwOnError()} is called.
+   */
+  public List<Throwable> getErrors() {
+    return m_errors;
+  }
+
+  /**
    * Throws the first exception handled by this {@code ExceptionHandler} and resets this handler.<br/>
    * This method call has no effect if no exception was handled.
    */
   public void throwOnError() throws Throwable {
-    final Throwable throwable = m_error.getAndSet(null); // clear the exception.
-    if (throwable != null) {
-      throw throwable;
+    if (m_errors.isEmpty()) {
+      return;
     }
+    final Throwable throwable = m_errors.get(0);
+    m_errors.clear();
+    throw throwable;
   }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/util/ScoutAssert.java b/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/util/ScoutAssert.java
index 341a4c4..0f6f444 100644
--- a/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/util/ScoutAssert.java
+++ b/org.eclipse.scout.rt.platform.test/src/main/java/org/eclipse/scout/rt/testing/platform/util/ScoutAssert.java
@@ -69,7 +69,7 @@
     }
     int actualIndex = 0;
     expectedLoop: for (Object expectedElement : expected) {
-      for (int j = actualIndex; j < actual.length; j++) {
+      for (int j = actualIndex; j < actual.length; j++) { //NOSONAR
         if (expectedElement.equals(actual[j])) {
           actualIndex = j + 1;
           continue expectedLoop;
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HTMLTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HTMLTest.java
index be1ef23..4f8444c 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HTMLTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HTMLTest.java
@@ -21,17 +21,20 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
+import org.eclipse.scout.rt.platform.util.CloneUtility;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.junit.Assert;
 import org.junit.Test;
 
 /**
  * Tests for {@link HtmlBinds}
  */
 public class HTMLTest {
-  private static final String BIND_TEXT = "Test Last Name&";
-  private static final String ENCODED_BIND_TEXT = "Test Last Name&amp;";
-  private static final String TEST_URL = "http://SCOUTBLABLA.com";
+  private static final String HTML_TEXT = "Test Last Name&";
+  private static final String ESCAPED_HTML_TEXT = "Test Last Name&amp;";
+  private static final String TEST_URL = "http://SCOUTBLABLA.com\"";
 
   private static final String sampleCSS = "p {"
       + "    text-align: center;"
@@ -40,21 +43,21 @@
 
   @Test
   public void testHtmlNoBinds() {
-    assertEncodedText("h1", HTML.h1(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("h2", HTML.h2(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("h3", HTML.h3(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("h4", HTML.h4(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("h5", HTML.h5(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("h6", HTML.h6(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("b", bold(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("i", italic(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("td", td(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("div", div(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("p", HTML.p(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("span", HTML.span(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("li", HTML.li(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("head", HTML.head(BIND_TEXT).toEncodedHtml());
-    assertEncodedText("body", HTML.body(BIND_TEXT).toEncodedHtml());
+    assertEncodedText("h1", HTML.h1(HTML_TEXT).toHtml());
+    assertEncodedText("h2", HTML.h2(HTML_TEXT).toHtml());
+    assertEncodedText("h3", HTML.h3(HTML_TEXT).toHtml());
+    assertEncodedText("h4", HTML.h4(HTML_TEXT).toHtml());
+    assertEncodedText("h5", HTML.h5(HTML_TEXT).toHtml());
+    assertEncodedText("h6", HTML.h6(HTML_TEXT).toHtml());
+    assertEncodedText("b", bold(HTML_TEXT).toHtml());
+    assertEncodedText("i", italic(HTML_TEXT).toHtml());
+    assertEncodedText("td", td(HTML_TEXT).toHtml());
+    assertEncodedText("div", div(HTML_TEXT).toHtml());
+    assertEncodedText("p", HTML.p(HTML_TEXT).toHtml());
+    assertEncodedText("span", HTML.span(HTML_TEXT).toHtml());
+    assertEncodedText("li", HTML.li(HTML_TEXT).toHtml());
+    assertEncodedText("head", HTML.head(HTML_TEXT).toHtml());
+    assertEncodedText("body", HTML.body(HTML_TEXT).toHtml());
   }
 
   /**
@@ -62,8 +65,8 @@
    */
   @Test
   public void testLinkNoBinds() {
-    String html = HTML.link(TEST_URL, BIND_TEXT).toEncodedHtml();
-    assertEquals("<a href=\"" + TEST_URL + "\">" + encode(BIND_TEXT) + "</a>", html);
+    String html = HTML.link(TEST_URL, HTML_TEXT).toHtml();
+    assertEquals("<a href=\"" + TEST_URL.replace("\"", "&quot;") + "\">" + escape(HTML_TEXT) + "</a>", html);
   }
 
   /**
@@ -71,23 +74,29 @@
    */
   @Test
   public void testImageNoBinds() {
-    String html = HTML.img("logo.png").toEncodedHtml();
+    String html = HTML.img("logo.png").toHtml();
     assertEquals("<img src=\"logo.png\">", html);
   }
 
+  @Test
+  public void testNullAttribute() {
+    assertEquals("<a href=\"\"></a>", HTML.link(null, null).toHtml());
+    assertEquals("<a href=\"\">&lt;a&gt;badlink&lt;&#47;a&gt;</a>", HTML.link(null, "<a>badlink</a>").toHtml());
+  }
+
   /**
    * Tests for {@link HTML#br()}
    */
   @Test
   public void testBr() {
     IHtmlElement br = HTML.br();
-    assertEquals("<br>", br.toEncodedHtml());
+    assertEquals("<br>", br.toHtml());
   }
 
   @Test
   public void testAddAttribute() {
     IHtmlElement span = HTML.span("text").addAttribute("name", "value");
-    assertEquals("<span name=\"value\">text</span>", span.toEncodedHtml());
+    assertEquals("<span name=\"value\">text</span>", span.toHtml());
   }
 
   /**
@@ -96,73 +105,78 @@
   @Test
   public void testAppLinkNoBinds() {
     final IHtmlElement html = HTML.appLink("domain=123&text=456", "Link Text&");
-    assertEquals("<span class=\"app-link\" data-ref=\"domain=123&amp;text=456\">Link Text&amp;</span>", html.toEncodedHtml());
+    assertEquals("<span class=\"app-link\" data-ref=\"domain=123&text=456\">Link Text&amp;</span>", html.toHtml());
+  }
+
+  @Test
+  public void testAppLinkWithQuote() {
+    final IHtmlElement html = HTML.appLink("domain=123\"text=456", "Link Text<a href=\"javascript:window.alert('bad');\">test</a>");
+    assertEquals("<span class=\"app-link\" data-ref=\"domain=123&quot;text=456\">Link Text&lt;a href=&quot;javascript:window.alert(&#39;bad&#39;);&quot;&gt;test&lt;&#47;a&gt;</span>", html.toHtml());
   }
 
   @Test
   public void testBoldAppLink() {
     final IHtmlElement html = HTML.bold("asdf", HTML.appLink("domain=123&text=456", "Link Text&"));
-    assertEquals("<b>asdf<span class=\"app-link\" data-ref=\"domain=123&amp;text=456\">Link Text&amp;</span></b>", html.toEncodedHtml());
+    assertEquals("<b>asdf<span class=\"app-link\" data-ref=\"domain=123&text=456\">Link Text&amp;</span></b>", html.toHtml());
   }
 
   @Test
   public void testTableNoBinds() {
-    String html = HTML.table(tr(td(BIND_TEXT))).toEncodedHtml();
-    assertEquals("<table><tr><td>" + encode(BIND_TEXT) + "</td></tr></table>", html);
+    String html = HTML.table(tr(td(HTML_TEXT))).toHtml();
+    assertEquals("<table><tr><td>" + escape(HTML_TEXT) + "</td></tr></table>", html);
   }
 
   @Test
   public void testTableAttributesNoBinds() {
-    final IHtmlTable table = HTML.table(tr(td(BIND_TEXT)));
-    assertEquals("<table><tr><td>" + encode(BIND_TEXT) + "</td></tr></table>", table.toEncodedHtml());
+    final IHtmlTable table = HTML.table(tr(td(HTML_TEXT)));
+    assertEquals("<table><tr><td>" + escape(HTML_TEXT) + "</td></tr></table>", table.toHtml());
   }
 
   @Test
   public void testLinkWithBoldNoBinds() {
-    final IHtmlElement html = HTML.bold(BIND_TEXT, link(TEST_URL, BIND_TEXT));
-    assertEquals("<b>Test Last Name&amp;<a href=\"http://SCOUTBLABLA.com\">Test Last Name&amp;</a></b>", html.toEncodedHtml());
+    final IHtmlElement html = HTML.bold(HTML_TEXT, link(TEST_URL, HTML_TEXT));
+    assertEquals("<b>Test Last Name&amp;<a href=\"http://SCOUTBLABLA.com&quot;\">Test Last Name&amp;</a></b>", html.toHtml());
   }
 
-  private String encode(String text) {
-    return StringUtility.htmlEncode(text, false);
+  private String escape(String text) {
+    return BEANS.get(HtmlHelper.class).escape(text);
   }
 
   private void assertEncodedText(String tagName, String actualText) {
-    assertEquals("<" + tagName + ">" + ENCODED_BIND_TEXT + "</" + tagName + ">", actualText);
+    assertEquals("<" + tagName + ">" + ESCAPED_HTML_TEXT + "</" + tagName + ">", actualText);
   }
 
   @Test
   public void testFragment() {
-    assertEquals("", HTML.fragment((CharSequence) null).toEncodedHtml());
+    assertEquals("", HTML.fragment((CharSequence) null).toHtml());
 
-    final IHtmlContent fragment = HTML.fragment(HTML.div(BIND_TEXT), BIND_TEXT);
-    assertEquals("<div>" + ENCODED_BIND_TEXT + "</div>" + ENCODED_BIND_TEXT, fragment.toEncodedHtml());
+    final IHtmlContent fragment = HTML.fragment(HTML.div(HTML_TEXT), HTML_TEXT);
+    assertEquals("<div>" + ESCAPED_HTML_TEXT + "</div>" + ESCAPED_HTML_TEXT, fragment.toHtml());
   }
 
   @Test
   public void testMultipleFragments() {
     final IHtmlContent fragment = HTML.fragment(HTML.div("1"), HTML.div("2"));
-    assertEquals("<div>1</div><div>2</div>", fragment.toEncodedHtml());
+    assertEquals("<div>1</div><div>2</div>", fragment.toHtml());
   }
 
   @Test
   public void testRowWithMultipleBinds() {
     IHtmlTableRow row = HTML.tr(HTML.td("p1"), HTML.td("p2"), HTML.td("p4"));
-    assertEquals("<tr><td>p1</td><td>p2</td><td>p4</td></tr>", row.toEncodedHtml());
-    assertEquals("<tr><td>:b__0</td><td>:b__1</td><td>:b__2</td></tr>", row.toString());
-    assertEquals(3, row.getBinds().getBindMap().size());
+    assertEquals("<tr><td>p1</td><td>p2</td><td>p4</td></tr>", row.toHtml());
+    assertEquals("<tr><td>p1</td><td>p2</td><td>p4</td></tr>", row.toString());
   }
 
   @Test
   public void testMultipleCellsNoBinds() {
     IHtmlTableRow row1 = HTML.tr(HTML.td("p1"), HTML.td("p2"));
-    assertEquals("<tr><td>:b__0</td><td>:b__1</td></tr>", row1.toString());
+    assertEquals("<tr><td>p1</td><td>p2</td></tr>", row1.toString());
   }
 
   @Test
   public void testCellWithColspan() {
     IHtmlTableRow row = HTML.tr(HTML.td("1").colspan(2), HTML.td("2"));
-    assertEquals("<tr><td colspan=\"2\">1</td><td>2</td></tr>", row.toEncodedHtml());
+    assertEquals("<tr><td colspan=\"2\">1</td><td>2</td></tr>", row.toHtml());
   }
 
   @Test
@@ -172,64 +186,64 @@
     String row1String = "<tr><td>p1</td><td>p2</td></tr>";
     String row2String = "<tr><td>p3</td><td>p4</td></tr>";
 
-    String res = HTML.table(row1, row2).toEncodedHtml();
+    String res = HTML.table(row1, row2).toHtml();
     assertEquals("<table>" + row1String + row2String + "</table>", res);
   }
 
   @Test
   public void testComplexHtml() {
-    final IHtmlElement html = HTML.div(link(TEST_URL, BIND_TEXT), HTML.table(tr(td(BIND_TEXT), td(BIND_TEXT), td(BIND_TEXT))));
-    String expected = "<div><a href=\"http://SCOUTBLABLA.com\">Test Last Name&amp;</a><table><tr><td>Test Last Name&amp;</td><td>Test Last Name&amp;</td><td>Test Last Name&amp;</td></tr></table></div>";
-    assertEquals(expected, html.toEncodedHtml());
+    final IHtmlElement html = HTML.div(link(TEST_URL, HTML_TEXT), HTML.table(tr(td(HTML_TEXT), td(HTML_TEXT), td(HTML_TEXT))));
+    String expected = "<div><a href=\"http://SCOUTBLABLA.com&quot;\">Test Last Name&amp;</a><table><tr><td>Test Last Name&amp;</td><td>Test Last Name&amp;</td><td>Test Last Name&amp;</td></tr></table></div>";
+    assertEquals(expected, html.toHtml());
   }
 
   @Test
   public void testUl() {
-    String html = HTML.ul(HTML.li(BIND_TEXT)).toEncodedHtml();
-    assertEquals("<ul><li>" + ENCODED_BIND_TEXT + "</li></ul>", html);
+    String html = HTML.ul(HTML.li(HTML_TEXT)).toHtml();
+    assertEquals("<ul><li>" + ESCAPED_HTML_TEXT + "</li></ul>", html);
   }
 
   @Test
   public void testMultipleUl() {
-    String html = HTML.ul(HTML.li(BIND_TEXT), HTML.li("2")).toEncodedHtml();
-    assertEquals("<ul><li>" + ENCODED_BIND_TEXT + "</li><li>2</li></ul>", html);
+    String html = HTML.ul(HTML.li(HTML_TEXT), HTML.li("2")).toHtml();
+    assertEquals("<ul><li>" + ESCAPED_HTML_TEXT + "</li><li>2</li></ul>", html);
   }
 
   @Test
   public void testMultipleOl() {
-    String html = HTML.ol(HTML.li(BIND_TEXT), HTML.li("2")).toEncodedHtml();
-    assertEquals("<ol><li>" + ENCODED_BIND_TEXT + "</li><li>2</li></ol>", html);
+    String html = HTML.ol(HTML.li(HTML_TEXT), HTML.li("2")).toHtml();
+    assertEquals("<ol><li>" + ESCAPED_HTML_TEXT + "</li><li>2</li></ol>", html);
   }
 
   @Test
   public void testHtmlCssStyle() {
     IHtmlContent head = HTML.head(HTML.cssStyle(sampleCSS));
-    assertEquals("<head><style type=\"text/css\">" + sampleCSS + "</style></head>", head.toEncodedHtml());
+    assertEquals("<head><style type=\"text/css\">" + sampleCSS + "</style></head>", head.toHtml());
   }
 
   @Test
   public void testFullHtml() {
-    IHtmlDocument html = HTML.html(HTML.cssStyle(sampleCSS), BIND_TEXT);
-    String expected = "<html><head><style type=\"text/css\">" + sampleCSS + "</style>" + "</head><body>" + ENCODED_BIND_TEXT + "</body></html>";
-    assertEquals(expected, html.toEncodedHtml());
+    IHtmlDocument html = HTML.html(HTML.cssStyle(sampleCSS), HTML_TEXT);
+    String expected = "<html><head><style type=\"text/css\">" + sampleCSS + "</style>" + "</head><body>" + ESCAPED_HTML_TEXT + "</body></html>";
+    assertEquals(expected, html.toHtml());
   }
 
   @Test
   public void testFullHtmlDocType() {
-    IHtmlDocument html = HTML.html5(HTML.cssStyle(sampleCSS), BIND_TEXT);
-    String expected = "<!DOCTYPE html><html><head><style type=\"text/css\">" + sampleCSS + "</style>" + "</head><body>" + ENCODED_BIND_TEXT + "</body></html>";
-    assertEquals(expected, html.toEncodedHtml());
+    IHtmlDocument html = HTML.html5(HTML.cssStyle(sampleCSS), HTML_TEXT);
+    String expected = "<!DOCTYPE html><html><head><style type=\"text/css\">" + sampleCSS + "</style>" + "</head><body>" + ESCAPED_HTML_TEXT + "</body></html>";
+    assertEquals(expected, html.toHtml());
   }
 
   @Test
   public void testPlain() {
-    assertEquals("", HTML.raw((CharSequence) null).toEncodedHtml());
-    assertEquals(BIND_TEXT, HTML.raw(BIND_TEXT).toEncodedHtml());
-    IHtmlContent plainLink = HTML.raw(BIND_TEXT, HTML.appLink("REF", BIND_TEXT));
-    String plainLinkString = String.format("%s<span class=\"app-link\" data-ref=\"REF\">%s</span>", BIND_TEXT, ENCODED_BIND_TEXT);
-    assertEquals(String.format(plainLinkString, BIND_TEXT, ENCODED_BIND_TEXT), plainLink.toEncodedHtml());
-    assertEquals(String.format("<b>%s</b>", plainLinkString), HTML.bold(plainLink).toEncodedHtml());
-    assertEquals(String.format("<i>%s</i>", plainLinkString), HTML.italic(plainLink).toEncodedHtml());
+    assertEquals("", HTML.raw((CharSequence) null).toHtml());
+    assertEquals(HTML_TEXT, HTML.raw(HTML_TEXT).toHtml());
+    IHtmlContent plainLink = HTML.raw(HTML_TEXT, HTML.appLink("REF", HTML_TEXT));
+    String plainLinkString = String.format("%s<span class=\"app-link\" data-ref=\"REF\">%s</span>", HTML_TEXT, ESCAPED_HTML_TEXT);
+    assertEquals(String.format(plainLinkString, HTML_TEXT, ESCAPED_HTML_TEXT), plainLink.toHtml());
+    assertEquals(String.format("<b>%s</b>", plainLinkString), HTML.bold(plainLink).toHtml());
+    assertEquals(String.format("<i>%s</i>", plainLinkString), HTML.italic(plainLink).toHtml());
   }
 
   @Test
@@ -240,12 +254,12 @@
     IHtmlElement html = HTML.div(h2, table);
 
     String exp = "<div><h2>h2</h2>" + createTableString("0") + "</div>";
-    assertEquals(exp, html.toEncodedHtml());
+    assertEquals(exp, html.toHtml());
   }
 
   @Test
   public void testNullValues() {
-    String encodedNullDiv = HTML.div((String) null).toEncodedHtml();
+    String encodedNullDiv = HTML.div((String) null).toHtml();
     assertEquals("<div></div>", encodedNullDiv);
   }
 
@@ -255,28 +269,28 @@
     expected = expected.replace("'", "\"");
 
     IHtmlInput htmlInput = HTML.input().id("lastName").name("Last name").cssClass("person-data").maxlength(30).value("").type("text");
-    assertEquals(expected, htmlInput.toEncodedHtml());
+    assertEquals(expected, htmlInput.toHtml());
   }
 
   @Test
   public void testSpecialCharacters() {
-    assertEquals("<p>Test$Class</p>", HTML.p("Test$Class").toEncodedHtml());
-    assertEquals("<p>C:\\Temp\\config.properties</p>", HTML.p("C:\\Temp\\config.properties").toEncodedHtml());
+    assertEquals("<p>Test$Class</p>", HTML.p("Test$Class").toHtml());
+    assertEquals("<p>C:\\Temp\\config.properties</p>", HTML.p("C:\\Temp\\config.properties").toHtml());
   }
 
   @Test
   public void testIconFromScoutFont() {
-    assertEquals("<span class=\"font-icon\">\uE002</span>", HTML.icon("font:\uE002").toEncodedHtml());
+    assertEquals("<span class=\"font-icon\">\uE002</span>", HTML.icon("font:\uE002").toHtml());
   }
 
   @Test
   public void testIconFromCustomFont() {
-    assertEquals("<span class=\"font-crmIcons\">\uE100</span>", HTML.icon("font:crmIcons \uE100").toEncodedHtml());
+    assertEquals("<span class=\"font-crmIcons\">\uE100</span>", HTML.icon("font:crmIcons \uE100").toHtml());
   }
 
   @Test
   public void testIconFromImage() {
-    assertEquals("<img src=\"iconId:logo\">", HTML.icon("logo").toEncodedHtml());
+    assertEquals("<img src=\"iconId:logo\">", HTML.icon("logo").toHtml());
   }
 
   private String createTableString(String prefix) {
@@ -289,7 +303,7 @@
   }
 
   private String createRowString(String prefix, int i) {
-    return HTML.tr(HTML.td("A" + prefix + i), HTML.td("B" + prefix + i)).toEncodedHtml();
+    return HTML.tr(HTML.td("A" + prefix + i), HTML.td("B" + prefix + i)).toHtml();
   }
 
   private IHtmlTable createTable(String prefix) {
@@ -304,4 +318,88 @@
     return HTML.tr(HTML.td("A" + prefix + i), HTML.td("B" + prefix + i));
   }
 
+  @Test
+  public void testNewLineToBr() {
+    assertEquals("one &amp; two<br>three &amp; four", HTML.fragment("one & two\nthree & four").toHtml());
+    assertEquals("one &amp; two\nthree &amp; four", HTML.fragment("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<span>one &amp; two<br>three &amp; four</span>", HTML.span("one & two\nthree & four").toHtml());
+    assertEquals("<span>one &amp; two\nthree &amp; four</span>", HTML.span("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<i>one &amp; two<br>three &amp; four</i>", HTML.italic("one & two\nthree & four").toHtml());
+    assertEquals("<i>one &amp; two\nthree &amp; four</i>", HTML.italic("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<b>one &amp; two<br>three &amp; four</b>", HTML.bold("one & two\nthree & four").toHtml());
+    assertEquals("<b>one &amp; two\nthree &amp; four</b>", HTML.bold("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<div>one &amp; two<br>three &amp; four</div>", HTML.div("one & two\nthree & four").toHtml());
+    assertEquals("<div>one &amp; two\nthree &amp; four</div>", HTML.div("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<h1>one &amp; two<br>three &amp; four</h1>", HTML.h1("one & two\nthree & four").toHtml());
+    assertEquals("<h1>one &amp; two\nthree &amp; four</h1>", HTML.h1("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals("<p>one &amp; two<br>three &amp; four</p>", HTML.p("one & two\nthree & four").toHtml());
+    assertEquals("<p>one &amp; two\nthree &amp; four</p>", HTML.p("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    // for app links, only 2 argument (text) is escaped and new lines are replaced
+    assertEquals("<span class=\"app-link\" data-ref=\"one & two\nthree & four\">one &amp; two<br>three &amp; four</span>", HTML.appLink("one & two\nthree & four", "one & two\nthree & four").toHtml());
+    assertEquals("<span class=\"app-link\" data-ref=\"one & two\nthree & four\">one &amp; two\nthree &amp; four</span>", HTML.appLink("one & two\nthree & four", "one & two\nthree & four").withNewLineToBr(false).toHtml());
+  }
+
+  @Test
+  public void testEquality() {
+    assertEquals(BEANS.get(HtmlHelper.class).escapeAndNewLineToBr("one & two\nthree & four"), HTML.fragment("one & two\nthree & four").toHtml());
+    assertEquals(BEANS.get(HtmlHelper.class).escape("one & two\nthree & four"), HTML.fragment("one & two\nthree & four").withNewLineToBr(false).toHtml());
+
+    assertEquals(HTML.raw(BEANS.get(HtmlHelper.class).escapeAndNewLineToBr("one & two\nthree & four")).toHtml(), HTML.fragment("one & two\nthree & four").toHtml());
+    assertEquals(HTML.raw(BEANS.get(HtmlHelper.class).escape("one & two\nthree & four")).toHtml(), HTML.fragment("one & two\nthree & four").withNewLineToBr(false).toHtml());
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testNonSerializableRaw() {
+    HTML.raw("1", "2", new NonSerializableCharSequence(), "3");
+  }
+
+  @Test(expected = ProcessingException.class)
+  public void testNonSerializableFragment() {
+    HTML.fragment("1", "2", new NonSerializableCharSequence(), "3");
+  }
+
+  @Test
+  public void testSerializability() throws Exception {
+    IHtmlDocument htmlDocument = HTML.html5(
+        null,
+        HTML.body(
+            HTML.p("Lorem ipsum"),
+            HTML.bold(" dolor sit amet,"),
+            HTML.div(" consetetur sadipscing elitr,"),
+            HTML.fragment(" sed", " diam", " nonumy", "eirmod"),
+            HTML.italic(HTML.raw("<p>tempor invidunt ut labore et dolore magna aliquyam erat.</p>"))));
+
+    String htmlBeforeSerialization = htmlDocument.toHtml();
+    String plainTextBeforeSerialization = htmlDocument.toPlainText();
+
+    IHtmlDocument clonedHtmlDocument = CloneUtility.createDeepCopyBySerializing(htmlDocument);
+
+    Assert.assertEquals(htmlBeforeSerialization, clonedHtmlDocument.toHtml());
+    Assert.assertEquals(plainTextBeforeSerialization, clonedHtmlDocument.toPlainText());
+  }
+
+  protected static class NonSerializableCharSequence implements CharSequence {
+
+    @Override
+    public int length() {
+      return 0;
+    }
+
+    @Override
+    public char charAt(int index) {
+      return 0;
+    }
+
+    @Override
+    public CharSequence subSequence(int start, int end) {
+      return null;
+    }
+  }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlBindsTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlBindsTest.java
deleted file mode 100644
index f79af8d..0000000
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlBindsTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.platform.html;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.eclipse.scout.rt.platform.html.HtmlBinds;
-import org.eclipse.scout.rt.platform.html.IHtmlBind;
-import org.junit.Test;
-
-/**
- * Tests for {@link HtmlBinds}
- */
-public class HtmlBindsTest {
-
-  @Test
-  public void testBindInput() {
-    String testInput = "test";
-    HtmlBinds binds = new HtmlBinds();
-    IHtmlBind newBind = binds.put(testInput);
-    Object bindValue = binds.getBindValue(newBind.toString());
-    assertEquals(testInput, bindValue);
-  }
-
-  @Test
-  public void testGetReplacements_EmptyBinds() {
-    HtmlBinds binds = new HtmlBinds();
-    HtmlBinds binds2 = new HtmlBinds();
-    Map<String, String> replacements = binds.getReplacements(binds2);
-    assertTrue(replacements.isEmpty());
-  }
-
-  @Test
-  public void testGetReplacements() {
-    HtmlBinds binds = new HtmlBinds();
-    binds.put("a");
-    HtmlBinds binds2 = new HtmlBinds();
-    binds2.put("b");
-    Map<String, String> replacements = binds.getReplacements(binds2);
-    Entry<String, String> firstEntry = replacements.entrySet().iterator().next();
-    assertEquals(":b__0", firstEntry.getKey());
-    assertEquals(":b__1", firstEntry.getValue());
-  }
-
-  @Test
-  public void testGetRepl2() {
-    HtmlBinds binds = new HtmlBinds();
-    binds.put("a");
-    binds.put("b");
-    HtmlBinds binds2 = new HtmlBinds();
-    binds2.put("c");
-    Map<String, String> replacements = binds.getReplacements(binds2);
-    Entry<String, String> firstEntry = replacements.entrySet().iterator().next();
-    assertEquals(":b__0", firstEntry.getKey());
-    assertEquals(":b__2", firstEntry.getValue());
-  }
-
-  @Test
-  public void testGetRepl3() {
-    HtmlBinds binds = new HtmlBinds();
-    binds.put("a");
-    HtmlBinds binds2 = new HtmlBinds();
-    binds2.put("b");
-    binds2.put("c");
-    Map<String, String> replacements = binds.getReplacements(binds2);
-    Iterator<Entry<String, String>> iter = replacements.entrySet().iterator();
-    Entry<String, String> firstEntry = iter.next();
-    Entry<String, String> secondEntry = iter.next();
-    assertEquals(":b__1", firstEntry.getKey());
-    assertEquals(":b__2", firstEntry.getValue());
-    assertEquals(":b__0", secondEntry.getKey());
-    assertEquals(":b__1", secondEntry.getValue());
-  }
-}
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlContentBuilderTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlContentBuilderTest.java
index 43eec2e..99952bd 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlContentBuilderTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlContentBuilderTest.java
@@ -15,10 +15,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.scout.rt.platform.html.HTML;
-import org.eclipse.scout.rt.platform.html.IHtmlElement;
-import org.eclipse.scout.rt.platform.html.IHtmlTable;
-import org.eclipse.scout.rt.platform.html.IHtmlTableRow;
 import org.eclipse.scout.rt.platform.html.internal.HtmlContentBuilder;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.junit.Test;
@@ -29,27 +25,6 @@
 public class HtmlContentBuilderTest {
 
   @Test
-  public void test2Binds() {
-    IHtmlElement h1 = HTML.h2("0");
-    IHtmlElement h2 = HTML.h2("1");
-    HtmlContentBuilder cb = new HtmlContentBuilder(h1, h2);
-    assertEquals(2, cb.getBinds().getBindMap().size());
-    assertEquals("0", cb.getBinds().getBindMap().get(":b__0"));
-    assertEquals("1", cb.getBinds().getBindMap().get(":b__1"));
-  }
-
-  @Test
-  public void testImportBinds() {
-    IHtmlElement h2 = HTML.h2("0");
-    IHtmlElement h22 = HTML.h2("1", HTML.bold("2"));
-
-    HtmlContentBuilder cb = new HtmlContentBuilder(h2, h22);
-    assertEquals("0", cb.getBinds().getBindMap().get(":b__0"));
-    assertEquals("1", cb.getBinds().getBindMap().get(":b__1"));
-    assertEquals("2", cb.getBinds().getBindMap().get(":b__2"));
-  }
-
-  @Test
   public void testManyBinds() throws Exception {
     IHtmlElement h2 = HTML.h2("h2");
     IHtmlTable table = createTable("0");
@@ -59,7 +34,7 @@
         table);
 
     String exp = "<div><h2>h2</h2>" + createTableString("0") + "</div>";
-    assertEquals(exp, html.toEncodedHtml());
+    assertEquals(exp, html.toHtml());
   }
 
   private String createTableString(String prefix) {
@@ -72,7 +47,7 @@
   }
 
   private String createRowString(String prefix, int i) {
-    return HTML.tr(HTML.td("A" + prefix + i), HTML.td("B" + prefix + i)).toEncodedHtml();
+    return HTML.tr(HTML.td("A" + prefix + i), HTML.td("B" + prefix + i)).toHtml();
   }
 
   private IHtmlTable createTable(String prefix) {
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlHelperTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlHelperTest.java
index d97e10d..1050b83 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlHelperTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/html/HtmlHelperTest.java
@@ -36,6 +36,8 @@
     assertEquals("one\ttwo", helper.toPlainText("one&#9;two"));
     assertEquals("one \t two", helper.toPlainText("one &#9; two"));
     assertEquals("one\ttwo", helper.toPlainText("one" + StringUtility.HTML_ENCODED_TAB + "two"));
+    assertEquals("one    two", helper.toPlainText("one&#160;&#xa0;&#Xa0;&#xA0;two")); // HTML5 spec allows for mixed case hex values.
+    assertEquals("one\t\ttwo", helper.toPlainText("one&#x9;&#X9;two")); // HTML5 spec allows for mixed case hex values.
 
     // Simple documents
     assertEquals("", helper.toPlainText("<html>"));
@@ -72,13 +74,14 @@
 
     assertEquals("one &amp; two", helper.escape("one & two"));
     assertEquals("one &lt; two", helper.escape("one < two"));
-    assertEquals("&gt;&lt;script&gt;alert(&#39;hacker attack&#39;);&lt;/script&gt;&lt;", helper.escape("><script>alert('hacker attack');</script><"));
+    assertEquals("&gt;&lt;script&gt;alert(&#39;hacker attack&#39;);&lt;&#47;script&gt;&lt;", helper.escape("><script>alert('hacker attack');</script><"));
     assertEquals("one&amp;nbsp;&amp;nbsp; two", helper.escape("one&nbsp;&nbsp; two"));
     assertEquals("this is &quot;good&quot;", helper.escape("this is \"good\""));
-    assertEquals("http://www.example.com/~myapp/script?q=search%20query&amp;time=now&amp;x=17263.23", helper.escape("http://www.example.com/~myapp/script?q=search%20query&time=now&x=17263.23"));
-    assertEquals("&lt;div&gt;&lt;span style=&quot;color: red; content: &#39;\\u39&#39;;&quot;&gt;Alert!&lt;/span&gt;&lt;br/&gt;Line2&lt;/div&gt;",
+    assertEquals("http:&#47;&#47;www.example.com&#47;~myapp&#47;script?q=search%20query&amp;time=now&amp;x=17263.23", helper.escape("http://www.example.com/~myapp/script?q=search%20query&time=now&x=17263.23"));
+    assertEquals("&lt;div&gt;&lt;span style=&quot;color: red; content: &#39;\\u39&#39;;&quot;&gt;Alert!&lt;&#47;span&gt;&lt;br&#47;&gt;Line2&lt;&#47;div&gt;",
         helper.escape("<div><span style=\"color: red; content: '\\u39';\">Alert!</span><br/>Line2</div>"));
     assertEquals("hell&amp;ouml;", helper.escape("hell&ouml;"));
+    assertEquals("one&#47;two&#47;end", helper.escape("one/two/end"));
 
     // Things that should NOT be escaped
     assertEquals("one\ntwo  end", helper.escape("one\ntwo  end"));
@@ -99,14 +102,47 @@
     assertEquals("><script>alert('hacker attack');</script><", helper.unescape("&gt;&lt;script&gt;alert(&#39;hacker attack&#39;);&lt;/script&gt;&lt;"));
     assertEquals("one&nbsp;&nbsp; two", helper.unescape("one&amp;nbsp;&amp;nbsp; two"));
     assertEquals("this is \"good\"", helper.unescape("this is &quot;good&quot;"));
-    assertEquals("http://www.example.com/~myapp/script?q=search%20query&time=now&x=17263.23", helper.unescape("http://www.example.com/~myapp/script?q=search%20query&amp;time=now&amp;x=17263.23"));
+    assertEquals("http://www.example.com/~myapp/script?q=search%20query&time=now&x=17263.23",
+        helper.unescape("http://www.example.com/~myapp/script?q=search%20query&amp;time=now&amp;x=17263.23"));
     assertEquals("<div><span style=\"color: red; content: '\\u39';\">Alert!</span><br/>Line2</div>",
         helper.unescape("&lt;div&gt;&lt;span style=&quot;color: red; content: &#39;\\u39&#39;;&quot;&gt;Alert!&lt;/span&gt;&lt;br/&gt;Line2&lt;/div&gt;"));
     assertEquals("hell&ouml;", helper.unescape("hell&amp;ouml;"));
+    assertEquals("one/two/end", helper.unescape("one&#47;two&#47;end"));
+    assertEquals("one&two<three>four\"five/six'seven'eight&nine>ten", // HTML5 spec allows for mixed case hex values.
+        helper.unescape("one&#x26;two&#X3c;three&#x3E;four&#x22;five&#X2F;six&#x27;seven&#X27;eight&#X26;nine&#X3E;ten"));
 
     // Things that should NOT be unescaped
     assertEquals("one\ntwo  end", helper.unescape("one\ntwo  end"));
     assertEquals("key:\tvalue\r\nline2", helper.unescape("key:\tvalue\r\nline2"));
     assertEquals("hell&ouml;", helper.unescape("hell&ouml;"));
   }
+
+  @Test
+  public void testNewLineToBr() {
+    HtmlHelper helper = BEANS.get(HtmlHelper.class);
+
+    assertEquals(null, helper.newLineToBr(null));
+    assertEquals("", helper.newLineToBr(""));
+    assertEquals(" ", helper.newLineToBr(" "));
+    assertEquals("hello", helper.newLineToBr("hello"));
+    assertEquals("<br>", helper.newLineToBr("<br>"));
+
+    assertEquals("foo\rbar", helper.newLineToBr("foo\rbar"));
+    assertEquals("foo<br>bar", helper.newLineToBr("foo\r\nbar"));
+    assertEquals("foo<br>bar", helper.newLineToBr("foo\nbar"));
+    assertEquals("foo<br>bar", helper.newLineToBr("foo\r\nbar"));
+    assertEquals("foo<br>bar<br>foo", helper.newLineToBr("foo\nbar\r\nfoo"));
+  }
+
+  @Test
+  public void testEscapeAndNewLineToBr() {
+    HtmlHelper helper = BEANS.get(HtmlHelper.class);
+
+    assertEquals(null, helper.escapeAndNewLineToBr(null));
+    assertEquals("", helper.escapeAndNewLineToBr(""));
+    assertEquals(" ", helper.escapeAndNewLineToBr(" "));
+
+    assertEquals("one &amp; two<br>three &amp; four", helper.escapeAndNewLineToBr("one & two\nthree & four"));
+    assertEquals("&gt;&lt;script&gt;alert(&#39;hacker<br>attack&#39;);&lt;&#47;script&gt;&lt;", helper.escapeAndNewLineToBr("><script>alert('hacker\r\nattack');</script><"));
+  }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/IndexedStoreTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/IndexedStoreTest.java
index 98bdf17..2418b65 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/IndexedStoreTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/IndexedStoreTest.java
@@ -18,9 +18,6 @@
 import java.util.List;
 import java.util.Set;
 
-import org.eclipse.scout.rt.platform.index.AbstractMultiValueIndex;
-import org.eclipse.scout.rt.platform.index.AbstractSingleValueIndex;
-import org.eclipse.scout.rt.platform.index.IndexedStore;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 import org.junit.Before;
 import org.junit.Test;
@@ -40,11 +37,11 @@
   public void before() {
     m_store = new PersonStore();
 
-    m_store.add(m_john1 = new Person().withId(1).withName("john").withAge(35));
+    m_store.add(m_john1 = new Person().withId(1).withName("john").withAge(35).withCar("VW").withCar("Audi"));
     m_store.add(m_anna = new Person().withId(2).withName("anna").withAge(25));
-    m_store.add(m_maria = new Person().withId(3).withName("maria").withAge(80));
-    m_store.add(m_john2 = new Person().withId(4).withName("john").withAge(75));
-    m_store.add(m_frank = new Person().withId(5).withName("frank").withAge(50));
+    m_store.add(m_maria = new Person().withId(3).withName("maria").withAge(80).withCar("Nissan"));
+    m_store.add(m_john2 = new Person().withId(4).withName("john").withAge(75).withCar("VW"));
+    m_store.add(m_frank = new Person().withId(5).withName("frank").withAge(50).withCar("Seat").withCar("Porsche"));
     m_store.add(m_tom = new Person().withId(6).withName("tom").withAge(35));
   }
 
@@ -67,6 +64,11 @@
     assertEquals(CollectionUtility.arrayList(m_maria), m_store.getByName("maria"));
     assertEquals(CollectionUtility.arrayList(m_frank), m_store.getByName("frank"));
     assertEquals(CollectionUtility.arrayList(m_tom), m_store.getByName("tom"));
+    assertEquals(CollectionUtility.arrayList(m_john1, m_john2), m_store.getByCar("VW"));
+    assertEquals(CollectionUtility.arrayList(m_frank), m_store.getByCar("Porsche"));
+    assertEquals(CollectionUtility.arrayList(m_frank), m_store.getByCar("Seat"));
+    assertEquals(CollectionUtility.arrayList(m_john1), m_store.getByCar("Audi"));
+    assertEquals(CollectionUtility.arrayList(m_maria), m_store.getByCar("Nissan"));
 
     assertEquals(CollectionUtility.arrayList(m_maria, m_john2), m_store.getRetiredPersons());
   }
@@ -114,12 +116,18 @@
     assertEquals(CollectionUtility.arrayList(m_maria), ageIndex.get(80));
 
     m_maria.withAge(81); // was registered with a age of 80 years
+    m_maria.withCar("Aston Martin");
+    m_maria.withoutCar("Nissan");
     assertEquals(CollectionUtility.arrayList(m_maria), ageIndex.get(80));
+    assertEquals(CollectionUtility.emptyArrayList(), m_store.getByCar("Aston Martin"));
+    assertEquals(CollectionUtility.arrayList(m_maria), m_store.getByCar("Nissan"));
     assertTrue(ageIndex.get(81).isEmpty());
 
     m_store.add(m_maria);
     assertTrue(ageIndex.get(80).isEmpty());
     assertEquals(CollectionUtility.arrayList(m_maria), ageIndex.get(81));
+    assertEquals(CollectionUtility.emptyArrayList(), m_store.getByCar("Nissan"));
+    assertEquals(CollectionUtility.arrayList(m_maria), m_store.getByCar("Aston Martin"));
   }
 
   @Test
@@ -134,6 +142,7 @@
     private final PersonIdIndex IDX_PERSON_ID = registerIndex(new PersonIdIndex());
     private final PersonNameIndex IDX_PERSON_NAME = registerIndex(new PersonNameIndex());
     private final PersonRetiredIndex IDX_PERSON_RETIRED = registerIndex(new PersonRetiredIndex());
+    private final CarIndex IDX_CAR = registerIndex(new CarIndex());
 
     public Person getById(long id) {
       return IDX_PERSON_ID.get(id);
@@ -155,6 +164,10 @@
       return IDX_PERSON_RETIRED.get(Boolean.TRUE);
     }
 
+    public List<Person> getByCar(String car) {
+      return IDX_CAR.get(car);
+    }
+
     private class PersonIdIndex extends AbstractSingleValueIndex<Long, Person> {
 
       @Override
@@ -178,5 +191,13 @@
         return person.getAge() > 65;
       }
     }
+
+    private class CarIndex extends AbstractMultiValuesIndex<String, Person> {
+
+      @Override
+      protected Set<String> calculateIndexesFor(Person person) {
+        return person.getCars();
+      }
+    }
   }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/Person.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/Person.java
index df7ab2e..b3ddd67 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/Person.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/index/Person.java
@@ -10,12 +10,16 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.index;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import org.eclipse.scout.rt.platform.util.ToStringBuilder;
 
 public class Person {
   private long m_id;
   private String m_name;
   private int m_age;
+  private Set<String> m_cars = new HashSet<>();
 
   public long getId() {
     return m_id;
@@ -44,12 +48,27 @@
     return this;
   }
 
+  public Set<String> getCars() {
+    return m_cars;
+  }
+
+  public Person withCar(String car) {
+    m_cars.add(car);
+    return this;
+  }
+
+  public Person withoutCar(String car) {
+    m_cars.remove(car);
+    return this;
+  }
+
   @Override
   public String toString() {
     ToStringBuilder builder = new ToStringBuilder(this);
     builder.attr("id", m_id);
     builder.attr("name", m_name);
     builder.attr("age", m_age);
+    builder.attr("cars", m_cars);
     return builder.toString();
   }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/CloneUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/CloneUtilityTest.java
index bbb1067..f7e783d 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/CloneUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/CloneUtilityTest.java
@@ -20,7 +20,6 @@
 import java.io.Serializable;
 import java.net.URL;
 
-import org.eclipse.scout.rt.platform.util.CloneUtility;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -202,7 +201,6 @@
     }
     System.out.println("reading class file: " + resource + "\n\n");
 
-    InputStream in = resource.openStream();
     StringBuilder sb = new StringBuilder();
     sb.append("private static final String CUSTOM_TYPE_CLASS_NAME = \"");
     sb.append(CUSTOM_TYPE_CLASS_NAME);
@@ -212,19 +210,21 @@
 
     int size;
     byte[] buffer = new byte[512];
-    while ((size = in.read(buffer)) > -1) {
-      for (int i = 0; i < size; i++) {
-        int v = buffer[i] & 0xff;
-        if (counter > 0) {
-          sb.append(", ");
+    try (InputStream in = resource.openStream()) {
+      while ((size = in.read(buffer)) > -1) {
+        for (int i = 0; i < size; i++) {
+          int v = buffer[i] & 0xff;
+          if (counter > 0) {
+            sb.append(", ");
+          }
+          if (counter % 15 == 0) {
+            sb.append("\n    ");
+          }
+          sb.append("0x");
+          sb.append(HEX_ARRAY[v >>> 4]);
+          sb.append(HEX_ARRAY[v & 0x0F]);
+          counter++;
         }
-        if (counter % 15 == 0) {
-          sb.append("\n    ");
-        }
-        sb.append("0x");
-        sb.append(HEX_ARRAY[v >>> 4]);
-        sb.append(HEX_ARRAY[v & 0x0F]);
-        counter++;
       }
     }
     sb.append("};");
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/FileUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/FileUtilityTest.java
index f8e79fb..da73eef 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/FileUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/FileUtilityTest.java
@@ -16,6 +16,7 @@
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Paths;
 
@@ -50,9 +51,10 @@
     }
   }
 
-  private File createTempFile(String name) {
-    InputStream inputStream = getClass().getClassLoader().getResourceAsStream(PLATFORM_PATH + name);
-    return IOUtility.createTempFile(inputStream, "temp", "zip");
+  private File createTempFile(String name) throws IOException {
+    try (InputStream in = getClass().getClassLoader().getResourceAsStream(PLATFORM_PATH + name)) {
+      return IOUtility.createTempFile(in, "temp", "zip");
+    }
   }
 
   @Test
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/HTMLUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/HTMLUtilityTest.java
index 42618c9..c72282a 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/HTMLUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/HTMLUtilityTest.java
@@ -15,15 +15,11 @@
 
 import java.awt.Color;
 import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 
 import javax.swing.text.html.HTMLDocument;
 
 import org.eclipse.scout.rt.platform.html.HTMLUtility;
 import org.eclipse.scout.rt.platform.html.HTMLUtility.DefaultFont;
-import org.eclipse.scout.rt.platform.util.ColorUtility;
-import org.eclipse.scout.rt.platform.util.IOUtility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -798,9 +794,8 @@
    * @return
    */
   private String readResourceAsText(String relativeFileName) {
-    InputStream in = ResourceBase.class.getResourceAsStream(relativeFileName);
-    try {
-      return new String(IOUtility.getContent(in), StandardCharsets.UTF_8.name());
+    try (InputStream in = ResourceBase.class.getResourceAsStream(relativeFileName)) {
+      return IOUtility.readStringUTF8(in);
     }
     catch (Exception e) {
       fail("could not read input file: " + ResourceBase.class.getPackage() + "/" + relativeFileName);
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/IOUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/IOUtilityTest.java
index 74279ac..cefd718 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/IOUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/IOUtilityTest.java
@@ -18,13 +18,19 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.RandomAccessFile;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -66,6 +72,7 @@
     }
   }
 
+  @SuppressWarnings("resource")
   private File createTempFile(String name) {
     InputStream inputStream = getClass().getClassLoader().getResourceAsStream(PLATFORM_PATH + name);
     return IOUtility.createTempFile(inputStream, "temp", "zip");
@@ -226,10 +233,9 @@
   }
 
   @Test
-  public void testReadLinesUTF8() throws FileNotFoundException {
+  public void testReadLinesUTF8() throws IOException {
     File tempFile = null;
-    try {
-      InputStream inputStream = getClass().getClassLoader().getResourceAsStream("org/eclipse/scout/rt/platform/ioUtilityTestUtf8.txt");
+    try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("org/eclipse/scout/rt/platform/ioUtilityTestUtf8.txt")) {
       tempFile = IOUtility.createTempFile(inputStream, "temp", "zip");
 
       List<String> readLines = IOUtility.readLines(tempFile, StandardCharsets.UTF_8.name());
@@ -423,4 +429,119 @@
     return combined;
   }
 
+  @Test
+  public void testReadBytes1() {
+    byte[] expected = new byte[]{0, 1, 2, 3};
+    byte[] actual = IOUtility.readBytes(newInputStream(expected));
+    assertArrayEquals(expected, actual);
+  }
+
+  @Test
+  public void testReadBytes2() {
+    byte[] data = new byte[]{0, 1, 2, 3};
+    byte[] expected = Arrays.copyOfRange(data, 0, 3);
+    byte[] actual = IOUtility.readBytes(newInputStream(data), 3);
+    assertArrayEquals(expected, actual);
+  }
+
+  @Test
+  public void testReadStringFromStream1() throws Exception {
+    String expected = "0123äöü";
+    String actual = IOUtility.readString(newInputStream(expected.getBytes("UTF-8")), "UTF-8");
+    assertEquals(expected, actual);
+  }
+
+  @Test
+  public void testReadStringFromStream2() throws Exception {
+    String data = "0123äöü";
+    String expected = data.substring(0, 6);
+    String actual = IOUtility.readString(newInputStream(data.getBytes("UTF-8")), "UTF-8", 6);
+    assertEquals(expected, actual);
+  }
+
+  @Test
+  public void testReadString1() {
+    String expected = "0123";
+    String actual = IOUtility.readString(newReader(expected));
+    assertEquals(expected, actual);
+  }
+
+  @Test
+  public void testReadString2() {
+    String data = "0123";
+    String expected = data.substring(0, 3);
+    String actual = IOUtility.readString(newReader(data), 3);
+    assertEquals(expected, actual);
+  }
+
+  private InputStream newInputStream(byte[] bytes) {
+    return new ByteArrayInputStream(bytes);
+  }
+
+  private Reader newReader(String s) {
+    return new StringReader(s);
+  }
+
+  @Test
+  public void testWriteBytes() {
+    byte[] expected = new byte[]{0, 1, 2, 3};
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    IOUtility.writeBytes(out, expected);
+    byte[] actual = out.toByteArray();
+    assertArrayEquals(expected, actual);
+  }
+
+  @Test
+  public void testWriteStringToStream() throws Exception {
+    String expected = "0123äöü";
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    IOUtility.writeString(out, "UTF-8", expected);
+    String actual = new String(out.toByteArray(), "UTF-8");
+    assertEquals(expected, actual);
+  }
+
+  @Test
+  public void testWriteString() {
+    String expected = "0123";
+    StringWriter out = new StringWriter();
+    IOUtility.writeString(out, expected);
+    String actual = out.toString();
+    assertEquals(expected, actual);
+  }
+
+  @Test
+  public void testResourceTryNull() throws Exception {
+    try (InputStream res = (System.currentTimeMillis() == 0 ? new ByteArrayInputStream(new byte[15]) : null)) {
+      if (res != null) {
+        System.out.println("null resource: " + res);
+      }
+    }
+  }
+
+  @Test
+  public void testResourceTryError1() throws Exception {
+    try (InputStream res = new FileInputStream("foo/bar/test")) {
+      if (res != null) {
+        System.out.println("null resource: " + res);
+      }
+    }
+    catch (Exception ex) {
+      assertEquals(ex.getClass(), java.io.FileNotFoundException.class);
+      return;
+    }
+    fail("should not go here");
+  }
+
+  @Test
+  public void testResourceTryError2() throws Exception {
+    try (InputStream res = null) {
+      @SuppressWarnings({"resource", "unused"})
+      InputStream tmp = new FileInputStream("foo/bar/test");
+    }
+    catch (Exception ex) {
+      assertEquals(ex.getClass(), java.io.FileNotFoundException.class);
+      return;
+    }
+    fail("should not go here");
+  }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/StringUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/StringUtilityTest.java
index fe9ffa5..3bff129 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/StringUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/StringUtilityTest.java
@@ -54,6 +54,19 @@
   }
 
   @Test
+  public void testReplace() {
+    assertEquals("ba", StringUtility.replace("aaa", "aa", "b"));
+    assertNull(StringUtility.replace(null, "aa", "b"));
+    assertEquals("", StringUtility.replace("", "aa", "b"));
+    assertEquals("asdfasdf", StringUtility.replace("asdfasdf", null, "b"));
+    assertEquals("asdfasdf", StringUtility.replace("asdfasdf", "", "b"));
+    assertEquals("asdasd", StringUtility.replace("asdfasdf", "f", null));
+    assertEquals("asdasd", StringUtility.replace("asdfasdf", "f", ""));
+    assertEquals("aaffffffcc", StringUtility.replace("aabbcc", "b", "fff"));
+    assertEquals("asdf", StringUtility.replace("asdf", "ll", "fff"));
+  }
+
+  @Test
   public void testImplodeDelimiters() {
     String a = "a";
     String b = "b";
@@ -280,6 +293,7 @@
    * Test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=347254
    */
   @Test
+  @SuppressWarnings("deprecation")
   public void testHtmlEncodeAmpLT() {
     String testHtml = "<a &lt; b>";
     assertEqualsAfterEncodeDecode(testHtml);
@@ -288,6 +302,7 @@
   }
 
   @Test
+  @SuppressWarnings("deprecation")
   public void testHtmlDecodeTabs() {
     assertEquals("a \tb", StringUtility.htmlDecode("a &#9;b"));
     assertEquals("a<span>\t</span>b", StringUtility.htmlDecode("a<span>&#9;</span>b"));
@@ -312,6 +327,7 @@
    * @param replaceSpace
    *          replace all spaces when encoding
    */
+  @SuppressWarnings("deprecation")
   private static void assertEqualsAfterEncodeDecode(String original, boolean replaceSpaces) {
     String encoded = StringUtility.htmlEncode(original, replaceSpaces);
     String decoded = StringUtility.htmlDecode(encoded);
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriBuilderTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriBuilderTest.java
index 32c1a0c..34b92d5 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriBuilderTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriBuilderTest.java
@@ -16,10 +16,11 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
 
-import org.eclipse.scout.rt.platform.util.UriBuilder;
 import org.junit.Test;
 
 /**
@@ -29,10 +30,95 @@
  */
 public class UriBuilderTest {
 
-  static final String SCHEME = "scheme";
-  static final String HOST = "host";
-  static final String PATH_TO_SCHEME = "/path/to";
-  static final String ANCHOR = "anchor";
+  private static final String SCHEME = "scheme";
+  private static final String HOST = "host";
+  private static final String PATH_TO_SCHEME = "/path/to";
+  private static final String ANCHOR = "anchor";
+
+  private static final String HTTP = "http";
+  private static final String PATH = "/";
+  private static final String SIMPLE_URL = HTTP + "://" + HOST;
+  private static final String SIMPLE_URL_PATH = HTTP + "://" + HOST + PATH;
+  private static final String TEST_URI_PATH = "http://acme.com:1234/scout";
+
+  @Test
+  public void testSimpleUrl() {
+    final UriBuilder builder = new UriBuilder(SIMPLE_URL);
+    assertSimpleUrl(builder.createURI());
+    assertSimpleUrl(builder);
+  }
+
+  @Test
+  public void testSimpleUrlByUri() throws URISyntaxException {
+    final UriBuilder builder = new UriBuilder(new URI(SIMPLE_URL));
+    assertSimpleUrl(builder.createURI());
+    assertSimpleUrl(builder);
+  }
+
+  private void assertSimpleUrl(final UriBuilder builder) {
+    assertEquals("", builder.getPath());
+    assertNull(builder.getFragment());
+    assertTrue(builder.getParameters().isEmpty());
+  }
+
+  private void assertSimpleUrl(final URI uri) {
+    assertEquals(SIMPLE_URL, uri.toString());
+    assertEquals(HOST, uri.getHost());
+    assertEquals(HTTP, uri.getScheme());
+    assertEquals("", uri.getPath());
+    assertNull(uri.getFragment());
+    assertNull(uri.getQuery());
+  }
+
+  @Test
+  public void testSimpleUrlPath() throws URISyntaxException {
+    final UriBuilder builder = new UriBuilder(new URI(SIMPLE_URL_PATH));
+    assertEquals(PATH, builder.getPath());
+    assertNull(builder.getFragment());
+    final URI uri = builder.createURI();
+    assertEquals(SIMPLE_URL_PATH, uri.toString());
+    assertEquals(HOST, uri.getHost());
+    assertEquals(HTTP, uri.getScheme());
+    assertEquals(PATH, uri.getPath());
+    assertNull(uri.getFragment());
+    assertNull(uri.getQuery());
+  }
+
+  @Test
+  public void testEncodedURI() throws URISyntaxException {
+    String encodedUrl = "http://localhost/?x=20D";
+    final URI uri = new URI(encodedUrl);
+    assertEquals(uri, new UriBuilder(uri).createURI());
+  }
+
+  @Test
+  public void testAddPathToSimpleUrl2() throws URISyntaxException {
+    UriBuilder builder = new UriBuilder(new URI(SIMPLE_URL + "/"))
+        .addPath("test");
+    assertEquals(SIMPLE_URL + "/test", builder.createURI().toString());
+  }
+
+  @Test
+  public void testAddPathToFullUrl() throws URISyntaxException {
+    UriBuilder builder = new UriBuilder(new URI(TEST_URI_PATH))
+        .addPath("test");
+    assertEquals(TEST_URI_PATH + "/test", builder.createURI().toString());
+  }
+
+  @Test
+  public void testAddPathToFullUrl2() throws URISyntaxException {
+    UriBuilder builder = new UriBuilder(new URI(TEST_URI_PATH + "/"))
+        .addPath("test");
+    assertEquals(TEST_URI_PATH + "/test", builder.createURI().toString());
+  }
+
+  @Test
+  public void testEncodedQuery() throws MalformedURLException {
+    String query = "?a=%3D";
+    UriBuilder builder = new UriBuilder(TEST_URI_PATH + query);
+    final String url = builder.createURL().toString();
+    assertTrue(url.toString(), url.toString().endsWith(query));
+  }
 
   @Test
   public void testScheme() throws Exception {
@@ -44,7 +130,7 @@
     builder.scheme("ftp");
     assertEquals("ftp", builder.getScheme());
     //
-    builder = new UriBuilder("http://acme.com:1234/scout");
+    builder = new UriBuilder(TEST_URI_PATH);
     assertEquals("http", builder.getScheme());
   }
 
@@ -59,7 +145,7 @@
     builder.host(host);
     assertEquals(host, builder.getHost());
     //
-    builder = new UriBuilder("http://acme.com:1234/scout");
+    builder = new UriBuilder(TEST_URI_PATH);
     assertEquals("acme.com", builder.getHost());
   }
 
@@ -124,7 +210,7 @@
     //
     builder = new UriBuilder("http://acme.com:1234");
     builder.addPath("test");
-    assertEquals("test", builder.getPath());
+    assertEquals("/test", builder.getPath());
   }
 
   @Test
@@ -197,14 +283,30 @@
     //
     builder = new UriBuilder();
     builder.scheme(SCHEME).host(HOST).path(PATH_TO_SCHEME).fragment(ANCHOR).parameter("key", "äöü");
-    assertEquals("scheme://host/path/to?key=%25E4%25F6%25FC#anchor", builder.createURI().toASCIIString());
+    assertEquals("scheme://host/path/to?key=%C3%A4%C3%B6%C3%BC#anchor", builder.createURI().toASCIIString());
     //
     builder = new UriBuilder();
     builder.scheme(SCHEME).host(HOST).path(PATH_TO_SCHEME).fragment(ANCHOR).parameter("key", "äöü");
-    assertEquals("scheme://host/path/to?key=%25C3%25A4%25C3%25B6%25C3%25BC#anchor", builder.createURI(StandardCharsets.UTF_8.name()).toASCIIString());
+    assertEquals("scheme://host/path/to?key=%E4%F6%FC#anchor", builder.createURI(StandardCharsets.ISO_8859_1.name()).toASCIIString());
     //
     URI baseUri = new URI("http://www.eclipse.org/scout");
     builder = new UriBuilder(baseUri);
     assertEquals(baseUri, builder.createURI());
   }
+
+  /**
+   * This tests checks whether
+   */
+  @Test
+  public void testQueryString() throws Exception {
+    UriBuilder builder = new UriBuilder(TEST_URI_PATH);
+    builder.parameter("key", "value"); // simple key/value
+    builder.parameter("k&y", "=alue"); // contains an equals sign (invalid value for url parameter)
+    builder.parameter("ke2", "va ue"); // contains a space
+
+    String s = builder.createURL().toString();
+    assertTrue(s.contains("key=value"));
+    assertTrue(s.contains("k%26y=%3Dalue"));
+    assertTrue(s.contains("ke2=va+ue"));
+  }
 }
diff --git a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriUtilityTest.java b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriUtilityTest.java
index 5ee5c3b..703f4bd 100644
--- a/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriUtilityTest.java
+++ b/org.eclipse.scout.rt.platform.test/src/test/java/org/eclipse/scout/rt/platform/util/UriUtilityTest.java
@@ -13,16 +13,16 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 
 import org.eclipse.scout.rt.platform.exception.ProcessingException;
-import org.eclipse.scout.rt.platform.util.UriBuilder;
-import org.eclipse.scout.rt.platform.util.UriUtility;
 import org.junit.Test;
 
 /**
@@ -33,15 +33,22 @@
 public class UriUtilityTest {
 
   @Test
-  public void testGetQueryParametersNull() throws Exception {
+  public void testGetQueryParametersNull() {
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URI) null));
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URI) null, null));
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URI) null, StandardCharsets.UTF_8.name()));
-    assertEquals(Collections.singletonMap("value", "1"), UriUtility.getQueryParameters(URI.create("scheme://test.com/path?value=1"), null));
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URL) null));
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URL) null, null));
     assertEquals(Collections.emptyMap(), UriUtility.getQueryParameters((URL) null, StandardCharsets.UTF_8.name()));
-    assertEquals(Collections.singletonMap("value", "1"), UriUtility.getQueryParameters(new URL("http://test.com/path?value=1"), null));
+  }
+
+  @Test
+  public void testQueryParameters() throws MalformedURLException {
+    assertEquals(Collections.singletonMap("value", "1"), UriUtility.getQueryParameters(URI.create("scheme://test.com/path?value=1")));
+    assertEquals(Collections.singletonMap("value", "1"), UriUtility.getQueryParameters(new URL("http://test.com/path?value=1")));
+    assertEquals(Collections.singletonMap("value", "1"), UriUtility.getQueryParameters(URI.create("http://test.com/path?value=1#fragment")));
+    assertEquals(Collections.singletonMap("x", "20D"), UriUtility.getQueryParameters(URI.create("http://localhost/?x=20D")));
+    assertTrue(UriUtility.getQueryParameters(URI.create("scheme://test.com/path/path2")).isEmpty());
   }
 
   @Test
@@ -83,4 +90,5 @@
       // ok
     }
   }
+
 }
diff --git a/org.eclipse.scout.rt.platform/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.platform/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.platform/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.platform/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.platform/pom.xml b/org.eclipse.scout.rt.platform/pom.xml
index e995f17..194c581 100644
--- a/org.eclipse.scout.rt.platform/pom.xml
+++ b/org.eclipse.scout.rt.platform/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
@@ -42,6 +42,12 @@
     <dependency>
       <groupId>org.quartz-scheduler</groupId>
       <artifactId>quartz</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>c3p0</groupId>
+          <artifactId>c3p0</artifactId>
+        </exclusion>
+      </exclusions>
    </dependency>
     <!-- optional logger dependencies -->
 
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/config/AbstractConfigProperty.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/config/AbstractConfigProperty.java
index 866b0c3..b2f0518 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/config/AbstractConfigProperty.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/config/AbstractConfigProperty.java
@@ -23,7 +23,7 @@
   }
 
   @Override
-  public final DATA_TYPE getValue() {
+  public DATA_TYPE getValue() {
     if (!m_valueInitialized) {
       try {
         m_value = createValue();
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/CSSPatch.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/CSSPatch.java
index 3c61295..bb8bdc2 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/CSSPatch.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/CSSPatch.java
@@ -25,7 +25,7 @@
 /**
  * Patch for CSS class. The patch is applied as soon as this class is accessed.
  *
- * @deprecated This legacy utility will be removed in Scout 7. Use {@link org.eclipse.scout.rt.platform.html.HTML} and
+ * @deprecated This legacy utility will be removed in Scout 6.1. Use {@link org.eclipse.scout.rt.platform.html.HTML} and
  *             {@link HtmlHelper} instead.
  */
 @Deprecated
@@ -203,7 +203,7 @@
       try {
         StyleContext.registerStaticAttributeKey(key);
       }
-      catch (Throwable t) {
+      catch (Throwable t) { //NOSONAR (deprecated class)
         LOG.error("Failed registering CSS.Attribute '{}' on StyleContext", key, t);
       }
     }
@@ -215,7 +215,7 @@
       c.setAccessible(true);
       return c.newInstance(s1, s2, b);
     }
-    catch (Throwable t) {
+    catch (Throwable t) {//NOSONAR (deprecated class)
       LOG.error("Failed patching CSS by adding key '{}'", s1, t);
     }
     return null;
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTML.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTML.java
index ad1f9ab..d2cd172 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTML.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTML.java
@@ -10,6 +10,7 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.html;
 
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -32,6 +33,9 @@
 /**
  * Convenience for building a html document or parts of it with encoded binds. <br>
  * Only the most common cases are supported, not intended to be complete.
+ * <p>
+ * Because {@link IHtmlContent} extends {@link Serializable}, all {@link CharSequence} provided as arguments must be
+ * serializable (constraint verified by constructor of {@link HtmlPlainBuilder} and {@link HtmlContentBuilder}.
  */
 public final class HTML {
 
@@ -48,7 +52,7 @@
    * Create a html element with encoded text for &lt;head&gt;text&lt;/head&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.head("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.head("text").toHtml(); <br>
    * </p>
    *
    * @param elements
@@ -62,7 +66,7 @@
    * Create a html element with encoded text for &lt;body&gt;text&lt;/body&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.body("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.body("text").toHtml(); <br>
    * </p>
    *
    * @param elements
@@ -76,7 +80,7 @@
    * Create a html element with encoded text for &lt;b&gt;text&lt;/b&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.bold("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.bold("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -90,7 +94,7 @@
    * Create a html element with encoded text for &lt;i&gt;text&lt;/i&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.italic("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.italic("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -104,7 +108,7 @@
    * Create a html element with encoded text for &lt;p&gt;text&lt;/p&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.p("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.p("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -118,7 +122,7 @@
    * Create a html element for &lt;br&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.br().toEncodedHtml(); <br>
+   * String encodedHtml = HTML.br().toHtml(); <br>
    * </p>
    */
   public static IHtmlElement br() {
@@ -129,7 +133,7 @@
    * Create a html element for &lt;hr&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.hr().toEncodedHtml(); <br>
+   * String encodedHtml = HTML.hr().toHtml(); <br>
    * </p>
    */
   public static IHtmlElement hr() {
@@ -140,7 +144,7 @@
    * Create a html element with encoded text for &lt;h1&gt;text&lt;/h1&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h1("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h1("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -154,7 +158,7 @@
    * Create a html element with encoded text for &lt;h2&gt;text&lt;/h2&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h2("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h2("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -168,7 +172,7 @@
    * Create a html element with encoded text for &lt;h3&gt;text&lt;/h3&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h3("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h3("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -182,7 +186,7 @@
    * Create a html element with encoded text for &lt;h4&gt;text&lt;/h4&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h4("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h4("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -196,7 +200,7 @@
    * Create a html element with encoded text for &lt;h5&gt;text&lt;/h5&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h5("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h5("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -210,7 +214,7 @@
    * Create a html element with encoded text for &lt;h6&gt;text&lt;/h6&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.h6("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.h6("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -224,14 +228,14 @@
    * Create a html element with encoded text for &lt;div&gt;content&lt;/div&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.div("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.div("text").toHtml(); <br>
    * </p>
    *
    * @param content
    *          content as bind
    */
   public static IHtmlElement div(CharSequence... content) {
-    return new HtmlNodeBuilder("div", Arrays.asList(content));
+    return div(Arrays.asList(content));
   }
 
   /**
@@ -248,7 +252,7 @@
    * Create a html element with encoded text for &lt;span&gt;content&lt;/span&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.span("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.span("text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -262,7 +266,7 @@
    * Create a html element with encoded text for a link &lt;a href="url"&gt;text&lt;/a&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.link("http://xyz.com","text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.link("http://xyz.com","text").toHtml(); <br>
    * </p>
    *
    * @param text
@@ -276,7 +280,7 @@
    * Create a html element for an image: &lt;img src="path"&gt;&lt;/img&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.img("image.png").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.img("image.png").toHtml(); <br>
    * </p>
    *
    * @param src
@@ -290,7 +294,7 @@
    * Create a html element for an image: &lt;img src="binaryResource:resourceName"&gt;&lt;/img&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.imgByBinaryResource("resourceName").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.imgByBinaryResource("resourceName").toHtml(); <br>
    * </p>
    *
    * @param binaryResource
@@ -304,7 +308,7 @@
    * Create a html element for an image: &lt;img src="iconid:icon_name"&gt;&lt;/img&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.imgByIconId("icon_name").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.imgByIconId("icon_name").toHtml(); <br>
    * </p>
    *
    * @param iconId
@@ -342,7 +346,7 @@
    * Create a html list element with encoded text: &lt;li&gt;text&lt;/li&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.li("text").toEncodedHtml(); <br>
+   * String encodedHtml = HTML.li("text").toHtml(); <br>
    * </p>
    */
   public static IHtmlListElement li(CharSequence text) {
@@ -353,7 +357,7 @@
    * Create an unordered html list element with encoded text: &lt;ul&gt;...&lt;/ul&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.ul(HTML.li("text"),...).toEncodedHtml(); <br>
+   * String encodedHtml = HTML.ul(HTML.li("text"),...).toHtml(); <br>
    * </p>
    */
   public static IHtmlElement ul(IHtmlListElement... li) {
@@ -364,7 +368,7 @@
    * Create an unordered html list element with encoded text: &lt;ul&gt;...&lt;/ul&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.ul(HTML.li("text"),...).toEncodedHtml(); <br>
+   * String encodedHtml = HTML.ul(HTML.li("text"),...).toHtml(); <br>
    * </p>
    */
   public static IHtmlElement ul(List<IHtmlListElement> li) {
@@ -375,7 +379,7 @@
    * Create an ordered html list element with encoded text: &lt;ul&gt;...&lt;/ul&gt;.
    * <p>
    * Example:<br>
-   * String encodedHtml = HTML.ol(HTML.li("text"),...).toEncodedHtml(); <br>
+   * String encodedHtml = HTML.ol(HTML.li("text"),...).toHtml(); <br>
    * </p>
    */
   public static IHtmlContent ol(IHtmlListElement... li) {
@@ -490,7 +494,7 @@
   }
 
   /**
-   * Creates an application local link String encodedHtml = HTML.appLink("path","text").toEncodedHtml(); <br>
+   * Creates an application local link String encodedHtml = HTML.appLink("path","text").toHtml(); <br>
    *
    * @param ref
    *          what the link is referring to
@@ -538,7 +542,7 @@
   }
 
   /**
-   * Creates HTML content that will not be encoded with {@link IHtmlContent#toEncodedHtml()}. <b>Use with caution!</b>
+   * Creates HTML content that will not be encoded with {@link IHtmlContent#toHtml()}. <b>Use with caution!</b>
    */
   public static IHtmlContent raw(CharSequence... text) {
     return new HtmlPlainBuilder(text);
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTMLUtility.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTMLUtility.java
index cbf6a87..4968bda 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTMLUtility.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HTMLUtility.java
@@ -14,6 +14,8 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.net.MalformedURLException;
@@ -51,7 +53,7 @@
 /**
  * Utility to manipulate HTML documents regardless of ui.
  *
- * @deprecated This legacy utility will be removed in Scout 7. Use {@link org.eclipse.scout.rt.platform.html.HTML} and
+ * @deprecated This legacy utility will be removed in Scout 6.1. Use {@link org.eclipse.scout.rt.platform.html.HTML} and
  *             {@link HtmlHelper} instead.
  */
 @SuppressWarnings("deprecation")
@@ -141,7 +143,7 @@
       kit.write(buf, doc, 0, doc.getLength());
       htmlText = buf.toString();
     }
-    catch (Throwable t) {
+    catch (Throwable t) { //NOSONAR (deprecated class)
       LOG.error("failed to extract HTML text from HTML document", t);
     }
     return htmlText;
@@ -302,7 +304,7 @@
     if (htmlDoc == null) {
       return htmlDoc;
     }
-    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc;
+    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc; // NOSONAR (deprecated class)
     StyleSheet styleSheet = doc.getStyleSheet();
     Style style;
     // p style
@@ -427,7 +429,7 @@
     if (htmlDoc == null) {
       return htmlDoc;
     }
-    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc;
+    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc; // NOSONAR (deprecated class)
     StyleSheet styleSheet = doc.getStyleSheet();
     final IntegerHolder changeCount = new IntegerHolder(0);
     // visit all css attributes for occurrences of "cid:" URLs
@@ -484,7 +486,7 @@
     if (htmlDoc == null) {
       return htmlDoc;
     }
-    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc;
+    MutableHTMLDocument doc = (MutableHTMLDocument) htmlDoc; // NOSONAR (deprecated class)
     // StyleSheet styleSheet=doc.getStyleSheet();
     final IntegerHolder changeCount = new IntegerHolder(0);
     // visit all img tags for occurrences of "cid:" URLs
@@ -506,7 +508,9 @@
               // this file is not yet in cache and needs to be copied to cache
               File cacheFile = new File(cacheDir, f.getName());
               if (cacheFile.exists() && cacheFile.length() != f.length()) {
-                IOUtility.writeContent(new FileOutputStream(cacheFile), IOUtility.getContent(new FileInputStream(f)));
+                try (InputStream in = new FileInputStream(f); OutputStream out = new FileOutputStream(cacheFile)) {
+                  IOUtility.writeBytes(out, IOUtility.readBytes(in));
+                }
               }
               // change attribute value
               if (atts instanceof MutableAttributeSet) {
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlBinds.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlBinds.java
deleted file mode 100644
index b6c1773..0000000
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlBinds.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.platform.html;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.eclipse.scout.rt.platform.html.internal.HtmlBind;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-
-/**
- * HTML Binds <br>
- */
-public class HtmlBinds {
-
-  /**
-   * Internal map to store bind variables.
-   */
-  private final Map<String, Object> m_bindMap = new HashMap<>();
-
-  /**
-   * Prefix for bind variable name.
-   */
-  private final String m_prefix = ":b__";
-
-  /**
-   * sequence for bind names
-   */
-  private long m_sequenceId = 0L;
-
-  public IHtmlBind putString(String value) {
-    String qualifiedName = nextBindName();
-    m_bindMap.put(qualifiedName, value);
-    return new HtmlBind(qualifiedName);
-  }
-
-  /**
-   * Generates a unique bind variable for a given value and puts key and value into the bind map.<br>
-   * Puts a value with a generated key into the map.
-   *
-   * @return {@link IHtmlBind} key
-   */
-  public IHtmlBind put(Object value) {
-    return putString(StringUtility.nvl(value, ""));
-  }
-
-  /**
-   * @return a new bind name as <code>bindPrefix + sequenceId</code> for example <code>:b__0</code>
-   */
-  protected String nextBindName() {
-    String name = getBindName(m_sequenceId);
-    m_sequenceId++;
-    return name;
-  }
-
-  /**
-   * @return the bind name given a sequenceNr
-   */
-  private String getBindName(long sequenceNr) {
-    return m_prefix + sequenceNr;
-  }
-
-  /**
-   * @return value for a given bind key.
-   */
-  public Object getBindValue(String key) {
-    return m_bindMap.get(key);
-  }
-
-  /**
-   * @return prefix of all binds
-   */
-  protected String getPrefix() {
-    return m_prefix;
-  }
-
-  public Map<String, Object> getBindMap() {
-    return CollectionUtility.copyMap(m_bindMap);
-  }
-
-  public void putAll(HtmlBinds binds) {
-    for (Entry<String, Object> entry : binds.getBindMap().entrySet()) {
-      String key = entry.getKey();
-      long seq = getSequenceId(key);
-      if (!m_bindMap.containsKey(key)) {
-        m_bindMap.put(key, entry.getValue());
-        if (m_sequenceId <= seq) {
-          m_sequenceId = seq + 1;
-        }
-      }
-    }
-  }
-
-  private long getSequenceId(String key) {
-    String seq = key.substring(m_prefix.length());
-    return Long.parseLong(seq);
-  }
-
-  public Map<String, String> getReplacements(HtmlBinds binds) {
-    Map<String, String> replaceMap = new HashMap<>();
-    Map<String, Object> bindMap = binds.getBindMap();
-    ArrayList<String> keys = new ArrayList<>(bindMap.keySet());
-    Collections.sort(keys, new BindIdComparator());
-    for (String existingBind : keys) {
-      if (m_bindMap.containsKey(existingBind)) {
-        String newBind = nextBindName();
-        m_bindMap.put(newBind, bindMap.get(existingBind));
-        replaceMap.put(existingBind, newBind);
-      }
-    }
-    return replaceMap;
-  }
-
-  /**
-   * @return all bind parameters (keys) in the given String
-   */
-  public List<String> getBindParameters(CharSequence s) {
-    List<String> binds = new ArrayList<String>();
-    Pattern p = Pattern.compile(getPrefix() + "(\\d+)", Pattern.MULTILINE);
-    Matcher m = p.matcher(s);
-    while (m.find()) {
-      binds.add(m.group(0));
-    }
-    return binds;
-  }
-
-  @Override
-  public String toString() {
-    return "HtmlBinds [m_bindMap=" + m_bindMap + "]";
-  }
-
-  /**
-   * @param bindMap
-   */
-  public void replaceBinds(Map<String, String> bindMap) {
-    for (Entry<String, String> entry : bindMap.entrySet()) {
-      m_bindMap.put(entry.getValue(), m_bindMap.get(entry.getKey()));
-      m_bindMap.remove(entry.getKey());
-    }
-
-  }
-
-  class BindIdComparator implements Comparator<String> {
-
-    @Override
-    public int compare(String o1, String o2) {
-      return (int) (Long.parseLong(o1.substring(getPrefix().length())) - Long.parseLong(o2.substring(getPrefix().length())));
-    }
-
-  }
-
-}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlHelper.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlHelper.java
index e537365..0408f8d 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlHelper.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/HtmlHelper.java
@@ -39,11 +39,8 @@
    * <li>All other tags are replaced by a space.
    * <li>Multiple consecutive spaces are merged to one space.
    * <li>Leading and trailing whitespace line is removed from each line.
-   * <li>{@link StringUtility#htmlDecode(String)} is applied to the result, so not all HTML entities are replaced!
    * </ul>
    * <p>
-   * <i>Note: This method originated from the now-deprecated HTMLUtility. It is possible that it will be enhanced in
-   * future Scout releases.</i>
    */
   public String toPlainText(String html) {
     if (html == null || html.length() == 0) {
@@ -55,11 +52,12 @@
       s = html;
     }
     //newlines
-    s = s.replaceAll("\r", "").replaceAll("\n", " ");
+    s = StringUtility.replace(s, "\r", "");
+    s = StringUtility.replace(s, "\n", " ");
     Matcher matcher = HTML_PARAGRAPH_END_TAGS.matcher(s);
     s = matcher.replaceAll("\n");
     //tabs
-    s = s.replace(StringUtility.HTML_ENCODED_TAB, "\t");
+    s = StringUtility.replace(s, StringUtility.HTML_ENCODED_TAB, "\t");
     //remove tags
     s = Pattern.compile("<[^>]+>", Pattern.DOTALL).matcher(s).replaceAll(" ");
     //remove multiple spaces
@@ -67,7 +65,17 @@
     //remove spaces at the beginning and end of each line
     s = s.replaceAll("[ ]+\n", "\n");
     s = s.replaceAll("\n[ ]+", "\n");
-    s = StringUtility.htmlDecode(s);
+    s = unescape(s);
+
+    // space
+    s = StringUtility.replace(s, "&nbsp;", " ");
+    s = StringUtility.replace(s, "&#160;", " ");
+    s = StringUtility.replaceNoCase(s, "&#xa0;", " ");
+
+    // tab
+    s = StringUtility.replace(s, "&#9;", "\t");
+    s = StringUtility.replaceNoCase(s, "&#x9;", "\t");
+
     s = s.trim();
     return s;
   }
@@ -85,20 +93,22 @@
    * <li><code>&gt;</code> --> <code>&amp;gt;</code>
    * <li><code>&quot;</code> --> <code>&amp;quot;</code>
    * <li><code>&#39;</code> --> <code>&amp;#39;</code>
+   * <li><code>&#47;</code> --> <code>&amp;#47;</code>
    * </ul>
+   *
+   * @see https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
    */
   public String escape(String text) {
     if (text == null || text.length() == 0) {
       return text;
     }
-    //
-    String encoded = text
-        .replace("&", "&amp;")
-        .replace("<", "&lt;")
-        .replace(">", "&gt;")
-        .replace("\"", "&quot;")
-        .replace("'", "&#39;");
-    return encoded;
+    text = StringUtility.replace(text, "&", "&amp;");
+    text = StringUtility.replace(text, "<", "&lt;");
+    text = StringUtility.replace(text, ">", "&gt;");
+    text = StringUtility.replace(text, "\"", "&quot;");
+    text = StringUtility.replace(text, "/", "&#47;");
+    text = StringUtility.replace(text, "'", "&#39;");
+    return text;
   }
 
   /**
@@ -109,12 +119,45 @@
     if (html == null || html.length() == 0) {
       return html;
     }
-    String decoded = html
-        .replace("&amp;", "&")
-        .replace("&lt;", "<")
-        .replace("&gt;", ">")
-        .replace("&quot;", "\"")
-        .replace("&#39;", "'");
+
+    String decoded = StringUtility.replace(html, "&amp;", "&");
+    decoded = StringUtility.replace(decoded, "&#38;", "&");
+    decoded = StringUtility.replaceNoCase(decoded, "&#x26;", "&");
+
+    decoded = StringUtility.replace(decoded, "&lt;", "<");
+    decoded = StringUtility.replace(decoded, "&#60;", "<");
+    decoded = StringUtility.replaceNoCase(decoded, "&#x3c;", "<");
+
+    decoded = StringUtility.replace(decoded, "&gt;", ">");
+    decoded = StringUtility.replace(decoded, "&#62;", ">");
+    decoded = StringUtility.replaceNoCase(decoded, "&#x3e;", ">");
+
+    decoded = StringUtility.replace(decoded, "&quot;", "\"");
+    decoded = StringUtility.replace(decoded, "&#34;", "\"");
+    decoded = StringUtility.replaceNoCase(decoded, "&#x22;", "\"");
+
+    decoded = StringUtility.replace(decoded, "&#47;", "/"); // no named entity for the slash
+    decoded = StringUtility.replaceNoCase(decoded, "&#x2f;", "/");
+
+    decoded = StringUtility.replace(decoded, "&apos;", "'");
+    decoded = StringUtility.replace(decoded, "&#39;", "'");
+    decoded = StringUtility.replaceNoCase(decoded, "&#x27;", "'");
     return decoded;
   }
+
+  /**
+   * Replaces all new lines with a HTML line break (&lt;br&gt; tag). In some cases used after an {@link #escape(String)}
+   * operation.
+   */
+  public String newLineToBr(String input) {
+    String result = StringUtility.replace(input, "\r\n", "<br>");
+    return StringUtility.replace(result, "\n", "<br>");
+  }
+
+  /**
+   * Combined called, first {@link #escape(String)} and then {@link #newLineToBr(String)}.
+   */
+  public String escapeAndNewLineToBr(String text) {
+    return newLineToBr(escape(text));
+  }
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlBind.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlBind.java
deleted file mode 100644
index d363109..0000000
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlBind.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.platform.html;
-
-import java.util.Map;
-
-public interface IHtmlBind extends CharSequence {
-
-  void replaceBinds(Map<String, String> bindMap);
-
-}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlContent.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlContent.java
index 3473bbe..9d13b5f 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlContent.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlContent.java
@@ -10,17 +10,26 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.html;
 
+import java.io.Serializable;
+
 /**
  * Marker Interface for any Html Content that may contain bind variables.
  */
-public interface IHtmlContent extends IHtmlBind {
+public interface IHtmlContent extends CharSequence, Serializable {
 
-  String toEncodedHtml();
+  String toHtml();
 
   String toPlainText();
 
-  HtmlBinds getBinds();
+  /**
+   * See {@link #withNewLineToBr(boolean)}.
+   */
+  boolean isNewLineToBr();
 
-  void setBinds(HtmlBinds binds);
-
+  /**
+   * @param newLineToBr
+   *          {@code true} if new lines should be replaced by <b>br</b> tags, {@code false} otherwise (default is
+   *          {@code true}).
+   */
+  IHtmlContent withNewLineToBr(boolean newLineToBr);
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlDocument.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlDocument.java
index 056b312..c69a999 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlDocument.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlDocument.java
@@ -14,7 +14,7 @@
 
   String HTML5_DOCTYPE = "<!DOCTYPE html>";
 
-  IHtmlDocument doctype(CharSequence type);
+  IHtmlDocument doctype(String type);
 
   /**
    * @return HTML document with HTML5 doctype {@value IHtmlDocument#HTML5_DOCTYPE}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlTable.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlTable.java
index b4ac773..e35a52e 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlTable.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/IHtmlTable.java
@@ -16,18 +16,6 @@
 public interface IHtmlTable extends IHtmlElement {
 
   /**
-   * @deprecated use {@link IHtmlElement#cssClass(CharSequence)} or {@link IHtmlElement#style(CharSequence)}
-   */
-  @Deprecated
-  IHtmlTable cellspacing(int pixel);
-
-  /**
-   * @deprecated use {@link IHtmlElement#cssClass(CharSequence)} or {@link IHtmlElement#style(CharSequence)}
-   */
-  @Deprecated
-  IHtmlTable cellpadding(int pixel);
-
-  /**
    * Add a css class
    */
   @Override
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/AbstractExpressionBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/AbstractExpressionBuilder.java
index 448dd18..40167d2 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/AbstractExpressionBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/AbstractExpressionBuilder.java
@@ -10,27 +10,21 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.html.internal;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.html.HtmlBinds;
 import org.eclipse.scout.rt.platform.html.HtmlHelper;
 import org.eclipse.scout.rt.platform.html.IHtmlContent;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Buffer for expressions</br>
  * (not thread safe)
  */
 public abstract class AbstractExpressionBuilder implements CharSequence, IHtmlContent {
-  private static final Logger LOG = LoggerFactory.getLogger(AbstractExpressionBuilder.class);
+
+  private static final long serialVersionUID = 1L;
+
   private StringBuilder m_buf;
-  private HtmlBinds m_binds = new HtmlBinds();
+
+  private boolean m_newLineToBr = true;
 
   protected StringBuilder validate() {
     if (m_buf == null) {
@@ -44,6 +38,17 @@
     m_buf = null;
   }
 
+  @Override
+  public boolean isNewLineToBr() {
+    return m_newLineToBr;
+  }
+
+  @Override
+  public IHtmlContent withNewLineToBr(boolean newLineToBr) {
+    m_newLineToBr = newLineToBr;
+    return this;
+  }
+
   protected abstract void build();
 
   @Override
@@ -66,64 +71,43 @@
     return validate().toString();
   }
 
-  protected void append(CharSequence arg) {
-    m_buf.append(arg);
-  }
-
-  @Override
-  public HtmlBinds getBinds() {
-    return m_binds;
-  }
-
-  @Override
-  public void setBinds(HtmlBinds binds) {
-    m_binds = binds;
-  }
-
-  protected IHtmlContent importHtml(IHtmlContent contentText) {
-    HtmlBinds binds = contentText.getBinds();
-    Map<String, String> replacements = getBinds().getReplacements(binds);
-    if (!replacements.isEmpty()) {
-      contentText.replaceBinds(replacements);
+  protected void append(CharSequence arg, boolean escape) {
+    String toAppend = null;
+    if (arg == null) {
+      toAppend = "";
     }
-
-    getBinds().putAll(contentText.getBinds());
-    return contentText;
-  }
-
-  @Override
-  public String toEncodedHtml() {
-    String res = this.toString();
-    List<String> binds = getBinds().getBindParameters(res);
-    Collections.sort(binds, new ReversedLengthComparator());
-    for (String b : binds) {
-      Object value = getBinds().getBindValue(b);
-      if (value == null) {
-        LOG.error("No bind value found for ", b);
+    else if (escape) {
+      if (isNewLineToBr()) {
+        toAppend = escapeAndNewLineToBr(arg);
       }
       else {
-        String encode = encode(value);
-        // quoteReplacement disables special meaning of $ and \ (back-references)
-        res = res.replaceAll(b, Matcher.quoteReplacement(encode));
+        toAppend = escape(arg);
       }
     }
-    return res;
+    else {
+      toAppend = arg.toString();
+    }
+    m_buf.append(toAppend);
+  }
+
+  @Override
+  public String toHtml() {
+    return toString();
   }
 
   @Override
   public String toPlainText() {
-    return BEANS.get(HtmlHelper.class).toPlainText(toEncodedHtml());
+    return BEANS.get(HtmlHelper.class).toPlainText(toHtml());
   }
 
   /**
    * @return the encoded bind value.
    */
-  protected String encode(Object value) {
-    return StringUtility.htmlEncode(StringUtility.emptyIfNull(value).toString(), false);
+  protected String escape(Object value) {
+    return BEANS.get(HtmlHelper.class).escape(value.toString());
   }
 
-  @Override
-  public void replaceBinds(Map<String, String> bindMap) {
-    invalidate();
+  protected String escapeAndNewLineToBr(Object value) {
+    return BEANS.get(HtmlHelper.class).escapeAndNewLineToBr(value.toString());
   }
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/EmptyHtmlNodeBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/EmptyHtmlNodeBuilder.java
index c66ef21..eaacbe3 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/EmptyHtmlNodeBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/EmptyHtmlNodeBuilder.java
@@ -19,6 +19,8 @@
  */
 public class EmptyHtmlNodeBuilder extends HtmlNodeBuilder {
 
+  private static final long serialVersionUID = 1L;
+
   public EmptyHtmlNodeBuilder(String tag, CharSequence... texts) {
     this(tag, Arrays.asList(texts));
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlBind.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlBind.java
deleted file mode 100644
index 5b4c747..0000000
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlBind.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.platform.html.internal;
-
-import java.util.Map;
-
-import org.eclipse.scout.rt.platform.html.IHtmlBind;
-import org.eclipse.scout.rt.platform.util.Assertions;
-
-public class HtmlBind implements IHtmlBind {
-
-  private String m_name;
-
-  public HtmlBind(String name) {
-    m_name = Assertions.assertNotNull(name);
-  }
-
-  @Override
-  public int length() {
-    return m_name.length();
-  }
-
-  @Override
-  public char charAt(int index) {
-    return m_name.charAt(index);
-  }
-
-  @Override
-  public CharSequence subSequence(int start, int end) {
-    return m_name.subSequence(end, end);
-  }
-
-  @Override
-  public String toString() {
-    return m_name;
-  }
-
-  @Override
-  public void replaceBinds(Map<String, String> bindMap) {
-    String newBind = bindMap.get(m_name);
-    if (newBind != null) {
-      m_name = newBind;
-    }
-  }
-
-}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlContentBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlContentBuilder.java
index 2cf6900..d3d7e60 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlContentBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlContentBuilder.java
@@ -10,45 +10,40 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.html.internal;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 
-import org.eclipse.scout.rt.platform.html.IHtmlBind;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
 import org.eclipse.scout.rt.platform.html.IHtmlContent;
 
 /**
  * Empty node for HTML fragments: Creates a node that may contain other html content, but does not have a tag name.
  */
 public class HtmlContentBuilder extends AbstractExpressionBuilder implements IHtmlContent {
-  private final List<? extends IHtmlBind> m_texts;
+
+  private static final long serialVersionUID = 1L;
+
+  private final List<? extends CharSequence> m_texts;
 
   public HtmlContentBuilder(CharSequence... texts) {
     this(Arrays.asList(texts));
   }
 
   public HtmlContentBuilder(List<? extends CharSequence> texts) {
-    m_texts = importTexts(texts);
-  }
-
-  protected ArrayList<? extends IHtmlBind> importTexts(List<? extends CharSequence> texts) {
-    ArrayList<IHtmlBind> bindTexts = new ArrayList<IHtmlBind>();
+    // explicit check for non-serializable objects
     for (CharSequence text : texts) {
       if (text == null) {
         continue;
       }
-      else if (text instanceof IHtmlContent) {
-        bindTexts.add(importHtml((IHtmlContent) text));
-      }
-      else if (text instanceof IHtmlBind) {
-        bindTexts.add((IHtmlBind) text);
-      }
-      else {
-        bindTexts.add(getBinds().put(text));
+
+      if (!(text instanceof Serializable)) {
+        throw new ProcessingException("At least one provided char sequence is not serializable: {}", text);
       }
     }
-    return bindTexts;
+
+    m_texts = new ArrayList<>(texts);
   }
 
   @Override
@@ -60,20 +55,11 @@
 
   protected void appendText() {
     for (CharSequence t : m_texts) {
-      append(t);
+      append(t, !(t instanceof IHtmlContent));
     }
   }
 
-  @Override
-  public void replaceBinds(Map<String, String> bindMap) {
-    super.replaceBinds(bindMap);
-    for (IHtmlBind elem : m_texts) {
-      elem.replaceBinds(bindMap);
-    }
-  }
-
-  protected List<? extends IHtmlBind> getTexts() {
+  protected List<? extends CharSequence> getTexts() {
     return m_texts;
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlDocumentBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlDocumentBuilder.java
index 2e21a00..5dddf3a 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlDocumentBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlDocumentBuilder.java
@@ -13,7 +13,10 @@
 import org.eclipse.scout.rt.platform.html.IHtmlDocument;
 
 public class HtmlDocumentBuilder extends HtmlNodeBuilder implements IHtmlDocument {
-  private CharSequence m_docType;
+
+  private static final long serialVersionUID = 1L;
+
+  private String m_docType;
 
   public HtmlDocumentBuilder(CharSequence... texts) {
     super("html", texts);
@@ -22,13 +25,13 @@
   @Override
   public void build() {
     if (m_docType != null) {
-      append(m_docType);
+      append(m_docType, false);
     }
     super.build();
   }
 
   @Override
-  public IHtmlDocument doctype(CharSequence doctype) {
+  public IHtmlDocument doctype(String doctype) {
     m_docType = doctype;
     return this;
   }
@@ -37,5 +40,4 @@
   public IHtmlDocument doctype() {
     return doctype(IHtmlDocument.HTML5_DOCTYPE);
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlImageBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlImageBuilder.java
index 5e7a53b..0f7c41d 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlImageBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlImageBuilder.java
@@ -17,9 +17,10 @@
  */
 public class HtmlImageBuilder extends EmptyHtmlNodeBuilder implements IHtmlElement {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlImageBuilder(CharSequence path) {
     super("img");
     addAttribute("src", path);
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlInputBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlInputBuilder.java
index b21523c..67aabbe 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlInputBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlInputBuilder.java
@@ -15,6 +15,8 @@
 
 public class HtmlInputBuilder extends EmptyHtmlNodeBuilder implements IHtmlInput {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlInputBuilder() {
     super("input");
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlLinkBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlLinkBuilder.java
index e35e112..755af74 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlLinkBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlLinkBuilder.java
@@ -17,9 +17,10 @@
  */
 public class HtmlLinkBuilder extends HtmlNodeBuilder implements IHtmlElement {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlLinkBuilder(CharSequence url, CharSequence text) {
     super("a", text);
     addAttribute("href", url);
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlListElement.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlListElement.java
index 54df87c..2dd02a8 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlListElement.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlListElement.java
@@ -14,6 +14,8 @@
 
 public class HtmlListElement extends HtmlNodeBuilder implements IHtmlListElement {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlListElement(CharSequence text) {
     super("li", text);
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlNodeBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlNodeBuilder.java
index a25dcc8..4eeb19d 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlNodeBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlNodeBuilder.java
@@ -13,18 +13,20 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 
-import org.eclipse.scout.rt.platform.html.IHtmlBind;
+import org.eclipse.scout.rt.platform.html.IHtmlContent;
 import org.eclipse.scout.rt.platform.html.IHtmlElement;
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
+import org.eclipse.scout.rt.platform.util.StringUtility;
 
 /**
  * Builder for a html node with start tag, end tag and attributes.
  */
 public class HtmlNodeBuilder extends HtmlContentBuilder implements IHtmlElement {
 
-  private final List<IHtmlBind> m_attributes = new ArrayList<>();
+  private static final long serialVersionUID = 1L;
+
+  private final List<IHtmlContent> m_attributes = new ArrayList<>();
   private String m_tag;
 
   protected String getTag() {
@@ -54,22 +56,22 @@
   }
 
   protected void appendStartTag() {
-    append("<");
-    append(getTag());
+    append("<", false);
+    append(getTag(), true);
     appendAttributes();
-    append(">");
+    append(">", false);
   }
 
   protected void appendEndTag() {
-    append("</");
-    append(getTag());
-    append(">");
+    append("</", false);
+    append(getTag(), true);
+    append(">", false);
   }
 
   private void appendAttributes() {
     if (m_attributes.size() > 0) {
-      append(" ");
-      append(CollectionUtility.format(m_attributes, " "));
+      append(" ", false);
+      append(CollectionUtility.format(m_attributes, " "), false);
     }
   }
 
@@ -79,24 +81,24 @@
 
   @Override
   public IHtmlElement addAttribute(String name, CharSequence value) {
+    String attribValue = null;
+    final String doubleQuote = "\"";
+    if (value == null) {
+      attribValue = "";
+    }
+    else {
+      attribValue = StringUtility.replace(value.toString(), doubleQuote, "&quot;");
+    }
+
     HtmlContentBuilder content = new HtmlContentBuilder(
-        getBinds().put(name),
-        new HtmlPlainBuilder("=\""),
-        getBinds().put(value),
-        new HtmlPlainBuilder("\""));
+        new HtmlPlainBuilder(escape(name)),
+        new HtmlPlainBuilder("=" + doubleQuote),
+        new HtmlPlainBuilder(attribValue),
+        new HtmlPlainBuilder(doubleQuote));
     m_attributes.add(content);
     return this;
   }
 
-  @Override
-  public void replaceBinds(Map<String/*old Bind*/, String/*new Bind*/> bindMap) {
-    super.replaceBinds(bindMap);
-    for (IHtmlBind elem : m_attributes) {
-      elem.replaceBinds(bindMap);
-    }
-    getBinds().replaceBinds(bindMap);
-  }
-
 /// GLOBAL ATTRIBUTES
   @Override
   public IHtmlElement style(CharSequence value) {
@@ -116,5 +118,4 @@
     addAttribute("data-ref", ref);
     return this;
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlPlainBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlPlainBuilder.java
index e50c528..d46fbc2 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlPlainBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlPlainBuilder.java
@@ -10,13 +10,17 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.html.internal;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.eclipse.scout.rt.platform.html.IHtmlContent;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
 
 public class HtmlPlainBuilder extends AbstractExpressionBuilder {
+
+  private static final long serialVersionUID = 1L;
+
   private final List<? extends CharSequence> m_texts;
 
   public HtmlPlainBuilder(CharSequence... texts) {
@@ -24,23 +28,18 @@
   }
 
   public HtmlPlainBuilder(List<? extends CharSequence> texts) {
-    m_texts = importTexts(texts);
-  }
-
-  protected ArrayList<? extends CharSequence> importTexts(List<? extends CharSequence> texts) {
-    ArrayList<CharSequence> bindTexts = new ArrayList<CharSequence>();
+    // explicit check for non-serializable objects
     for (CharSequence text : texts) {
       if (text == null) {
         continue;
       }
-      if (text instanceof IHtmlContent) {
-        bindTexts.add(importHtml((IHtmlContent) text));
-      }
-      else {
-        bindTexts.add(text);
+
+      if (!(text instanceof Serializable)) {
+        throw new ProcessingException("At least one provided char sequence is not serializable: " + text);
       }
     }
-    return bindTexts;
+
+    m_texts = new ArrayList<>(texts);
   }
 
   @Override
@@ -52,8 +51,7 @@
 
   protected void appendText() {
     for (CharSequence t : m_texts) {
-      append(t);
+      append(t, false);
     }
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableBuilder.java
index d45846c..bdf2369 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableBuilder.java
@@ -12,7 +12,6 @@
 
 import java.util.List;
 
-import org.eclipse.scout.rt.platform.html.IHtmlElement;
 import org.eclipse.scout.rt.platform.html.IHtmlTable;
 import org.eclipse.scout.rt.platform.html.IHtmlTableRow;
 
@@ -21,33 +20,13 @@
  */
 public class HtmlTableBuilder extends HtmlNodeBuilder implements IHtmlTable {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlTableBuilder(List<IHtmlTableRow> rows) {
     super("table", rows);
   }
 
   /**
-   * @deprecated use {@link IHtmlElement#cssClass(CharSequence)} or {@link IHtmlElement#style(CharSequence)}
-   */
-  @SuppressWarnings("deprecation")
-  @Override
-  @Deprecated
-  public IHtmlTable cellspacing(int pixel) {
-    addAttribute("cellspacing", pixel);
-    return this;
-  }
-
-  /**
-   * @deprecated use {@link IHtmlElement#cssClass(CharSequence)} or {@link IHtmlElement#style(CharSequence)}
-   */
-  @SuppressWarnings("deprecation")
-  @Override
-  @Deprecated
-  public IHtmlTable cellpadding(int pixel) {
-    addAttribute("cellpadding", pixel);
-    return this;
-  }
-
-  /**
    * Add a css class
    */
   @Override
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableDataBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableDataBuilder.java
index aff7e4c..7ebb0a8 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableDataBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableDataBuilder.java
@@ -19,6 +19,8 @@
  */
 public class HtmlTableDataBuilder extends HtmlNodeBuilder implements IHtmlTableCell {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlTableDataBuilder(List<? extends CharSequence> text) {
     super("td", text);
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableRowBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableRowBuilder.java
index 239abe8..ab97f01 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableRowBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/HtmlTableRowBuilder.java
@@ -20,6 +20,8 @@
  */
 public class HtmlTableRowBuilder extends HtmlNodeBuilder implements IHtmlTableRow {
 
+  private static final long serialVersionUID = 1L;
+
   public HtmlTableRowBuilder(List<? extends IHtmlTableCell> text) {
     super("tr", text);
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/ReversedLengthComparator.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/ReversedLengthComparator.java
deleted file mode 100644
index 9f32439..0000000
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/ReversedLengthComparator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.platform.html.internal;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-public class ReversedLengthComparator implements Comparator<String>, Serializable {
-  private static final long serialVersionUID = 1L;
-
-  @Override
-  public int compare(String o1, String o2) {
-    return o2.length() - o1.length();
-  }
-
-}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/StyleElementBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/StyleElementBuilder.java
index d4bad81..5ab6e69 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/StyleElementBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/html/internal/StyleElementBuilder.java
@@ -14,6 +14,8 @@
 
 public class StyleElementBuilder extends HtmlNodeBuilder implements IStyleElement {
 
+  private static final long serialVersionUID = 1L;
+
   public StyleElementBuilder(CharSequence... elements) {
     super("style", elements);
   }
@@ -50,5 +52,4 @@
   public IStyleElement appLink(CharSequence ref) {
     return (IStyleElement) super.appLink(ref);
   }
-
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValueIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValueIndex.java
index 261a8f4..c62a518 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValueIndex.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValueIndex.java
@@ -10,100 +10,28 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.platform.index;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.scout.rt.platform.util.CollectionUtility;
 
 /**
  * Represents an index for which multiple elements can result in the very same index value.
+ * <p>
+ * Use this index if the element provides a single index value for this index.
  *
  * @since 5.1
  */
-public abstract class AbstractMultiValueIndex<INDEX, ELEMENT> implements IIndex<INDEX, ELEMENT> {
-
-  private final Map<INDEX, List<ELEMENT>> m_mapByIndex = new HashMap<>();
-  private final Map<ELEMENT, INDEX> m_mapByElement = new LinkedHashMap<>(); // LinkedHashMap to preserve insertion-order.
+public abstract class AbstractMultiValueIndex<INDEX, ELEMENT> extends AbstractMultiValuesIndex<INDEX, ELEMENT> {
 
   @Override
-  public boolean addToIndex(final ELEMENT element) {
-    if (m_mapByElement.containsKey(element)) {
-      removeFromIndex(element);
-    }
-
+  protected final Set<INDEX> calculateIndexesFor(final ELEMENT element) {
     final INDEX index = calculateIndexFor(element);
-    if (index == null) {
-      return false;
+    if (index != null) {
+      return CollectionUtility.hashSet(index);
     }
-
-    List<ELEMENT> elements = m_mapByIndex.get(index);
-    if (elements == null) {
-      elements = new ArrayList<>();
-      m_mapByIndex.put(index, elements);
+    else {
+      return CollectionUtility.emptyHashSet();
     }
-    elements.add(element);
-    m_mapByElement.put(element, index);
-
-    return true;
-  }
-
-  @Override
-  public boolean removeFromIndex(final ELEMENT element) {
-    final INDEX index = m_mapByElement.remove(element);
-    if (index == null) {
-      return false;
-    }
-
-    final List<ELEMENT> elements = m_mapByIndex.get(index);
-    elements.remove(element);
-    if (elements.isEmpty()) {
-      m_mapByIndex.remove(index);
-    }
-
-    return true;
-  }
-
-  @Override
-  public Set<INDEX> indexValues() {
-    return new HashSet<>(m_mapByIndex.keySet());
-  }
-
-  @Override
-  public List<ELEMENT> values() {
-    return new ArrayList<>(m_mapByElement.keySet()); // ordered as inserted because LinkedHashMap is used
-  }
-
-  @Override
-  public void clear() {
-    m_mapByIndex.clear();
-    m_mapByElement.clear();
-  }
-
-  @Override
-  public boolean contains(final ELEMENT element) {
-    return m_mapByElement.containsKey(element);
-  }
-
-  @Override
-  public Iterator<ELEMENT> iterator() {
-    return values().iterator();
-  }
-
-  /**
-   * Returns the elements that correspond to the given index value in the order as inserted.
-   *
-   * @param index
-   *          the index to look elements for.
-   * @return elements ordered as inserted, or an empty {@link List} if no found.
-   */
-  public List<ELEMENT> get(final INDEX index) {
-    return CollectionUtility.arrayList(m_mapByIndex.get(index));
   }
 
   /**
@@ -111,7 +39,7 @@
    *
    * @param element
    *          the element to calculate its index value.
-   * @return the index value, or <code>null</code> to not add to the index.
+   * @return the index value, or <code>null</code> to not add the element to this index.
    */
-  protected abstract INDEX calculateIndexFor(ELEMENT element);
+  protected abstract INDEX calculateIndexFor(final ELEMENT element);
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValuesIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValuesIndex.java
new file mode 100644
index 0000000..9762e0d
--- /dev/null
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractMultiValuesIndex.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.scout.rt.platform.index;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.scout.rt.platform.util.CollectionUtility;
+
+/**
+ * Represents an index for which multiple elements can result in the very same index value.
+ * <p>
+ * Use this index if the element provides a multiple index values for this index.
+ *
+ * @since 5.2
+ */
+public abstract class AbstractMultiValuesIndex<INDEX, ELEMENT> implements IMultiValueIndex<INDEX, ELEMENT> {
+
+  private final Map<INDEX, List<ELEMENT>> m_mapByIndex = new HashMap<>();
+  private final Map<ELEMENT, Set<INDEX>> m_mapByElement = new LinkedHashMap<>(); // LinkedHashMap to preserve insertion-order.
+
+  @Override
+  public boolean addToIndex(final ELEMENT element) {
+    if (m_mapByElement.containsKey(element)) {
+      removeFromIndex(element);
+    }
+
+    final Set<INDEX> indexes = calculateIndexesFor(element);
+    if (indexes == null || indexes.isEmpty()) {
+      return false;
+    }
+
+    for (final INDEX index : indexes) {
+      List<ELEMENT> elements = m_mapByIndex.get(index);
+      if (elements == null) {
+        elements = new ArrayList<>();
+        m_mapByIndex.put(index, elements);
+      }
+      elements.add(element);
+    }
+    m_mapByElement.put(element, new HashSet<>(indexes));
+
+    return true;
+  }
+
+  @Override
+  public boolean removeFromIndex(final ELEMENT element) {
+    final Set<INDEX> indexes = m_mapByElement.remove(element);
+    if (indexes == null) {
+      return false;
+    }
+
+    for (final INDEX index : indexes) {
+      final List<ELEMENT> elements = m_mapByIndex.get(index);
+      elements.remove(element);
+
+      if (elements.isEmpty()) {
+        m_mapByIndex.remove(index);
+      }
+    }
+
+    return true;
+  }
+
+  @Override
+  public Set<INDEX> indexValues() {
+    return new HashSet<>(m_mapByIndex.keySet());
+  }
+
+  @Override
+  public List<ELEMENT> values() {
+    return new ArrayList<>(m_mapByElement.keySet()); // ordered as inserted because LinkedHashMap is used
+  }
+
+  @Override
+  public void clear() {
+    m_mapByIndex.clear();
+    m_mapByElement.clear();
+  }
+
+  @Override
+  public boolean contains(final ELEMENT element) {
+    return m_mapByElement.containsKey(element);
+  }
+
+  @Override
+  public Iterator<ELEMENT> iterator() {
+    return values().iterator();
+  }
+
+  @Override
+  public List<ELEMENT> get(final INDEX index) {
+    return CollectionUtility.arrayList(m_mapByIndex.get(index));
+  }
+
+  /**
+   * Method invoked to calculate the index values for the given element.
+   *
+   * @param element
+   *          the element to calculate its index values.
+   * @return the index values, or <code>null</code> or an empty {@link Set} to not add the element to this index.
+   */
+  protected abstract Set<INDEX> calculateIndexesFor(final ELEMENT element);
+}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractSingleValueIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractSingleValueIndex.java
index 88fc673..91af9e8 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractSingleValueIndex.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/AbstractSingleValueIndex.java
@@ -24,7 +24,7 @@
  *
  * @since 5.1
  */
-public abstract class AbstractSingleValueIndex<INDEX, ELEMENT> implements IIndex<INDEX, ELEMENT> {
+public abstract class AbstractSingleValueIndex<INDEX, ELEMENT> implements ISingleValueIndex<INDEX, ELEMENT> {
 
   private final Map<INDEX, ELEMENT> m_mapByIndex = new HashMap<>();
   private final Map<ELEMENT, INDEX> m_mapByElement = new LinkedHashMap<>(); // LinkedHashMap to preserve insertion-order.
@@ -82,13 +82,7 @@
     return values().iterator();
   }
 
-  /**
-   * Returns the element that corresponds to the given index value.
-   *
-   * @param index
-   *          the index to look the element for.
-   * @return element, or <code>null</code> if not found.
-   */
+  @Override
   public ELEMENT get(final INDEX index) {
     return m_mapByIndex.get(index);
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IIndex.java
index 490c647..6825890 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IIndex.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IIndex.java
@@ -65,5 +65,5 @@
    * Iterator to iterate over indexed elements.
    */
   @Override
-  public Iterator<ELEMENT> iterator();
+  Iterator<ELEMENT> iterator();
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IMultiValueIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IMultiValueIndex.java
new file mode 100644
index 0000000..d455abf
--- /dev/null
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/IMultiValueIndex.java
@@ -0,0 +1,20 @@
+package org.eclipse.scout.rt.platform.index;
+
+import java.util.List;
+
+/**
+ * Represents an index for which multiple elements can result in the very same index value.
+ *
+ * @since 6.0
+ */
+public interface IMultiValueIndex<INDEX, ELEMENT> extends IIndex<INDEX, ELEMENT> {
+
+  /**
+   * Returns the elements that correspond to the given index value in the order as inserted.
+   *
+   * @param index
+   *          the index to look elements for.
+   * @return elements ordered as inserted, or an empty {@link List} if no found.
+   */
+  List<ELEMENT> get(INDEX index);
+}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/ISingleValueIndex.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/ISingleValueIndex.java
new file mode 100644
index 0000000..40a6f6e
--- /dev/null
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/index/ISingleValueIndex.java
@@ -0,0 +1,18 @@
+package org.eclipse.scout.rt.platform.index;
+
+/**
+ * Represents an index that is unique among all elements, e.g. an element's primary key.
+ *
+ * @since 6.0
+ */
+public interface ISingleValueIndex<INDEX, ELEMENT> extends IIndex<INDEX, ELEMENT> {
+
+  /**
+   * Returns the element that corresponds to the given index value.
+   *
+   * @param index
+   *          the index to look the element for.
+   * @return element, or <code>null</code> if not found.
+   */
+  ELEMENT get(INDEX index);
+}
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResource.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResource.java
index 857de4b..7606d3c 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResource.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResource.java
@@ -67,10 +67,9 @@
    *          default false
    * @param cacheMaxAge
    *          default 0
-   * @deprecated Use {@link BinaryResources} instead. Constructor will be package private in 6.0.
    */
-  @Deprecated
-  public BinaryResource(String filename, String contentType, String charset, byte[] content, long lastModified, boolean cachingAllowed, int cacheMaxAge) {
+  // explicitly package private, only called by BinaryResources and second constructor
+  BinaryResource(String filename, String contentType, String charset, byte[] content, long lastModified, boolean cachingAllowed, int cacheMaxAge) {
     m_filename = filename;
     if (contentType == null) {
       if (filename != null) {
@@ -102,39 +101,6 @@
   }
 
   /**
-   * Convenience constructor which assumes <code>filename = empty, lastModified = -1</code>.
-   *
-   * @see #BinaryResource(String, String, String, byte[], long)
-   * @deprecated Use {@link BinaryResources} instead (use contentType.getType() for string content type).
-   */
-  @Deprecated
-  public BinaryResource(MimeType contentType, byte[] content) {
-    this(null, contentType != null ? contentType.getType() : null, null, content, -1, false, 0);
-  }
-
-  /**
-   * Convenience constructor which assumes <code>charset = null</code>.
-   *
-   * @see #BinaryResource(String, String, String, byte[], long)
-   * @deprecated Use {@link BinaryResources} instead.
-   */
-  @Deprecated
-  public BinaryResource(String filename, String contentType, byte[] content, long lastModified) {
-    this(filename, contentType, null, content, lastModified, false, 0);
-  }
-
-  /**
-   * Convenience constructor which assumes <code>lastModified = -1</code>.
-   *
-   * @see #BinaryResource(String, String, String, byte[], long)
-   * @deprecated Use {@link BinaryResources} instead.
-   */
-  @Deprecated
-  public BinaryResource(String filename, String contentType, byte[] content) {
-    this(filename, contentType, null, content, -1, false, 0);
-  }
-
-  /**
    * Convenience constructor which assumes <code>contentType = null</code> and <code>lastModified = -1</code>
    * <p>
    * null contentType is replaced by {@link FileUtility#getContentTypeForExtension(String)}
@@ -146,19 +112,6 @@
   }
 
   /**
-   * Reads the contents of the given file into a new {@link BinaryResource}. This constructor is intended to read from
-   * temporary files only. If the file is not accessible, the constructor will fail.
-   *
-   * @deprecated Use {@link BinaryResources} to build resource instead and load properties manually (filename:
-   *             file.getName(), content type: FileUtility.getContentType(file), content: IOUtility.getContent(file),
-   *             last modified: file.lastModified()).
-   */
-  @Deprecated
-  public BinaryResource(File file) {
-    this(file.getName(), FileUtility.getContentType(file), null, IOUtility.getContent(file), file.lastModified(), false, 0);
-  }
-
-  /**
    * Checks if the filename is not empty and has text.
    */
   public boolean hasFilename() {
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResources.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResources.java
index 60ba8d3..4a38f44 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResources.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/resource/BinaryResources.java
@@ -129,7 +129,6 @@
   /**
    * @return Built binary resource
    */
-  @SuppressWarnings("deprecation")
   public BinaryResource build() {
     // constructor will be changed to package private in 6.0, thus suppress deprecation warning in 5.2
     return new BinaryResource(m_filename, m_contentType, m_charset, m_content, m_lastModified, m_cachingAllowed, m_cacheMaxAge);
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ConfigFileCredentialVerifier.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ConfigFileCredentialVerifier.java
similarity index 98%
rename from org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ConfigFileCredentialVerifier.java
rename to org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ConfigFileCredentialVerifier.java
index da2cfda..bf022a8 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ConfigFileCredentialVerifier.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ConfigFileCredentialVerifier.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
+package org.eclipse.scout.rt.platform.security;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -27,7 +27,6 @@
 import org.eclipse.scout.rt.platform.config.AbstractStringConfigProperty;
 import org.eclipse.scout.rt.platform.config.CONFIG;
 import org.eclipse.scout.rt.platform.config.IConfigProperty;
-import org.eclipse.scout.rt.platform.security.SecurityUtility;
 import org.eclipse.scout.rt.platform.util.Assertions;
 import org.eclipse.scout.rt.platform.util.Base64Utility;
 import org.eclipse.scout.rt.platform.util.StringUtility;
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ICredentialVerifier.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ICredentialVerifier.java
similarity index 95%
rename from org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ICredentialVerifier.java
rename to org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ICredentialVerifier.java
index d3a9f41..cd15ba2 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ICredentialVerifier.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/ICredentialVerifier.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
+package org.eclipse.scout.rt.platform.security;
 
 import java.io.IOException;
 
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IPrincipalProducer.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/IPrincipalProducer.java
similarity index 93%
rename from org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IPrincipalProducer.java
rename to org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/IPrincipalProducer.java
index bc77397..8d970e0 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IPrincipalProducer.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/IPrincipalProducer.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
+package org.eclipse.scout.rt.platform.security;
 
 import java.security.Principal;
 
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/MalwareScanner.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/MalwareScanner.java
index a92f297..c815739 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/MalwareScanner.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/MalwareScanner.java
@@ -58,7 +58,7 @@
       f = IOUtility.createTempFile("malware-scan", ".tmp", expected);
       byte[] actual;
       try (FileInputStream in = new FileInputStream(f)) {
-        actual = IOUtility.getContent(in, expected.length);
+        actual = IOUtility.readBytes(in, expected.length);
       }
       if (!Arrays.equals(expected, actual)) {
         throwUnsafeResource(res);
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/SimplePrincipalProducer.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/SimplePrincipalProducer.java
similarity index 64%
rename from org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/SimplePrincipalProducer.java
rename to org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/SimplePrincipalProducer.java
index f72b490..acecf38 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/SimplePrincipalProducer.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/security/SimplePrincipalProducer.java
@@ -8,19 +8,25 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
+package org.eclipse.scout.rt.platform.security;
 
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
+import java.security.Principal;
 
 /**
  * Producer for {@link SimplePrincipal} objects to represent authenticated users.
+ * <p>
+ * There are exactly two scenarios for user principals
+ * <ol>
+ * <li>Container manager security with container Subject and Principal: Then this facility is not used at all</li>
+ * <li>Scout based principals: Then this facility is used and by default creates {@link SimplePrincipal} objects</li>
+ * </ol>
  *
  * @since 5.2
  */
 public class SimplePrincipalProducer implements IPrincipalProducer {
 
   @Override
-  public SimplePrincipal produce(final String username) {
+  public Principal produce(String username) {
     return new SimplePrincipal(username);
   }
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/IOUtility.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/IOUtility.java
index ba6b7d3..1ef5118 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/IOUtility.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/IOUtility.java
@@ -11,7 +11,6 @@
 package org.eclipse.scout.rt.platform.util;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -26,6 +25,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringWriter;
@@ -43,6 +43,7 @@
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
+import org.eclipse.scout.rt.platform.exception.PlatformException;
 import org.eclipse.scout.rt.platform.exception.ProcessingException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -53,9 +54,39 @@
   private IOUtility() {
   }
 
+  public static byte[] getContent(String filename) {
+    return getContent(toFile(filename));
+  }
+
+  public static byte[] getContent(File file) {
+    try (FileInputStream in = new FileInputStream(file)) {
+      return readBytes(in);
+    }
+    catch (IOException e) {
+      throw new ProcessingException("filename: " + file.getAbsolutePath(), e);
+    }
+  }
+
   /**
-   * retrieve content as raw bytes
+   * Reads the content of a file in the specified encoding (charset-name) e.g. "UTF-8"
+   * <p>
+   * If no encoding is provided, the system default encoding is used
    */
+  public static String getContentInEncoding(String filepath, String encoding) {
+    try (FileInputStream in = new FileInputStream(filepath)) {
+      return readString(in, encoding);
+    }
+    catch (IOException e) {
+      throw new ProcessingException(e.getMessage(), e);
+    }
+  }
+
+  /**
+   * retrieve content as raw bytes and close the stream
+   *
+   * @deprecated use {@link #readBytes(InputStream)} within a resource-try statement
+   */
+  @Deprecated
   public static byte[] getContent(InputStream stream) {
     return getContent(stream, true);
   }
@@ -70,13 +101,15 @@
    * @param charsetName
    *          The name of the {@link Charset}.
    * @return A {@link String} containing the content of the given {@link InputStream}.
+   * @deprecated use {@link #readString(InputStream, String)} within a resource-try statement
    */
+  @Deprecated
   public static String getContent(InputStream stream, String charsetName) {
-    try {
-      return new String(IOUtility.getContent(stream), charsetName);
+    try (InputStream in = stream) {
+      return readString(in, charsetName);
     }
-    catch (UnsupportedEncodingException e) {
-      throw new ProcessingException("Unsupported encoding: '" + charsetName + "'.", e);
+    catch (IOException e) {
+      throw new ProcessingException("input: " + stream, e);
     }
   }
 
@@ -87,27 +120,231 @@
    * @param stream
    *          The {@link InputStream} to read from.
    * @return The content of the given {@link InputStream}.
+   * @deprecated use {@link #readStringUTF8(InputStream)} within a resource-try statement
    */
+  @Deprecated
   public static String getContentUtf8(InputStream stream) {
-    return getContent(stream, StandardCharsets.UTF_8.name());
+    try (InputStream in = stream) {
+      return readStringUTF8(in);
+    }
+    catch (IOException e) {
+      throw new ProcessingException("input: " + stream, e);
+    }
   }
 
-  public static byte[] getContent(InputStream in, int len) throws IOException {
-    if (len >= 0) {
-      byte[] buf = new byte[len];
-      int count = 0;
-      while (count < len) {
-        count += in.read(buf, count, len - count);
+  /**
+   * @deprecated use {@link #readBytes(InputStream, int)} within a resource-try statement
+   */
+  @Deprecated
+  public static byte[] getContent(InputStream stream, int len) throws IOException {
+    try (InputStream in = stream) {
+      return readBytes(in, len);
+    }
+    catch (IOException e) {
+      throw new ProcessingException("input: " + stream, e);
+    }
+  }
+
+  /**
+   * @deprecated use {@link #readBytes(InputStream)} within a resource-try statement
+   */
+  @Deprecated
+  public static byte[] getContent(InputStream stream, boolean autoClose) {
+    if (autoClose) {
+      try (InputStream in = stream) {
+        return readBytes(in);
       }
-      return buf;
+      catch (IOException e) {
+        throw new ProcessingException("input: " + stream, e);
+      }
     }
     else {
-      ByteArrayOutputStream out = new ByteArrayOutputStream();
-      int b;
-      while ((b = in.read()) >= 0) {
-        out.write(b);
+      return readBytes(stream);
+    }
+  }
+
+  /**
+   * retrieve content as string (correct character conversion)
+   *
+   * @deprecated use {@link #readString(Reader)} within a resource-try statement
+   */
+  @Deprecated
+  public static String getContent(Reader stream) {
+    return getContent(stream, true);
+  }
+
+  /**
+   * @deprecated use {@link #readString(Reader)} within a resource-try statement
+   */
+  @Deprecated
+  public static String getContent(Reader stream, boolean autoClose) {
+    if (stream == null) {
+      return "";
+    }
+    if (autoClose) {
+      try (Reader in = stream) {
+        return readString(in);
       }
-      return out.toByteArray();
+      catch (IOException e) {
+        throw new ProcessingException("input: " + stream, e);
+      }
+    }
+    else {
+      return readString(stream);
+    }
+  }
+
+  /**
+   * Reads bytes.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @return the content bytes
+   */
+  public static byte[] readBytes(InputStream in) {
+    return readBytes(in, -1);
+  }
+
+  /**
+   * Reads bytes.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @param len
+   *          optional known length or -1 if unknown
+   * @return the content bytes
+   */
+  public static byte[] readBytes(InputStream in, int len) {
+    if (len >= 0) {
+      try {
+        byte[] buf = new byte[len];
+        int count = 0;
+        while (count < len) {
+          count += in.read(buf, count, len - count);
+        }
+        return buf;
+      }
+      catch (IOException e) {
+        throw new ProcessingException("input: " + in, e);
+      }
+    }
+    else {
+      try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
+        byte[] b = new byte[10240];
+        int k;
+        while ((k = in.read(b)) > 0) {
+          buffer.write(b, 0, k);
+        }
+        return buffer.toByteArray();
+      }
+      catch (IOException e) {
+        throw new ProcessingException("input: " + in, e);
+      }
+    }
+  }
+
+  /**
+   * Reads string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @param charset
+   *          optional charset, if null is provided, the system default encoding is used
+   * @return the content string
+   */
+  public static String readString(InputStream in, String charset) {
+    return readString(in, charset, -1);
+  }
+
+  /**
+   * Reads string from UTF-8 encoded stream.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @return the content string
+   */
+  public static String readStringUTF8(InputStream in) {
+    return readString(in, StandardCharsets.UTF_8.name(), -1);
+  }
+
+  /**
+   * Reads string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @param charset
+   *          optional charset, if null is provided, the system default encoding is used
+   * @param len
+   *          optional known length in bytes or -1 if unknown
+   * @return the content string
+   */
+  public static String readString(InputStream in, String charset, int len) {
+    if (StringUtility.hasText(charset)) {
+      try {
+        return readString(new InputStreamReader(in, charset), len);
+      }
+      catch (UnsupportedEncodingException e) {
+        throw new PlatformException("charset {}", charset, e);
+      }
+    }
+    else {
+      return readString(new InputStreamReader(in), len);
+    }
+  }
+
+  /**
+   * Reads string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @return the content string
+   */
+  public static String readString(Reader in) {
+    return readString(in, -1);
+  }
+
+  /**
+   * Reads string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param in
+   * @param len
+   *          optional known length in bytes or -1 if unknown
+   * @return the content string
+   */
+  public static String readString(Reader in, int len) {
+    if (len >= 0) {
+      try {
+        char[] buf = new char[len];
+        int count = 0;
+        while (count < len) {
+          count += in.read(buf, count, len - count);
+        }
+        return new String(buf);
+      }
+      catch (IOException e) {
+        throw new ProcessingException("input: " + in, e);
+      }
+    }
+    else {
+      try (StringWriter buffer = new StringWriter()) {
+        char[] b = new char[10240];
+        int k;
+        while ((k = in.read(b)) > 0) {
+          buffer.write(b, 0, k);
+        }
+        return buffer.toString();
+      }
+      catch (IOException e) {
+        throw new ProcessingException("input: " + in, e);
+      }
     }
   }
 
@@ -145,116 +382,23 @@
     }
   }
 
-  public static byte[] getContent(InputStream stream, boolean autoClose) {
-    BufferedInputStream in = null;
-    try {
-      in = new BufferedInputStream(stream);
-      ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-      byte[] b = new byte[10240];
-      int len;
-      while ((len = in.read(b)) > 0) {
-        buffer.write(b, 0, len);
-      }
-      buffer.close();
-      byte[] data = buffer.toByteArray();
-      return data;
-    }
-    catch (IOException e) {
-      throw new ProcessingException("input: " + stream, e);
-    }
-    finally {
-      try {
-        if (autoClose && in != null) {
-          in.close();
-        }
-      }
-      catch (IOException e) {
-        throw new ProcessingException("input: " + stream, e);
-      }
-    }
-  }
-
-  public static byte[] getContent(File file) {
-    try {
-      return getContent(new FileInputStream(file), true);
-    }
-    catch (FileNotFoundException e) {
-      throw new ProcessingException("filename: " + file.getAbsolutePath(), e);
-    }
-  }
-
-  public static byte[] getContent(String filename) {
-    return getContent(toFile(filename));
-  }
-
-  /**
-   * Reads the content of a file in the specified encoding (charset-name) e.g. "UTF-8" If no encoding is provided, the
-   * system default encoding is used
-   */
-  public static String getContentInEncoding(String filepath, String encoding) {
-    try {
-      FileInputStream in = null;
-      String content = null;
-      try {
-        in = new FileInputStream(filepath);
-        if (StringUtility.hasText(encoding)) {
-          content = getContent(new InputStreamReader(in, encoding));
-        }
-        else {
-          content = getContent(new InputStreamReader(in));
-        }
-      }
-      finally {
-        if (in != null) {
-          in.close();
-        }
-      }
-      return content;
-    }
-    catch (IOException e) {
-      throw new ProcessingException(e.getMessage(), e);
-    }
-  }
-
-  /**
-   * write content as raw bytes
-   */
-  public static void writeContent(OutputStream stream, byte[] data) {
-    writeContent(stream, data, true);
-  }
-
-  public static void writeContent(OutputStream stream, byte[] data, boolean autoClose) {
-    BufferedOutputStream out = null;
-    try {
-      out = new BufferedOutputStream(stream);
-      out.write(data);
-    }
-    catch (IOException e) {
-      throw new ProcessingException("output: " + stream, e);
-    }
-    finally {
-      try {
-        if (autoClose && out != null) {
-          out.close();
-        }
-      }
-      catch (IOException e) {
-        throw new ProcessingException("output: " + stream, e);
-      }
-    }
-  }
-
   public static void writeContent(String filename, Object o) {
     File f = toFile(filename);
     try {
       if (o instanceof byte[]) {
-        writeContent(new FileOutputStream(f), (byte[]) o);
+        try (FileOutputStream out = new FileOutputStream(f)) {
+          writeBytes(out, (byte[]) o);
+        }
       }
       else if (o instanceof char[]) {
-        writeContent(new FileWriter(f), new String((char[]) o));
+        try (FileWriter out = new FileWriter(f)) {
+          writeString(out, new String((char[]) o));
+        }
       }
       else if (o != null) {
-        writeContent(new FileWriter(f), o.toString());
+        try (FileWriter out = new FileWriter(f)) {
+          writeString(out, o.toString());
+        }
       }
     }
     catch (FileNotFoundException n) {
@@ -265,64 +409,124 @@
     }
   }
 
-  public static void writeContent(Writer stream, String text) {
-    writeContent(stream, text, true);
+  /**
+   * write content as raw bytes
+   *
+   * @deprecated use {@link #writeBytes(OutputStream, byte[])} within a resource-try statement
+   */
+  @Deprecated
+  public static void writeContent(OutputStream stream, byte[] data) {
+    writeContent(stream, data, true);
   }
 
-  public static void writeContent(Writer stream, String text, boolean autoClose) {
-    try {
-      stream.write(text);
-    }
-    catch (IOException e) {
-      throw new ProcessingException("output: " + stream, e);
-    }
-    finally {
-      try {
-        if (autoClose && stream != null) {
-          stream.close();
-        }
+  /**
+   * @deprecated use {@link #writeBytes(OutputStream, byte[])} within a resource-try statement
+   */
+  @Deprecated
+  public static void writeContent(OutputStream stream, byte[] data, boolean autoClose) {
+    if (autoClose) {
+      try (OutputStream out = stream) {
+        writeBytes(out, data);
       }
       catch (IOException e) {
         throw new ProcessingException("output: " + stream, e);
       }
-
+    }
+    else {
+      writeBytes(stream, data);
     }
   }
 
   /**
-   * retrieve content as string (correct character conversion)
+   * @deprecated use {@link #writeString(Writer, String)} within a resource-try statement
    */
-  public static String getContent(Reader stream) {
-    return getContent(stream, true);
+  @Deprecated
+  public static void writeContent(Writer stream, String text) {
+    writeContent(stream, text, true);
   }
 
-  public static String getContent(Reader stream, boolean autoClose) {
-    BufferedReader in = null;
-    try {
-      in = new BufferedReader(stream);
-      StringWriter buffer = new StringWriter();
-      char[] b = new char[10240];
-      int len;
-      while ((len = in.read(b)) > 0) {
-        buffer.write(b, 0, len);
-      }
-      buffer.close();
-      return buffer.toString();
-    }
-    catch (IOException e) {
-      throw new ProcessingException("input: " + stream, e);
-    }
-
-    finally {
-      try {
-        if (autoClose && in != null) {
-          in.close();
-        }
+  /**
+   * @deprecated use {@link #writeString(Writer, String)} within a resource-try statement
+   */
+  @Deprecated
+  public static void writeContent(Writer stream, String text, boolean autoClose) {
+    if (autoClose) {
+      try (Writer out = stream) {
+        writeString(out, text);
       }
       catch (IOException e) {
-        throw new ProcessingException("input: " + stream, e);
+        throw new ProcessingException("output: " + stream, e);
       }
     }
+    else {
+      writeString(stream, text);
+    }
+  }
+
+  /**
+   * Write string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param out
+   * @param s
+   */
+  public static void writeBytes(OutputStream out, byte[] bytes) {
+    try {
+      out.write(bytes);
+    }
+    catch (IOException e) {
+      throw new ProcessingException("output: " + out, e);
+    }
+  }
+
+  /**
+   * Write string in UTF8 encoding.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param out
+   * @param s
+   */
+  public static void writeStringUTF8(OutputStream out, String s) {
+    writeString(out, StandardCharsets.UTF_8.name(), s);
+  }
+
+  /**
+   * Write string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param out
+   * @param charset
+   * @param s
+   */
+  public static void writeString(OutputStream out, String charset, String s) {
+    try {
+      OutputStreamWriter w = new OutputStreamWriter(out, charset);
+      w.write(s);
+      w.flush();
+    }
+    catch (IOException e) {
+      throw new ProcessingException("output: " + out, e);
+    }
+  }
+
+  /**
+   * Write string.
+   * <p>
+   * Stream is <em>not</em> closed. Use resource-try on streams created by caller.
+   *
+   * @param out
+   * @param s
+   */
+  public static void writeString(Writer out, String s) {
+    try {
+      out.write(s);
+    }
+    catch (IOException e) {
+      throw new ProcessingException("output: " + out, e);
+    }
   }
 
   /**
@@ -396,7 +600,9 @@
       }
       f2.deleteOnExit();
       if (content != null) {
-        writeContent(new FileOutputStream(f2), content);
+        try (OutputStream out = new FileOutputStream(f2)) {
+          writeBytes(out, content);
+        }
       }
       else {
         f2.createNewFile();
@@ -410,6 +616,8 @@
 
   /**
    * Creates a temp file from an input stream.
+   * <p>
+   * Content stream is closed automatically.
    *
    * @param content
    * @param filename
@@ -418,27 +626,16 @@
    * @throws ProcessingException
    */
   public static File createTempFile(InputStream content, String filename, String extension) throws ProcessingException {
-    File temp = null;
-    FileOutputStream fo = null;
     try {
-      temp = File.createTempFile(filename, extension);
-      fo = new FileOutputStream(temp);
-      IOUtility.writeContent(fo, IOUtility.getContent(content));
+      File temp = File.createTempFile(filename, extension);
+      try (InputStream in = content; FileOutputStream out = new FileOutputStream(temp)) {
+        writeBytes(out, readBytes(in));
+      }
+      return temp;
     }
     catch (IOException e) {
       throw new ProcessingException("Error creating temp file", e);
     }
-    finally {
-      if (fo != null) {
-        try {
-          fo.close();
-        }
-        catch (IOException e) {
-          // nop
-        }
-      }
-    }
-    return temp;
   }
 
   /**
@@ -459,7 +656,9 @@
       f = File.createTempFile(prefix, suffix);
       f.deleteOnExit();
       if (content != null) {
-        writeContent(new FileOutputStream(f), content);
+        try (OutputStream out = new FileOutputStream(f)) {
+          writeBytes(out, content);
+        }
       }
       return f;
     }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/StringUtility.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/StringUtility.java
index 95d47e4..de28383 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/StringUtility.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/StringUtility.java
@@ -926,11 +926,17 @@
 
   /**
    * @return encoded text, ready to be included in a html text <xmp>replaces &, ", ', <, > and all whitespace</xmp>
+   * @deprecated Will be removed in Scout 7.0. Use <code>BEANS.get(HtmlHelper.class).escape(String)</code> instead.
    */
+  @Deprecated
   public static String htmlEncode(String s) {
     return htmlEncode(s, false);
   }
 
+  /**
+   * @deprecated Will be removed in Scout 7.0. Use <code>BEANS.get(HtmlHelper.class).escape(String)</code> instead.
+   */
+  @Deprecated
   public static String htmlEncode(String s, boolean replaceSpace) {
     if (s == null) {
       return s;
@@ -962,7 +968,9 @@
 
   /**
    * @return decoded text, ready to be printed as text <xmp>replaces &, ", ', <, > and all whitespace</xmp>
+   * @deprecated Will be removed in Scout 7.0. Use <code>BEANS.get(HtmlHelper.class).unescape(String)</code> instead.
    */
+  @Deprecated
   public static String htmlDecode(String s) {
     if (s == null || s.length() == 0) {
       return s;
@@ -1357,14 +1365,37 @@
   }
 
   /**
-   * replace plain text without using regex
+   * Replaces each substring of the given source {@link String} that matches the given search {@link String} with the
+   * specified replacement {@link String}. The replacement proceeds from the beginning of the string to the end, for
+   * example, replacing "aa" with "b" in the string "aaa" will result in "ba" rather than "ab".
+   *
+   * @param source
+   *          The original string
+   * @param search
+   *          The string to be searched within the source string
+   * @param replacement
+   *          The new string that should be used instead of the search string
+   * @return A new string with all occurences of search replaced to replacement.
    */
-  public static String replace(String s, String sOld, String sNew) {
-    sNew = (sNew == null ? "" : sNew);
-    if (s == null || sOld == null) {
-      return s;
+  public static String replace(final String source, final String search, String replacement) {
+    if (source == null || source.length() < 1 || search == null || search.length() < 1) {
+      return source;
     }
-    return s.replace(sOld, sNew);
+    if (replacement == null) {
+      replacement = "";
+    }
+
+    final int searchLength = search.length();
+    StringBuilder result = new StringBuilder(source.length());
+    int lastPos = 0;
+    int occurrenceIndex = source.indexOf(search, lastPos);
+    while (occurrenceIndex >= 0) {
+      result.append(source.substring(lastPos, occurrenceIndex)).append(replacement);
+      lastPos = occurrenceIndex + searchLength;
+      occurrenceIndex = source.indexOf(search, lastPos);
+    }
+    result.append(source.substring(lastPos));
+    return result.toString();
   }
 
   /**
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriBuilder.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriBuilder.java
index 28539c5..b2db230 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriBuilder.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriBuilder.java
@@ -11,10 +11,12 @@
 package org.eclipse.scout.rt.platform.util;
 
 import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -24,14 +26,16 @@
 
 /**
  * Builder for {@link URI} and {@link URL} instances.
- * 
+ *
  * @since 3.8.1
  */
 public class UriBuilder {
 
   private static final Logger LOG = LoggerFactory.getLogger(UriBuilder.class);
 
-  private final Map<String, String> m_parameters = new HashMap<String, String>();
+  private static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name();
+
+  private final Map<String, String> m_parameters = new HashMap<>();
   private String m_scheme;
   private String m_host;
   private int m_port = -1;
@@ -42,7 +46,7 @@
   }
 
   public UriBuilder(String uri) {
-    this(uri, null);
+    this(uri, DEFAULT_ENCODING);
   }
 
   public UriBuilder(String uri, String encoding) {
@@ -50,11 +54,11 @@
   }
 
   public UriBuilder(URL url) {
-    this(UriUtility.urlToUri(url), null);
+    this(UriUtility.urlToUri(url), DEFAULT_ENCODING);
   }
 
   public UriBuilder(URI uri) {
-    this(uri, null);
+    this(uri, DEFAULT_ENCODING);
   }
 
   public UriBuilder(URL url, String encoding) {
@@ -86,7 +90,7 @@
 
   /**
    * Sets the remote host's port. Values lower than 1 are resetting a possibly set explicit port.
-   * 
+   *
    * @param port
    * @return
    */
@@ -107,11 +111,19 @@
 
   public UriBuilder addPath(String path) {
     if (StringUtility.hasText(path)) {
-      m_path = StringUtility.join("/", m_path, path);
+      m_path = StringUtility.join("/", removeTrailingSlash(m_path), path);
     }
+    ensureAbsolutePathWithHost();
     return this;
   }
 
+  private String removeTrailingSlash(String path) {
+    if (path != null && path.endsWith("/")) {
+      return path.substring(0, path.length() - 1);
+    }
+    return path;
+  }
+
   public UriBuilder fragment(String fragment) {
     m_fragment = fragment;
     return this;
@@ -131,50 +143,77 @@
   }
 
   public URL createURL() {
-    return createURL(null);
+    return createURL(DEFAULT_ENCODING);
   }
 
   public URI createURI() {
-    return createURI(null);
+    return createURI(DEFAULT_ENCODING);
   }
 
   public URL createURL(String encoding) {
-    return UriUtility.uriToUrl(createURI(encoding));
+    URI uri = createURI(encoding);
+    return UriUtility.uriToUrl(uri);
   }
 
   public URI createURI(String encoding) {
     try {
-      if (m_parameters == null || m_parameters.isEmpty()) {
-        return new URI(m_scheme, null, m_host, m_port, m_path, null, m_fragment);
-      }
-      if (encoding == null) {
-        encoding = UriUtility.ISO_8859_1;
-      }
-      StringBuilder query = new StringBuilder();
-      for (Map.Entry<String, String> param : m_parameters.entrySet()) {
-        if (!StringUtility.hasText(param.getKey())) {
-          LOG.warn("ignoring parameter with empty key");
-          continue;
-        }
-        if (query.length() > 0) {
-          query.append("&");
-        }
-        try {
-          query.append(URLEncoder.encode(param.getKey(), encoding));
-          query.append("=");
-          query.append(URLEncoder.encode(param.getValue(), encoding));
-        }
-        catch (UnsupportedEncodingException e) {
-          throw new ProcessingException("Unsupported encoding '" + encoding + "'", e);
-        }
-      }
-      return new URI(m_scheme, null, m_host, m_port, m_path, query.toString(), m_fragment);
+      return createURIInternal(encoding);
     }
-    catch (URISyntaxException e) {
+    catch (MalformedURLException | URISyntaxException e) {
       throw new ProcessingException("error creating URI", e);
     }
   }
 
+  // Inspired by: https://blog.stackhunter.com/2014/03/31/encode-special-characters-java-net-uri/
+  // See also: http://stackoverflow.com/questions/19917079/java-net-uri-and-percent-in-query-parameter-value
+  // It seems that the URI class knows nothing about key/value pairs used by most webservers.
+  // the URI class just makes sure that the query-string is correct according to the rules defined by the RFC.
+  // Thus: we can and should not use URI as an object to store query-parameters. Maybe we should replace our own
+  // API with a custom GetRequest implementation.
+  // Another approach would be to use URL instead of URI since, the URL class does not change the query string.
+  private URI createURIInternal(String encoding) throws MalformedURLException, URISyntaxException {
+    final URI uri = new URI(m_scheme, null, m_host, m_port, m_path, null, null);
+    final String urlWithQuery = StringUtility.join("?", uri.toString(), getQueryString(encoding));
+    final String fullUrl = StringUtility.join("#", urlWithQuery, m_fragment);
+    return new URI(fullUrl);
+  }
+
+  /**
+   * Ensures, that the path is absolute, if the host is defined
+   */
+  private void ensureAbsolutePathWithHost() {
+    if (m_host != null && !m_host.isEmpty() && m_path != null && !m_path.startsWith("/")) {
+      m_path = "/" + m_path;
+    }
+  }
+
+  private String getQueryString(String encoding) {
+    Assertions.assertNotNull(encoding);
+    if (m_parameters == null || m_parameters.isEmpty()) {
+      return null;
+    }
+
+    StringBuilder query = new StringBuilder();
+    for (Map.Entry<String, String> param : m_parameters.entrySet()) {
+      if (!StringUtility.hasText(param.getKey())) {
+        LOG.warn("ignoring parameter with empty key");
+        continue;
+      }
+      if (query.length() > 0) {
+        query.append("&");
+      }
+      try {
+        query.append(URLEncoder.encode(param.getKey(), encoding));
+        query.append("=");
+        query.append(URLEncoder.encode(param.getValue(), encoding));
+      }
+      catch (UnsupportedEncodingException e) {
+        throw new ProcessingException("Unsupported encoding '" + encoding + "'", e);
+      }
+    }
+    return query.toString();
+  }
+
   public String getScheme() {
     return m_scheme;
   }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriUtility.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriUtility.java
index 4e29b8f..5648611 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriUtility.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/UriUtility.java
@@ -16,6 +16,7 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -31,13 +32,13 @@
 public final class UriUtility {
 
   private static final Logger LOG = LoggerFactory.getLogger(UriUtility.class);
-  public static final String ISO_8859_1 = "ISO-8859-1";
+  private static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name();
 
   private UriUtility() {
   }
 
   /**
-   * Parses the given URL's query string using encoding ISO-8859-1 and extracts the query parameter.
+   * Parses the given URL's query string using encoding UTF_8 and extracts the query parameter.
    *
    * @param uri
    * @return map with parsed query parameters. Never <code>null</code>.
@@ -51,18 +52,18 @@
    *
    * @param uri
    * @param encoding
-   *          encoding of the query parameter. If <code>null</code> ISO-8859-1 is used.
+   *          encoding of the query parameter. If <code>null</code> UTF_8 is used.
    * @return map with parsed query parameters. Never <code>null</code>.
    */
   public static Map<String, String> getQueryParameters(URL url, String encoding) {
     if (url == null) {
-      return new HashMap<String, String>(0);
+      return new HashMap<>(0);
     }
     return getQueryParameters(urlToUri(url), encoding);
   }
 
   /**
-   * Parses the given URI's query string using encoding ISO-8859-1 and extracts the query parameter.
+   * Parses the given URI's query string using encoding UTF_8 and extracts the query parameter.
    *
    * @param uri
    * @return map with parsed query parameters. Never <code>null</code>.
@@ -76,24 +77,25 @@
    *
    * @param uri
    * @param encoding
-   *          encoding of the query parameter. If <code>null</code> ISO-8859-1 is used.
+   *          encoding of the query parameter. If <code>null</code> UTF-8 is used.
    * @return map with parsed query parameters. Never <code>null</code>.
    */
   public static Map<String, String> getQueryParameters(URI uri, String encoding) {
     if (uri == null || uri.getQuery() == null) {
-      return new HashMap<String, String>(0);
+      return new HashMap<>(0);
     }
-    String[] params = uri.getQuery().split("&");
-    Map<String, String> result = new HashMap<String, String>(params.length);
+    if (encoding == null) {
+      encoding = DEFAULT_ENCODING;
+    }
+
+    String[] params = getQueryString(uri).split("&");
+    Map<String, String> result = new HashMap<>(params.length);
     for (String param : params) {
       String[] parts = StringUtility.split(param, "=");
       if (parts.length != 2) {
         throw new ProcessingException("invalid query parameter: '" + param + "'");
       }
       try {
-        if (encoding == null) {
-          encoding = ISO_8859_1;
-        }
         String key = URLDecoder.decode(parts[0], encoding);
         String value = URLDecoder.decode(parts[1], encoding);
         String existingMapping = result.put(key, value);
@@ -109,6 +111,21 @@
   }
 
   /**
+   * Find exact query string instead of decoded query string from {@link URI#getQuery()} to allow for encoded characters
+   * like '=' in query values.
+   */
+  private static String getQueryString(URI uri) {
+    final String uriString = Assertions.assertNotNull(uri).toString();
+    final int start = uriString.indexOf("?");
+    if (start > 0) {
+      final int fragmentStart = uriString.indexOf("#", start);
+      final int end = fragmentStart > 0 ? fragmentStart : uriString.length();
+      return uriString.substring(start + 1, end);
+    }
+    return "";
+  }
+
+  /**
    * Splits the path of the given {@link URI} in its elements.
    *
    * @param uri
@@ -196,4 +213,5 @@
       throw new ProcessingException("Exception while parsing URL", e);
     }
   }
+
 }
diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/VerboseUtility.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/VerboseUtility.java
index 460aa66..4dd7ddb 100644
--- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/VerboseUtility.java
+++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/util/VerboseUtility.java
@@ -29,8 +29,8 @@
   }
 
   public static String dumpGenerics(Type... types) {
-    HashMap<Type, String> longDesc = new HashMap<Type, String>();
-    StringBuffer buf = new StringBuffer();
+    HashMap<Type, String> longDesc = new HashMap<>();
+    StringBuilder buf = new StringBuilder();
     buf.append(dumpGenericsRec(new HashMap<Type, String>(), longDesc, types));
     longDesc.remove(Object.class);
     if (longDesc.size() > 0) {
@@ -50,7 +50,7 @@
     if (types.length == 1) {
       return dumpGenericsImpl(shortDecl, longDecl, types[0]);
     }
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append("{");
     for (Type t : types) {
       if (buf.length() > 1) {
@@ -146,7 +146,7 @@
       return "null";
     }
     if (o.getClass().isArray()) {
-      StringBuffer buf = new StringBuffer();
+      StringBuilder buf = new StringBuilder();
       buf.append("[");
       int n = Array.getLength(o);
       if (n > 100) {
@@ -198,7 +198,7 @@
     if (args == null) {
       return "";
     }
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     for (int i = 0; i < args.length; i++) {
       buf.append(dumpObject(args[i]));
       if (i + 1 < args.length) {
diff --git a/org.eclipse.scout.rt.server.commons.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.commons.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.commons.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.commons.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.commons.test/pom.xml b/org.eclipse.scout.rt.server.commons.test/pom.xml
index 8442805..88c1486 100644
--- a/org.eclipse.scout.rt.server.commons.test/pom.xml
+++ b/org.eclipse.scout.rt.server.commons.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.commons.test/src/test/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilterTest.java b/org.eclipse.scout.rt.server.commons.test/src/test/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilterTest.java
deleted file mode 100644
index 6ec6fab..0000000
--- a/org.eclipse.scout.rt.server.commons.test/src/test/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilterTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.BeanMetaData;
-import org.eclipse.scout.rt.platform.IBean;
-import org.eclipse.scout.rt.server.commons.cache.IHttpSessionCacheService;
-import org.eclipse.scout.rt.server.commons.cache.TestHttpSession;
-import org.eclipse.scout.rt.testing.platform.runner.PlatformTestRunner;
-import org.eclipse.scout.rt.testing.shared.TestingUtility;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-
-/**
- * Test for {@link BasicSecurityFilter}
- */
-@RunWith(PlatformTestRunner.class)
-@SuppressWarnings("deprecation")
-public class BasicSecurityFilterTest {
-  private HttpServletRequest m_requestMock;
-  private HttpServletResponse m_responseMock;
-  private PrincipalHolder m_testPrincipalHolder;
-  private BasicSecurityFilter m_filter;
-  private List<IBean<?>> m_registeredServices = new ArrayList<IBean<?>>();
-  private FilterConfig m_testFilterConfig;
-
-  @Before
-  public void setup() {
-    m_requestMock = mock(HttpServletRequest.class);
-    m_responseMock = mock(HttpServletResponse.class);
-    m_testPrincipalHolder = new PrincipalHolder();
-    when(m_requestMock.getSession(true)).thenReturn(new TestHttpSession());
-    when(m_requestMock.getSession()).thenReturn(new TestHttpSession());
-    m_filter = new BasicSecurityFilter();
-    m_testFilterConfig = mock(FilterConfig.class);
-    when(m_testFilterConfig.getInitParameter("users")).thenReturn("admin=secret");
-  }
-
-  @After
-  public void tearDown() {
-    TestingUtility.unregisterBeans(m_registeredServices);
-  }
-
-  @Test
-  public void testAuthenticateHeaderOnFirstAttempt() throws IOException, ServletException {
-    negotiateNTimes(1);
-    verify(m_responseMock, times(1)).setHeader(anyString(), anyString());
-  }
-
-  @Test
-  public void testNoAuthenticateHeaderOnThirdAttempt() throws IOException, ServletException {
-    negotiateNTimes(10);
-    verify(m_responseMock, times(3)).setHeader(anyString(), anyString());
-  }
-
-  private void negotiateNTimes(int n) throws IOException, ServletException {
-    for (int i = 0; i < n; i++) {
-      m_filter.negotiate(m_requestMock, m_responseMock, m_testPrincipalHolder);
-    }
-  }
-
-  @Test
-  public void testFilterNotAuthenticated() throws IOException, ServletException {
-    IHttpSessionCacheService cacheService = mock(IHttpSessionCacheService.class);
-    registerTestService(cacheService, IHttpSessionCacheService.class);
-
-    BasicSecurityFilter f = new BasicSecurityFilter();
-    f.init(m_testFilterConfig);
-    f.doFilter(m_requestMock, m_responseMock, null);
-
-    verify(cacheService, times(0)).put(subjectProperty(), anyObject(), any(HttpServletRequest.class), any(HttpServletResponse.class));
-    verify(cacheService, times(0)).put(subjectProperty(), anyObject(), any(HttpServletRequest.class), any(HttpServletResponse.class), anyLong());
-  }
-
-  @Test
-  public void testFilterAuthenticated() throws IOException, ServletException {
-    IHttpSessionCacheService cacheService = mock(IHttpSessionCacheService.class);
-    registerTestService(cacheService, IHttpSessionCacheService.class);
-
-    BasicSecurityFilter f = new BasicSecurityFilter();
-    f.init(m_testFilterConfig);
-    final String validAutHeader = "Basic YWRtaW46c2VjcmV0";
-    when(m_requestMock.getHeader(anyString())).thenReturn(validAutHeader);
-    f.doFilter(m_requestMock, m_responseMock, mock(FilterChain.class));
-    verify(cacheService).put(subjectProperty(), anyObject(), any(HttpServletRequest.class), any(HttpServletResponse.class));
-  }
-
-  private <SERVICE> void registerTestService(SERVICE service, Class<? extends SERVICE> clazz) {
-    m_registeredServices.add(
-        TestingUtility.registerBean(
-            new BeanMetaData(clazz)
-                .withInitialInstance(service)
-                .withApplicationScoped(true)));
-  }
-
-  private String subjectProperty() {
-    return argThat(new ArgumentMatcher<String>() {
-
-      @Override
-      public boolean matches(Object item) {
-        return BasicSecurityFilter.PROP_SUBJECT.equals(item);
-      }
-    });
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.commons/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.commons/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.commons/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.commons/pom.xml b/org.eclipse.scout.rt.server.commons/pom.xml
index 067b352..52ec157 100644
--- a/org.eclipse.scout.rt.server.commons/pom.xml
+++ b/org.eclipse.scout.rt.server.commons/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/BufferedServletInputStream.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/BufferedServletInputStream.java
index 4f010ed..1524af8 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/BufferedServletInputStream.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/BufferedServletInputStream.java
@@ -26,11 +26,11 @@
   private volatile boolean m_finished;
 
   public BufferedServletInputStream(InputStream source, int len) throws IOException {
-    this(IOUtility.getContent(source, len)); // maybe read the data async?
+    this(IOUtility.readBytes(source, len)); // maybe read the data async?
   }
 
   public BufferedServletInputStream(InputStream source) throws IOException {
-    this(IOUtility.getContent(source, -1));
+    this(IOUtility.readBytes(source));
   }
 
   public BufferedServletInputStream(byte[] data) {
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/ServerCommonsConfigProperties.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/ServerCommonsConfigProperties.java
new file mode 100644
index 0000000..2197f57
--- /dev/null
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/ServerCommonsConfigProperties.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+ * http://www.bsiag.com/
+ */
+package org.eclipse.scout.rt.server.commons;
+
+import org.eclipse.scout.rt.platform.Platform;
+import org.eclipse.scout.rt.platform.config.AbstractBooleanConfigProperty;
+import org.eclipse.scout.rt.server.commons.servlet.UrlHints;
+
+public final class ServerCommonsConfigProperties {
+
+  private ServerCommonsConfigProperties() {
+  }
+
+  /**
+   * Enable or disable changing {@link UrlHints} using URL parameters in the browser address line
+   */
+  public static class UrlHintsEnabledProperty extends AbstractBooleanConfigProperty {
+
+    @Override
+    protected Boolean getDefaultValue() {
+      return Platform.get().inDevelopmentMode();
+    }
+
+    @Override
+    public String getKey() {
+      return "scout.urlHints.enabled";
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/AnonymousAccessController.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/AnonymousAccessController.java
index caacfb0..dc50e68 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/AnonymousAccessController.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/AnonymousAccessController.java
@@ -21,6 +21,8 @@
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.config.AbstractBooleanConfigProperty;
 import org.eclipse.scout.rt.platform.config.CONFIG;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.SimplePrincipalProducer;
 
 /**
  * Access controller to always continue filter-chain with a fixed user. By default, the user's name is 'anonymous'.
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/FormBasedAccessController.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/FormBasedAccessController.java
index 2223d3f..ff6007d 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/FormBasedAccessController.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/FormBasedAccessController.java
@@ -23,6 +23,9 @@
 import javax.servlet.http.HttpSession;
 
 import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.SimplePrincipalProducer;
 import org.eclipse.scout.rt.platform.util.Assertions;
 import org.eclipse.scout.rt.platform.util.SleepUtil;
 import org.eclipse.scout.rt.platform.util.StringUtility;
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IAccessController.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IAccessController.java
index ca32296..304e941 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IAccessController.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/IAccessController.java
@@ -19,6 +19,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.eclipse.scout.rt.platform.Bean;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
 
 /**
  * Provides functionality to control access to resources only accessible for authenticated users.
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipal.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipal.java
deleted file mode 100644
index e001675..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipal.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.eclipse.scout.rt.platform.util.Assertions;
-
-/**
- * Principal representing a {@link HttpServletRequest#getRemoteUser()}.
- *
- * @since 5.1
- */
-public class RemoteUserPrincipal implements Principal, Serializable {
-
-  private static final long serialVersionUID = 1L;
-
-  private final String m_name;
-
-  public RemoteUserPrincipal(final String name) {
-    m_name = Assertions.assertNotNull(name, "name must not be null").toLowerCase();
-  }
-
-  @Override
-  public String getName() {
-    return m_name;
-  }
-
-  @Override
-  public int hashCode() {
-    return m_name.hashCode();
-  }
-
-  @Override
-  public boolean equals(final Object other) {
-    if (other == null) {
-      return false;
-    }
-    if (other == this) {
-      return true;
-    }
-    if (other.getClass() != this.getClass()) {
-      return false;
-    }
-    return ((RemoteUserPrincipal) other).m_name.equals(this.m_name);
-  }
-
-  @Override
-  public String toString() {
-    return getName();
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipalProducer.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipalProducer.java
deleted file mode 100644
index ed0381c..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/RemoteUserPrincipalProducer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
-
-/**
- * Producer for {@link RemoteUserPrincipal} objects.
- *
- * @since 5.2
- */
-public class RemoteUserPrincipalProducer implements IPrincipalProducer {
-
-  @Override
-  public RemoteUserPrincipal produce(final String username) {
-    return new RemoteUserPrincipal(username);
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelAccessTokenAccessController.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelAccessTokenAccessController.java
index b351889..4a790ed 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelAccessTokenAccessController.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelAccessTokenAccessController.java
@@ -20,9 +20,11 @@
 import javax.servlet.http.HttpSession;
 
 import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.SimplePrincipalProducer;
 import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.eclipse.scout.rt.shared.servicetunnel.http.AbstractHttpServiceTunnel;
 import org.eclipse.scout.rt.shared.servicetunnel.http.DefaultAuthToken;
+import org.eclipse.scout.rt.shared.servicetunnel.http.HttpServiceTunnel;
 
 /**
  * Access controller to continue filter-chain if a valid {@link AbstractHttpServiceTunnel#TOKEN_AUTH_HTTP_HEADER Service
@@ -53,7 +55,7 @@
       return false;
     }
 
-    final String tokenString = request.getHeader(AbstractHttpServiceTunnel.TOKEN_AUTH_HTTP_HEADER);
+    final String tokenString = request.getHeader(HttpServiceTunnel.TOKEN_AUTH_HTTP_HEADER);
     if (tokenString == null) {
       return false;
     }
@@ -104,7 +106,7 @@
   public static class ServiceTunnelAccessTokenAuthConfig {
 
     private boolean m_enabled = DefaultAuthToken.isEnabled();
-    private IPrincipalProducer m_principalProducer = BEANS.get(ServiceTunnelPrincipalProducer.class);
+    private IPrincipalProducer m_principalProducer = BEANS.get(SimplePrincipalProducer.class);
 
     public boolean isEnabled() {
       return m_enabled;
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipal.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipal.java
deleted file mode 100644
index 04be4f3..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipal.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-/**
- * Principal representing a service tunnel remote call impersonation
- */
-public class ServiceTunnelPrincipal implements Principal, Serializable {
-  private static final long serialVersionUID = 1L;
-
-  private String m_name;
-
-  public ServiceTunnelPrincipal(String name) {
-    if (name == null) {
-      throw new IllegalArgumentException("name is null");
-    }
-    m_name = name.toLowerCase();
-  }
-
-  @Override
-  public String getName() {
-    return m_name;
-  }
-
-  @Override
-  public int hashCode() {
-    return getName().hashCode();
-  }
-
-  @Override
-  public boolean equals(Object other) {
-    if (other == null) {
-      return false;
-    }
-    if (other == this) {
-      return true;
-    }
-    if (other.getClass() != this.getClass()) {
-      return false;
-    }
-    return ((ServiceTunnelPrincipal) other).m_name.equals(this.m_name);
-  }
-
-  @Override
-  public String toString() {
-    return getName();
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipalProducer.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipalProducer.java
deleted file mode 100644
index cbbfbc1..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServiceTunnelPrincipalProducer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.authentication;
-
-/**
- * Producer for {@link ServiceTunnelPrincipal} objects.
- *
- * @since 5.2
- */
-public class ServiceTunnelPrincipalProducer implements IPrincipalProducer {
-
-  @Override
-  public ServiceTunnelPrincipal produce(final String username) {
-    return new ServiceTunnelPrincipal(username);
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServletFilterHelper.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServletFilterHelper.java
index 801aaba..2f6c14f 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServletFilterHelper.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServletFilterHelper.java
@@ -26,6 +26,7 @@
 import javax.servlet.http.HttpSession;
 
 import org.eclipse.scout.rt.platform.ApplicationScoped;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 import org.eclipse.scout.rt.platform.util.Base64Utility;
 import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.slf4j.Logger;
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/TrivialAccessController.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/TrivialAccessController.java
index 7aa8e85..c25d5af 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/TrivialAccessController.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/TrivialAccessController.java
@@ -21,6 +21,8 @@
 import javax.servlet.http.HttpSession;
 
 import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.SimplePrincipalProducer;
 import org.eclipse.scout.rt.platform.util.StringUtility;
 
 /**
@@ -151,7 +153,7 @@
   public static class TrivialAuthConfig {
 
     private boolean m_enabled = true;
-    private IPrincipalProducer m_principalProducer = BEANS.get(RemoteUserPrincipalProducer.class);
+    private IPrincipalProducer m_principalProducer = BEANS.get(SimplePrincipalProducer.class);
     private PathInfoFilter m_exclusionFilter;
     private boolean m_loginPageInstalled = false;
 
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/HttpServletControl.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/HttpServletControl.java
index d252eee..91f5a74 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/HttpServletControl.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/HttpServletControl.java
@@ -32,10 +32,26 @@
   public static final String HTTP_HEADER_X_XSS_PROTECTION = "X-XSS-Protection";
   public static final String XSS_MODE_BLOCK = "1; mode=block";
 
-  public static final String HTTP_HEADER_CSP = "Content-Security-Policy";//final version, mozilla und firefox
-  public static final String HTTP_HEADER_CSP_LEGACY_CHROME = "X-WebKit-CSP";//chrome
-  public static final String HTTP_HEADER_CSP_LEGACY_IE = "X-Content-Security-Policy";//ie
-  private static final String TYPICAL_CSP_RULE = "allow self; object-src 'self'; options inlinescript; report-uri csp.cgi";//see ContentSecurityPolicyReportHandler
+  public static final String HTTP_HEADER_CSP = "Content-Security-Policy";
+  public static final String HTTP_HEADER_CSP_LEGACY = "X-Content-Security-Policy";
+
+  /**
+   * <ul>
+   * <li><b>default-src 'self'</b><br>
+   * Only accept 'self' sources by default.</li>
+   * <li><b>script-src 'self' 'unsafe-inline' 'unsafe-eval'</b><br>
+   * Unsafe-inline is necessary for the bootstrapping process (index.html uses an inline script block).<br>
+   * Unsafe-eval is necessary for the number field.</li>
+   * <li><b>style-src 'self' 'unsafe-inline'</b><br>
+   * Without inline styling many widgets would not work as expected.</li>
+   * <li><b>frame-src *; child-src *</b><br>
+   * Everything is allowed because the iframes created by the browser field run in the sandbox mode and therefore handle
+   * the security policy by their own.</li>
+   * <li><b>report-uri csp.cgi</b><br>
+   * Report errors to csp.cgi, see ContentSecurityPolicyReportHandler</li>
+   * </ul>
+   */
+  public static final String DEFAULT_CSP_RULE = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-src *; child-src *; report-uri csp.cgi";
 
   /**
    * Every servlet should call this method to make sure the defaults are applied
@@ -55,15 +71,14 @@
     resp.setHeader(HTTP_HEADER_X_FRAME_OPTIONS, SAMEORIGIN);
     resp.setHeader(HTTP_HEADER_X_XSS_PROTECTION, XSS_MODE_BLOCK);
     resp.setHeader(HTTP_HEADER_CSP, cspRule());
-    resp.setHeader(HTTP_HEADER_CSP_LEGACY_IE, cspRule());
-    resp.setHeader(HTTP_HEADER_CSP_LEGACY_CHROME, cspRule());
+    resp.setHeader(HTTP_HEADER_CSP_LEGACY, cspRule());
   }
 
   /**
    * see also ContentSecurityPolicyReportHandler
    */
   protected String cspRule() {
-    return TYPICAL_CSP_RULE;
+    return DEFAULT_CSP_RULE;
   }
 
 }
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/UrlHints.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/UrlHints.java
index 6d279ce..190e44c 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/UrlHints.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/UrlHints.java
@@ -13,8 +13,11 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
+import org.eclipse.scout.rt.platform.IPlatform;
 import org.eclipse.scout.rt.platform.Platform;
-import org.eclipse.scout.rt.server.commons.servlet.filter.gzip.GzipServletFilter;
+import org.eclipse.scout.rt.platform.config.CONFIG;
+import org.eclipse.scout.rt.server.commons.ServerCommonsConfigProperties;
+import org.eclipse.scout.rt.server.commons.ServerCommonsConfigProperties.UrlHintsEnabledProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,19 +33,41 @@
  * <li><b><code>?inspector=(true|false)</code></b>: Enable/disable inspector attributes in DOM ("modelClass", "classId")
  * </ul>
  * All values are <code>true</code> by default, unless the application is run in development mode.
+ * <p>
+ * <b>Security considerations</b>
+ * <p>
+ * cache, compress, minify have the default value <code>not({@link IPlatform#inDevelopmentMode()})</code>. The above URL
+ * parameters can only be changed using URL parameters if the config property
+ * {@link ServerCommonsConfigProperties.UrlHintsEnabledProperty} is set to true.
  */
 public final class UrlHints {
   private static final Logger LOG = LoggerFactory.getLogger(UrlHints.class);
 
+  private static final boolean UPDATE_ENABLED = CONFIG.getPropertyValue(UrlHintsEnabledProperty.class);
+
   /**
    * Enables/disables cache, compress, minify. Also decides if scoutClass attribute is added to the DOM for form-fields.
    */
   private static final String URL_PARAM_DEBUG = "debug";
+  /**
+   * Enables/disables caching.
+   */
   private static final String URL_PARAM_CACHE_HINT = "cache";
+  /**
+   * Enables/disables gzip compression of js and css.
+   */
+  private static final String URL_PARAM_COMPRESS_HINT = "compress";
+  /**
+   * Enables/disables minify of js and css.
+   */
   private static final String URL_PARAM_MINIFY_HINT = "minify";
+  /**
+   * Enables/disables js inspector.
+   */
   private static final String URL_PARAM_INSPECTOR_HINT = "inspector";
 
   private static final String SESSION_ATTRIBUTE_CACHE_HINT = UrlHints.class.getName() + "#cache";
+  private static final String SESSION_ATTRIBUTE_COMPRESS_HINT = UrlHints.class.getName() + "#compress";
   private static final String SESSION_ATTRIBUTE_MINIFY_HINT = UrlHints.class.getName() + "#minify";
   private static final String SESSION_ATTRIBUTE_INSPECTOR_HINT = UrlHints.class.getName() + "#inspector";
 
@@ -51,18 +76,21 @@
   }
 
   public static void updateHints(HttpServletRequest req) {
+    if (!UPDATE_ENABLED) {
+      return;
+    }
     Boolean debug = getRequestParameterBoolean(req, URL_PARAM_DEBUG);
     if (debug != null) {
       updateHint(req, !debug.booleanValue(),
           SESSION_ATTRIBUTE_CACHE_HINT,
-          GzipServletFilter.SESSION_ATTRIBUTE_COMPRESS_HINT,
+          UrlHints.SESSION_ATTRIBUTE_COMPRESS_HINT,
           SESSION_ATTRIBUTE_MINIFY_HINT);
       updateHint(req, debug.booleanValue(), SESSION_ATTRIBUTE_INSPECTOR_HINT);
     }
 
     updateHint(req, getRequestParameterBoolean(req, URL_PARAM_INSPECTOR_HINT), SESSION_ATTRIBUTE_INSPECTOR_HINT);
     updateHint(req, getRequestParameterBoolean(req, URL_PARAM_CACHE_HINT), SESSION_ATTRIBUTE_CACHE_HINT);
-    updateHint(req, getRequestParameterBoolean(req, GzipServletFilter.URL_PARAM_COMPRESS_HINT), GzipServletFilter.SESSION_ATTRIBUTE_COMPRESS_HINT);
+    updateHint(req, getRequestParameterBoolean(req, UrlHints.URL_PARAM_COMPRESS_HINT), UrlHints.SESSION_ATTRIBUTE_COMPRESS_HINT);
     updateHint(req, getRequestParameterBoolean(req, URL_PARAM_MINIFY_HINT), SESSION_ATTRIBUTE_MINIFY_HINT);
   }
 
@@ -85,6 +113,19 @@
     return s != null ? ("true".equals(s)) : null;
   }
 
+  private static boolean calculateHint(HttpServletRequest req, String sessionAttr, boolean defaultValue) {
+    if (req != null) {
+      HttpSession session = req.getSession(false);
+      if (session != null) {
+        Boolean hint = (Boolean) session.getAttribute(sessionAttr);
+        if (hint != null) {
+          return hint.booleanValue();
+        }
+      }
+    }
+    return defaultValue;
+  }
+
   public static boolean isInspectorHint(HttpServletRequest req) {
     return calculateHint(req, SESSION_ATTRIBUTE_INSPECTOR_HINT, Platform.get().inDevelopmentMode());
   }
@@ -97,17 +138,8 @@
     return calculateHint(req, SESSION_ATTRIBUTE_MINIFY_HINT, !Platform.get().inDevelopmentMode());
   }
 
-  private static boolean calculateHint(HttpServletRequest req, String sessionAttr, boolean defaultValue) {
-    if (req != null) {
-      HttpSession session = req.getSession(false);
-      if (session != null) {
-        Boolean hint = (Boolean) session.getAttribute(sessionAttr);
-        if (hint != null) {
-          return hint.booleanValue();
-        }
-      }
-    }
-    return defaultValue;
+  public static boolean isCompressHint(HttpServletRequest req) {
+    return calculateHint(req, SESSION_ATTRIBUTE_COMPRESS_HINT, !Platform.get().inDevelopmentMode());
   }
 
 }
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AbstractChainableSecurityFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AbstractChainableSecurityFilter.java
deleted file mode 100644
index 274de1c..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AbstractChainableSecurityFilter.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.Principal;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import javax.security.auth.Subject;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.eclipse.scout.rt.server.commons.authentication.IAccessController;
-import org.eclipse.scout.rt.server.commons.authentication.SecureHttpServletRequestWrapper;
-import org.eclipse.scout.rt.server.commons.cache.IHttpSessionCacheService;
-
-/**
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself. See {@link IAccessController} and its subclasses.
- *             <p>
- *             Example client-side filter:
- *
- *             <pre>
- *             &#64;Override
- *             public void doFilter(final ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException {
- *               final HttpServletRequest req = (HttpServletRequest) in;
- *               final HttpServletResponse resp = (HttpServletResponse) out;
- *
- *               if (m_trivialAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               if (m_formBasedAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               if (m_developmentAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               BEANS.get(ServletFilterHelper.class).forwardToLoginForm(req, resp);
- *             }
- *             </pre>
- *
- *             Example server-side filter:
- *
- *             <pre>
- *             &#64;Override
- *             public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
- *               final HttpServletRequest req = (HttpServletRequest) request;
- *               final HttpServletResponse resp = (HttpServletResponse) response;
- *
- *               if (m_trivialAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               if (m_tunnelAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               if (m_developmentAccessController.handle(req, resp, chain)) {
- *                 return;
- *               }
- *
- *               resp.sendError(HttpServletResponse.SC_FORBIDDEN);
- *             }
- *             </pre>
- */
-@Deprecated
-@SuppressWarnings("deprecation")
-public abstract class AbstractChainableSecurityFilter implements Filter {
-  public static final String PROP_SUBJECT = Subject.class.getName();
-
-  public static final int STATUS_CONTINUE_CHAIN = 1;
-  public static final int STATUS_BREAK_CHAIN = 2;
-  public static final int STATUS_CONTINUE_WITH_PRINCIPAL = 3;
-
-  private boolean m_failover;
-  private String m_realm;
-
-  /**
-   * identifier for this filter.
-   *
-   * @rn aho, 4.6.09
-   */
-  protected String getFilterId() {
-    return this.getClass().getSimpleName();
-  }
-
-  @Override
-  public void init(FilterConfig config) throws ServletException {
-
-    // read config
-    m_failover = "true".equals(config.getInitParameter("failover"));
-    m_realm = StringUtility.nvl(config.getInitParameter("realm"), "Default");
-  }
-
-  @Override
-  public final void doFilter(ServletRequest in, ServletResponse out, final FilterChain chain) throws IOException, ServletException {
-    final HttpServletRequest req = (HttpServletRequest) in;
-    final HttpServletResponse res = (HttpServletResponse) out;
-    //touch the session so it is effectively used
-    req.getSession();
-    // check subject on session
-    Subject subject = findSubject(req, res);
-
-    if (subject == null || subject.getPrincipals().size() == 0) {
-      //try negotiate
-      PrincipalHolder pHolder = new PrincipalHolder();
-      switch (negotiate(req, res, pHolder)) {
-        case STATUS_CONTINUE_CHAIN:
-          if (m_failover) {
-            chain.doFilter(req, res);
-            return;
-          }
-          else {
-            res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-            return;
-          }
-        case STATUS_BREAK_CHAIN:
-          return;
-        case STATUS_CONTINUE_WITH_PRINCIPAL:
-          if (subject == null || subject.isReadOnly()) {
-            subject = new Subject();
-          }
-          subject.getPrincipals().add(pHolder.getPrincipal());
-          subject.setReadOnly();
-          cacheSubject(req, res, subject);
-          break;
-      }
-    }
-    //run in subject
-    if (Subject.getSubject(AccessController.getContext()) != null) {
-      doFilterInternal(req, res, chain);
-    }
-    else {
-      try {
-        Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
-          @Override
-          public Object run() throws Exception {
-            HttpServletRequest secureReq = req;
-            if (!(secureReq instanceof SecureHttpServletRequestWrapper)) {
-              Principal principal = Subject.getSubject(AccessController.getContext()).getPrincipals().iterator().next();
-              secureReq = new SecureHttpServletRequestWrapper(req, principal);
-            }
-            doFilterInternal(secureReq, res, chain);
-            return null;
-          }
-        });
-      }
-      catch (PrivilegedActionException e) {
-        Throwable t = e.getCause();
-        if (t instanceof IOException) {
-          throw (IOException) t;
-        }
-        else if (t instanceof ServletException) {
-          throw (ServletException) t;
-        }
-        else {
-          throw new ServletException(t);
-        }
-      }
-    }
-  }
-
-  /**
-   * Find already existing subject
-   */
-  protected Subject findSubject(final HttpServletRequest req, final HttpServletResponse res) {
-    synchronized (req.getSession()) {
-      Subject subject = getCachedSubject(req, res);
-      //check if we are already authenticated
-      if (subject == null) {
-        subject = Subject.getSubject(AccessController.getContext());
-      }
-      if (subject == null) {
-        Principal principal = req.getUserPrincipal();
-        if (principal == null || !StringUtility.hasText(principal.getName())) {
-          principal = null;
-          String name = req.getRemoteUser();
-          if (StringUtility.hasText(name)) {
-            principal = new SimplePrincipal(name);
-          }
-        }
-        if (principal != null) {
-          subject = createSubject(principal);
-          cacheSubject(req, res, subject);
-        }
-      }
-      return subject;
-    }
-  }
-
-  protected void cacheSubject(final HttpServletRequest req, final HttpServletResponse res, Subject subject) {
-    synchronized (req.getSession()) {
-      BEANS.get(IHttpSessionCacheService.class).put(PROP_SUBJECT, subject, req, res);
-    }
-  }
-
-  protected Subject getCachedSubject(final HttpServletRequest req, final HttpServletResponse res) {
-    synchronized (req.getSession()) {
-      Object s = BEANS.get(IHttpSessionCacheService.class).getAndTouch(PROP_SUBJECT, req, res);
-      if (s instanceof Subject) {
-        return (Subject) s;
-      }
-      return null;
-    }
-  }
-
-  protected Subject createSubject(Principal principal) {
-    Subject s = new Subject();
-    s.getPrincipals().add(principal);
-    s.setReadOnly();
-    return s;
-  }
-
-  /**
-   * set the 'WWW-Authenticate' value on the response to enforce the client to provide login data.
-   *
-   * @param req
-   * @param resp
-   * @return
-   */
-  protected abstract int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException;
-
-  protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
-    chain.doFilter(req, res);
-  }
-
-  public String getRealm() {
-    return m_realm;
-  }
-
-  public boolean isFailover() {
-    return m_failover;
-  }
-
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AnonymousSecurityFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AnonymousSecurityFilter.java
deleted file mode 100644
index c66c688..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/AnonymousSecurityFilter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.server.commons.authentication.ServletFilterHelper;
-
-/**
- * A security filter allowing anonymous access to the application.
- *
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; see depreciation note of {@link AbstractChainableSecurityFilter}
- */
-@SuppressWarnings("deprecation")
-@Deprecated
-public class AnonymousSecurityFilter extends AbstractChainableSecurityFilter {
-
-  public static final String ANONYMOUS_USER_NAME = "anonymous";
-
-  @Override
-  protected int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException {
-    holder.setPrincipal(new SimplePrincipal(ANONYMOUS_USER_NAME));
-    return STATUS_CONTINUE_WITH_PRINCIPAL;
-  }
-
-  @Override
-  protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
-    if (isLogoutRequest(req)) {
-      ServletFilterHelper helper = BEANS.get(ServletFilterHelper.class);
-      helper.doLogout(req);
-      helper.forwardToLogoutForm(req, res);
-      return;
-    }
-
-    if (isLoginRequest(req)) {
-      ServletFilterHelper helper = BEANS.get(ServletFilterHelper.class);
-      helper.doLogout(req);
-      helper.redirectTo(req, res, "");
-      return;
-    }
-
-    super.doFilterInternal(req, res, chain);
-  }
-
-  protected boolean isLogoutRequest(HttpServletRequest req) {
-    return "/logout".equals(req.getPathInfo());
-  }
-
-  protected boolean isLoginRequest(HttpServletRequest req) {
-    return "/login".equals(req.getPathInfo());
-  }
-
-  @Override
-  public void destroy() {
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilter.java
deleted file mode 100644
index d2f4c75..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/BasicSecurityFilter.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.platform.util.Base64Utility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.eclipse.scout.rt.server.commons.cache.IHttpSessionCacheService;
-
-/**
- * <h4>BasicSecurityFilter</h4> A simple security filter using username,password tuples defined in the config.properties
- * file. The following properties are supported:
- * <ul>
- * <li><code>realm=abcde</code> <b>default: 'Default'</b></li>
- * <li><code>failover=true/false</code> <b>default false</b></li>
- * <li><code>users=username1\=password1,username2\=password2</code> <b>required</b></li>
- * </ul>
- * <p>
- *
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; see depreciation note of {@link AbstractChainableSecurityFilter}
- */
-@SuppressWarnings("deprecation")
-@Deprecated
-public class BasicSecurityFilter extends AbstractChainableSecurityFilter {
-  public static final String PROP_BASIC_ATTEMPT = "BasicSecurityFilter.basicAttempt";
-
-  private Map<String, String> m_userDatabase;
-
-  @Override
-  public void init(FilterConfig config) throws ServletException {
-    super.init(config);
-
-    // read config
-    String usersParam = config.getInitParameter("users");
-    if (!StringUtility.hasText(usersParam)) {
-      throw new ServletException("missing init-param with name 'users'.");
-    }
-
-    m_userDatabase = new HashMap<>();
-    for (String pair : usersParam.split(",")) {
-      String[] a = pair.trim().split("=", 2);
-      m_userDatabase.put(a[0].toLowerCase(), a[1]);
-    }
-  }
-
-  @Override
-  public void destroy() {
-    m_userDatabase.clear();
-  }
-
-  @Override
-  protected int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException {
-    String h = req.getHeader("Authorization");
-    if (h != null && h.matches("Basic .*")) {
-      String[] a = new String(Base64Utility.decode(h.substring(6)), "ISO-8859-1").split(":", 2);
-      String user = a[0].toLowerCase();
-      String pass = a[1];
-      if (user != null && pass != null) {
-        if (pass.equals(m_userDatabase.get(user))) {// check can also be based on
-          // filter init params
-          // success
-          holder.setPrincipal(new SimplePrincipal(user));
-          return STATUS_CONTINUE_WITH_PRINCIPAL;
-        }
-      }
-    }
-    int attempts = getBasicAttempt(req, resp);
-    if (attempts > 2) {
-      return STATUS_CONTINUE_CHAIN;
-    }
-    else {
-      setBasicAttept(req, resp, attempts + 1);
-      resp.setHeader("WWW-Authenticate", "Basic realm=\"" + getRealm() + "\"");
-      return STATUS_CONTINUE_CHAIN;
-    }
-  }
-
-  private int getBasicAttempt(HttpServletRequest req, HttpServletResponse res) {
-    int basicAtttempt = 0;
-    Object attribute = BEANS.get(IHttpSessionCacheService.class).getAndTouch(PROP_BASIC_ATTEMPT, req, res);
-    if (attribute instanceof Integer) {
-      basicAtttempt = ((Integer) attribute).intValue();
-    }
-    return basicAtttempt;
-  }
-
-  private void setBasicAttept(HttpServletRequest req, HttpServletResponse res, int attempts) {
-    BEANS.get(IHttpSessionCacheService.class).put(PROP_BASIC_ATTEMPT, attempts, req, res);
-  }
-
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/DataSourceSecurityFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/DataSourceSecurityFilter.java
deleted file mode 100644
index 0156eef..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/DataSourceSecurityFilter.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Hashtable;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.sql.DataSource;
-
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.security.SecurityUtility;
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.platform.util.Base64Utility;
-import org.eclipse.scout.rt.server.commons.cache.IHttpSessionCacheService;
-import org.eclipse.scout.rt.server.commons.servlet.ServletExceptionTranslator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <h4>DataSourceSecurityFilter</h4> The following properties can be set in the <code>web.xml</code> file:
- * <ul>
- * <li><code>realm=abcde</code> <b>default "Default"</b></li>
- * <li><code>failover=true/false</code> <b>default false</b></li>
- * <li><code>jdbcDriverName=[e.g. oracle.jdbc.OracleDriver]</code> <b>required for JDBC</b></li>
- * <li><code>jdbcMappingName=[e.g. jdbc:oracle:thin:@dbUrl:1521:DBNAME]</code> <b>required for JDBC</b></li>
- * <li><code>jdbcUsername=USER</code> <b>required for JDBC, optional JNDI</b></li>
- * <li><code>jdbcPassword=PASS</code> <b>required for JDBC, optional JNDI</b></li>
- * <li><code>selectUserPass=<br>
- * [e.g. SELECT LOWER(USERNAME), SALT FROM TAB_USER WHERE ACCOUNT_LOCKED=0 AND NVL(EVT_ACCOUNT_EXPIRY,SYSDATE)>=SYSDATE AND LOWER(USERNAME)=? AND PASSWORD=?]</code>
- * <b>required for JDBC</b></li>
- * <li><code>useJndiConnection=false</code> <b>default false</b></li>
- * <li><code>jndiName=[e.g. jdbc/jndiDbname]</code> <b>required for JNDI</b></li>
- * <li><code>jndiInitialContextFactory=</code></li>
- * <li><code>jndiProviderUrl=</code></li>
- * <li><code>jndiUrlPkgPrefixes=</code></li>
- * </ul>
- * <p>
- *
- * @author Michael Rudolf
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; see depreciation note of {@link AbstractChainableSecurityFilter}
- */
-@SuppressWarnings("deprecation")
-@Deprecated
-public class DataSourceSecurityFilter extends AbstractChainableSecurityFilter {
-
-  private static final Logger LOG = LoggerFactory.getLogger(DataSourceSecurityFilter.class);
-  public static final String PROP_BASIC_ATTEMPT = "DataSourceSecurityFilter.basicAttempt";
-
-  /**
-   * Default random salt that will be used to hash the passwords. Should be replaced by projects with an implementation
-   * that uses a separate salt for each password.
-   *
-   * @see #isValidUser(String, String, Connection)
-   */
-  private static final byte[] DEFAULT_SALT = Base64Utility.decode("X89TeeW9tSB0KQkYex3/LQ==");
-
-  // init params
-  private String m_jdbcUserName;
-  private String m_jdbcPassword;
-  private String m_jdbcDriverName;
-  private String m_jdbcMappingName;
-  private String m_selectStatement;
-
-  private boolean m_useJndiConnection;
-  private String m_jndiName;
-  private String m_jndiInitialContextFactory;
-  private String m_jndiProviderUrl;
-  private String m_jndiUrlPkgPrefixes;
-
-  @Override
-  public void init(FilterConfig config) throws ServletException {
-    super.init(config);
-
-    // read config
-    m_useJndiConnection = "true".equals(config.getInitParameter("useJndiConnection"));
-    m_jdbcDriverName = config.getInitParameter("jdbcDriverName");
-    m_jdbcMappingName = config.getInitParameter("jdbcMappingName");
-    m_jdbcUserName = config.getInitParameter("jdbcUsername");
-    m_jdbcPassword = config.getInitParameter("jdbcPassword");
-    m_selectStatement = config.getInitParameter("selectUserPass");
-    m_jndiName = config.getInitParameter("jndiName");
-    m_jndiInitialContextFactory = config.getInitParameter("jndiInitialContextFactory");
-    m_jndiProviderUrl = config.getInitParameter("jndiProviderUrl");
-    m_jndiUrlPkgPrefixes = config.getInitParameter("jndiUrlPkgPrefixes");
-  }
-
-  @Override
-  public void destroy() {
-  }
-
-  @Override
-  protected int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException {
-    String h = req.getHeader("Authorization");
-    if (h != null && h.matches("Basic .*")) {
-      String[] a = new String(Base64Utility.decode(h.substring(6)), "ISO-8859-1").split(":", 2);
-      String user = a[0].toLowerCase();
-      String pass = a[1];
-      if (user != null && pass != null) {
-        if (isValidUser(user, pass)) {
-          holder.setPrincipal(new SimplePrincipal(user));
-          return STATUS_CONTINUE_WITH_PRINCIPAL;
-        }
-      }
-    }
-    int attempts = getBasicAttempt(req, resp);
-    if (attempts > 2) {
-      return STATUS_CONTINUE_CHAIN;
-    }
-    else {
-      setBasicAttept(req, resp, attempts + 1);
-      resp.setHeader("WWW-Authenticate", "Basic realm=\"" + getRealm() + "\"");
-      return STATUS_CONTINUE_CHAIN;
-    }
-  }
-
-  private int getBasicAttempt(HttpServletRequest req, HttpServletResponse res) {
-    int basicAtttempt = 0;
-    Object attribute = BEANS.get(IHttpSessionCacheService.class).getAndTouch(PROP_BASIC_ATTEMPT, req, res);
-    if (attribute instanceof Integer) {
-      basicAtttempt = ((Integer) attribute).intValue();
-    }
-    return basicAtttempt;
-  }
-
-  private void setBasicAttept(HttpServletRequest req, HttpServletResponse res, int attempts) {
-    BEANS.get(IHttpSessionCacheService.class).put(PROP_BASIC_ATTEMPT, attempts, req, res);
-  }
-
-  protected Connection createConnection() throws Exception {
-    if (m_useJndiConnection) {
-      return createJndiConnection();
-    }
-    else {
-      return createJdbcDirectConnection();
-    }
-  }
-
-  protected boolean isValidUser(String username, String password) throws ServletException {
-    try (Connection connection = createConnection()) {
-      return isValidUser(username, password, connection);
-    }
-    catch (Exception e) {
-      LOG.error("Cannot SELECT user/pass.", e);
-      throw BEANS.get(ServletExceptionTranslator.class).translate(e);
-    }
-  }
-
-  /**
-   * This method can be overwritten by projects to use a custom salt per user instead of the pre-defined one of this
-   * filter.
-   *
-   * @param username
-   *          The username
-   * @param password
-   *          The clear text password
-   * @param connection
-   *          The connection to use to verify the username and password
-   * @return <code>true</code> if it is valid. <code>false</code> otherwise.
-   * @throws Exception
-   */
-  protected boolean isValidUser(String username, String password, Connection connection) throws Exception {
-    password = encryptPass(password);
-
-    try (PreparedStatement stmt = connection.prepareStatement(m_selectStatement)) {
-      stmt.setString(1, username);
-      stmt.setString(2, password);
-      stmt.execute();
-      ResultSet resultSet = stmt.getResultSet();
-      return (resultSet.next() && resultSet.getString(1).equals(username));
-    }
-  }
-
-  protected String encryptPass(String pass) throws ServletException {
-    if (pass == null) {
-      return null;
-    }
-
-    try {
-      return Base64Utility.encode(SecurityUtility.hash(pass.getBytes(UTF_8), DEFAULT_SALT));
-    }
-    catch (RuntimeException e) {
-      throw BEANS.get(ServletExceptionTranslator.class).translate(e);
-    }
-  }
-
-  protected Connection createJdbcDirectConnection() throws ClassNotFoundException, SQLException {
-    Class.forName(m_jdbcDriverName);
-    return DriverManager.getConnection(m_jdbcMappingName, m_jdbcUserName, m_jdbcPassword);
-  }
-
-  protected Connection createJndiConnection() throws NamingException, SQLException {
-    InitialContext initialContext = null;
-
-    String jndiName = m_jndiName;
-    String jndiInitialContextFactory = m_jndiInitialContextFactory;
-    String jndiProviderUrl = m_jndiProviderUrl;
-    String jndiUrlPkgPrefixes = m_jndiUrlPkgPrefixes;
-    LOG.info("Opening rmi connection. jndiName: '{}', user: '{}', initialContextFactory: '{}', providerUrl: '{}'", jndiName, m_jdbcUserName, jndiInitialContextFactory, jndiProviderUrl);
-    Hashtable<String, String> ht = new Hashtable<String, String>();
-    if (jndiInitialContextFactory != null) {
-      ht.put(Context.INITIAL_CONTEXT_FACTORY, jndiInitialContextFactory);
-    }
-    if (jndiProviderUrl != null) {
-      ht.put(Context.PROVIDER_URL, jndiProviderUrl);
-    }
-    if (jndiUrlPkgPrefixes != null) {
-      ht.put(Context.URL_PKG_PREFIXES, jndiUrlPkgPrefixes);
-    }
-    DataSource dataSource = null;
-    if (ht.size() > 0) {
-      initialContext = new InitialContext(ht);
-    }
-    else {
-      initialContext = new InitialContext();
-    }
-    dataSource = (DataSource) initialContext.lookup(jndiName);
-    // Grab a connection
-    Connection conn;
-    if (m_jdbcUserName != null && m_jdbcPassword != null) {
-      conn = dataSource.getConnection(m_jdbcUserName, m_jdbcPassword);
-    }
-    else {
-      conn = dataSource.getConnection();
-    }
-    conn.setAutoCommit(false);
-    return conn;
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/HttpAuthJaasFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/HttpAuthJaasFilter.java
deleted file mode 100644
index 76f4906..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/HttpAuthJaasFilter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.Principal;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import javax.security.auth.Subject;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.platform.util.CollectionUtility;
-import org.eclipse.scout.rt.platform.util.StringUtility;
-import org.eclipse.scout.rt.server.commons.authentication.SecureHttpServletRequestWrapper;
-import org.eclipse.scout.rt.server.commons.authentication.TrivialAccessController;
-
-/**
- * Transformation filter used to create a subject based on {@link HttpServletRequest#getRemoteUser()} or
- * {@link HttpServletRequest#getUserPrincipal()}
- * <p>
- * If there is already a subject set as {@link Subject#getSubject(java.security.AccessControlContext)} then the filter
- * is transparent.
- * <p>
- * Normally this filters the alias /process
- * <p>
- * This filter is registered in the scout server plugin.xml as /process by default with order 1'000'000 and has the
- * active flag set to true
- *
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; use {@link TrivialAccessController} instead.
- */
-@Deprecated
-public class HttpAuthJaasFilter implements Filter {
-
-  @Override
-  public void init(FilterConfig config) throws ServletException {
-  }
-
-  @Override
-  public void destroy() {
-  }
-
-  @Override
-  public void doFilter(ServletRequest in, ServletResponse out, final FilterChain chain) throws IOException, ServletException {
-    HttpServletRequest req = (HttpServletRequest) in;
-    HttpServletResponse res = (HttpServletResponse) out;
-
-    String username = req.getRemoteUser();
-    if (isSubjectSetWithCorrectPrincipal(username)) {
-      chain.doFilter(in, out);
-      return;
-    }
-
-    // check if subject that has one principal at minimum is available
-    // create subject if necessary
-    Subject subject = Subject.getSubject(AccessController.getContext());
-    if (subject == null || subject.isReadOnly()) {
-      subject = new Subject();
-    }
-
-    // create principal if necessary
-    Principal principal = req.getUserPrincipal();
-    if (principal != null && !StringUtility.hasText(principal.getName())) {
-      principal = null;
-      String name = req.getRemoteUser();
-      if (StringUtility.hasText(name)) {
-        principal = new SimplePrincipal(name);
-      }
-    }
-    if (principal == null) {
-      // no principal provided, abort chain
-      res.sendError(HttpServletResponse.SC_FORBIDDEN);
-      return;
-    }
-
-    subject.getPrincipals().add(principal);
-    subject.setReadOnly();
-
-    continueChainWithPrincipal(subject, req, res, chain);
-  }
-
-  /**
-   * @return true, if a {@link Subject} is already set with a principal corresponding to the given username.
-   */
-  private boolean isSubjectSetWithCorrectPrincipal(String username) {
-    Subject subject = Subject.getSubject(AccessController.getContext());
-    if (subject == null) {
-      return false;
-    }
-    if (subject.getPrincipals().size() == 0) {
-      return false;
-    }
-    String name = CollectionUtility.firstElement(subject.getPrincipals()).getName();
-    return StringUtility.hasText(name) && name.equalsIgnoreCase(username);
-  }
-
-  private void continueChainWithPrincipal(Subject subject, final HttpServletRequest req, final HttpServletResponse res, final FilterChain chain) throws IOException, ServletException {
-    try {
-      Subject.doAs(
-          subject,
-          new PrivilegedExceptionAction<Object>() {
-            @Override
-            public Object run() throws Exception {
-              Principal principal = Subject.getSubject(AccessController.getContext()).getPrincipals().iterator().next();
-              HttpServletRequest secureReq = new SecureHttpServletRequestWrapper(req, principal);
-              chain.doFilter(secureReq, res);
-              return null;
-            }
-          });
-    }
-    catch (PrivilegedActionException e) {
-      Throwable t = e.getCause();
-      if (t instanceof IOException) {
-        throw (IOException) t;
-      }
-      else if (t instanceof ServletException) {
-        throw (ServletException) t;
-      }
-      else {
-        throw new ServletException(t);
-      }
-    }
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/LDAPSecurityFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/LDAPSecurityFilter.java
deleted file mode 100644
index a0c9e87..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/LDAPSecurityFilter.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.security.SimplePrincipal;
-import org.eclipse.scout.rt.platform.util.Base64Utility;
-import org.eclipse.scout.rt.server.commons.cache.IHttpSessionCacheService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <h4>LDAPSecurityFilter</h4> The following properties can be set in the <code>config.properties</code> file:
- * <ul>
- * <li><code>&lt;fully qualified name of class&gt;#active=true/false</code> <b>might be set in the extension point</b>
- * </li>
- * <li><code>&lt;fully qualified name of class&gt;#realm=abcde</code> <b>required</b></li>
- * <li><code>&lt;fully qualified name of class&gt;#failover=true/false</code> <b>default false</b></li>
- * <li><code>&lt;fully qualified name of class&gt;#ldapServer=[e.g. ldap://100.100.29.4]</code> <b>required</b></li>
- * <li><code>&lt;fully qualified name of class&gt;#ldapBaseDN=[e.g. o=bsiag]</code> <b>required</b></li>
- * <li><code>&lt;fully qualified name of class&gt;#lDAPgroupDN=[e.g. ou=bsi_baden,ou=bsi_bern]</code> <b>required</b>
- * </li>
- * <li><code>&lt;fully qualified name of class&gt;#lDAPgroupAttributeId=[e.g. cn]</code> <b>required</b></li>
- * </ul>
- * <p>
- *
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; see depreciation note of {@link AbstractChainableSecurityFilter}
- */
-@SuppressWarnings("deprecation")
-@Deprecated
-public class LDAPSecurityFilter extends AbstractChainableSecurityFilter {
-  private static final Logger LOG = LoggerFactory.getLogger(LDAPSecurityFilter.class);
-  public static final String PROP_BASIC_ATTEMPT = "LDAPSecurityFilter.basicAttempt";
-
-  private String m_serverUrl;
-  private String m_baseDn;
-  private String m_groupDn;
-  private String m_groupAttr;
-
-  @Override
-  public void destroy() {
-  }
-
-  @Override
-  public void init(FilterConfig config) throws ServletException {
-    super.init(config);
-    m_serverUrl = config.getInitParameter("ldapServer");
-    m_baseDn = config.getInitParameter("ldapBaseDN");
-    m_groupDn = config.getInitParameter("ldapGroupDN");
-    m_groupAttr = config.getInitParameter("ldapGroupAttributeId");
-  }
-
-  @Override
-  protected int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException {
-    String h = req.getHeader("Authorization");
-    if (h != null && h.matches("Basic .*")) {
-      String[] a = new String(Base64Utility.decode(h.substring(6)), "ISO-8859-1").split(":", 2);
-      String user = a[0].toLowerCase();
-      String pass = a[1];
-      if (user != null && pass != null) {
-        if (ldapLogin(m_serverUrl, m_baseDn, m_groupDn, m_groupAttr, user, pass, false/* show exceptions */)) {
-          // success
-          holder.setPrincipal(new SimplePrincipal(user));
-          return STATUS_CONTINUE_WITH_PRINCIPAL;
-        }
-      }
-    }
-    int attempts = getBasicAttempt(req, resp);
-    if (attempts > 2) {
-      return STATUS_CONTINUE_CHAIN;
-    }
-    else {
-      setBasicAttept(req, resp, attempts + 1);
-      resp.setHeader("WWW-Authenticate", "Basic realm=\"" + getRealm() + "\"");
-      return STATUS_CONTINUE_CHAIN;
-    }
-  }
-
-  private int getBasicAttempt(HttpServletRequest req, HttpServletResponse res) {
-    int basicAtttempt = 0;
-    Object attribute = BEANS.get(IHttpSessionCacheService.class).getAndTouch(PROP_BASIC_ATTEMPT, req, res);
-    if (attribute instanceof Integer) {
-      basicAtttempt = ((Integer) attribute).intValue();
-    }
-    return basicAtttempt;
-  }
-
-  private void setBasicAttept(HttpServletRequest req, HttpServletResponse res, int attempts) {
-    BEANS.get(IHttpSessionCacheService.class).put(PROP_BASIC_ATTEMPT, attempts, req, res);
-  }
-
-  /**
-   * @param username
-   *          e.g. FooBar
-   * @param server
-   *          e.g. ldap://123.45.6.78
-   * @param baseDN
-   *          e.g. o=firmaxyz
-   * @param groupDN
-   *          e.g. cn=AGENTS,ou=fb,ou=lm,ou=hlg,ou=zentrale <br>
-   *          The user DN is defined within this group
-   * @param attributeId
-   *          e.g. equivalentToMe <br>
-   *          Name of the user DN attribute
-   * @return something like "cn=FooBar,ou=FB,ou=LM,ou=HLG,ou=ZENTRALE,o=FIRMAXYZ"
-   * @throws ServletException
-   */
-  @SuppressWarnings("unchecked")
-  protected String getUserDN(String username, String server, String baseDN, String groupDN, String attributeId) throws ServletException {
-
-    String userDN = "";
-    Hashtable env = new Hashtable();
-    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
-    env.put(Context.PROVIDER_URL, server + "/" + baseDN);
-    env.put(Context.SECURITY_PRINCIPAL, "" + "=" + "" + "," + "" + "," + baseDN);
-    env.put(Context.SECURITY_CREDENTIALS, "");
-    env.put(Context.LANGUAGE, "de");
-
-    try {
-      DirContext ldap = new InitialDirContext(env);
-      Attributes attrs = ldap.getAttributes(groupDN, new String[]{attributeId});
-      NamingEnumeration<? extends Attribute> equivalentToMe = attrs.getAll();
-
-      Attribute attr = null;
-      NamingEnumeration<?> allValues = null;
-      String dn = null;
-      String un = "";
-      String[] parts;
-      while (equivalentToMe.hasMore()) {
-        attr = equivalentToMe.next();
-
-        allValues = attr.getAll();
-
-        while (allValues.hasMore()) {
-          // dn is something like
-          // "cn=FooBar,ou=FB,ou=LM,ou=HLG,ou=ZENTRALE,o=FIRMAXYZ"
-          dn = (String) allValues.next();
-          // extract userName (e.g. "BulinskyMir")
-          if (dn.length() > 4) {
-            un = dn.substring(3);
-            parts = un.split(",");
-            if (parts.length > 1) {
-              un = parts[0].toLowerCase();
-              if (username.equals(un)) {
-                userDN = dn;
-                break;
-              }
-            }
-          }
-        }
-      }
-
-    }
-    catch (NamingException ne) {
-      LOG.error("Exception in getting user DN from LDAP: ", ne);
-      throw new SecurityException(ne.getMessage(), ne);
-    }
-    return userDN;
-  }
-
-  @SuppressWarnings("unchecked")
-  private boolean ldapLogin(
-      String server,
-      String baseDN,
-      String groupDN,
-      String groupAttr,
-      String username,
-      String password,
-      boolean showexceptions) throws ServletException {
-
-    String userDN = getUserDN(username, server, baseDN, groupDN, groupAttr);
-    if (userDN.equals("")) {
-      return false;
-    }
-    Hashtable env = new Hashtable();
-    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
-    env.put(Context.PROVIDER_URL, server + "/" + baseDN);
-    env.put(Context.SECURITY_PRINCIPAL, userDN);
-    env.put(Context.SECURITY_CREDENTIALS, password);
-    env.put(Context.LANGUAGE, "de");
-
-    try {
-      new InitialDirContext(env);
-      return true;
-    }
-    catch (NamingException ne) {
-      if (showexceptions) {
-        ne.printStackTrace();
-      }
-      return false;
-    }
-
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/PrincipalHolder.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/PrincipalHolder.java
deleted file mode 100644
index 6e678a6..0000000
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/authentication/PrincipalHolder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-package org.eclipse.scout.rt.server.commons.servlet.filter.authentication;
-
-import java.security.Principal;
-
-import org.eclipse.scout.rt.platform.holders.Holder;
-
-/**
- * @deprecated will be removed in release 6.0; is to be replaced with a project specific ServletFilter with the
- *             authenticators chained yourself; see depreciation note of {@link AbstractChainableSecurityFilter}
- */
-@Deprecated
-public class PrincipalHolder extends Holder<Principal> {
-  private static final long serialVersionUID = 1L;
-
-  public PrincipalHolder() {
-    super(Principal.class);
-  }
-
-  public void setPrincipal(Principal principal) {
-    setValue(principal);
-  }
-
-  public Principal getPrincipal() {
-    return getValue();
-  }
-}
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletFilter.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletFilter.java
index edd9e04..72b6fa8 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletFilter.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletFilter.java
@@ -21,10 +21,9 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
-import org.eclipse.scout.rt.platform.Platform;
 import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.eclipse.scout.rt.server.commons.servlet.UrlHints;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,8 +45,6 @@
   public static final String ACCEPT_ENCODING = "Accept-Encoding";
   public static final String CONTENT_ENCODING = "Content-Encoding";
   public static final String GZIP = "gzip";
-  public static final String URL_PARAM_COMPRESS_HINT = "compress";
-  public static final String SESSION_ATTRIBUTE_COMPRESS_HINT = GzipServletFilter.class.getName() + "#compress";
 
   private int m_getMinSize;
   private int m_postMinSize;
@@ -111,7 +108,7 @@
   }
 
   protected boolean supportsGzipEncoding(HttpServletRequest req) {
-    if (!isCompressHint(req)) {
+    if (!UrlHints.isCompressHint(req)) {
       return false;
     }
     String pathInfo = req.getPathInfo();
@@ -137,19 +134,6 @@
     return -1;
   }
 
-  protected boolean isCompressHint(HttpServletRequest req) {
-    boolean defaultValue = !Platform.get().inDevelopmentMode();
-    HttpSession session = req.getSession(false);
-    if (session == null) {
-      return defaultValue;
-    }
-    Boolean val = (Boolean) session.getAttribute(SESSION_ATTRIBUTE_COMPRESS_HINT);
-    if (val == null) {
-      return defaultValue;
-    }
-    return val.booleanValue();
-  }
-
   @Override
   public void destroy() {
   }
diff --git a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletRequestWrapper.java b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletRequestWrapper.java
index a62bf0a..ab2424e 100644
--- a/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletRequestWrapper.java
+++ b/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/filter/gzip/GzipServletRequestWrapper.java
@@ -39,7 +39,7 @@
 
   protected BufferedServletInputStream ensureBufferedStream() throws IOException {
     if (m_buf == null) {
-      byte[] gzipped = IOUtility.getContent(super.getInputStream(), super.getContentLength());
+      byte[] gzipped = IOUtility.readBytes(super.getInputStream(), super.getContentLength());
       m_compressedLength = gzipped.length;
       m_buf = new BufferedServletInputStream(IOUtility.uncompressGzip(gzipped));
       m_uncompressedLength = m_buf.getLength();
diff --git a/org.eclipse.scout.rt.server.jaxws.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.jaxws.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.jaxws.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.jaxws.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.jaxws.test/pom.xml b/org.eclipse.scout.rt.server.jaxws.test/pom.xml
index 303ae56..b4e2596 100644
--- a/org.eclipse.scout.rt.server.jaxws.test/pom.xml
+++ b/org.eclipse.scout.rt.server.jaxws.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.jaxws/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.jaxws/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.jaxws/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.jaxws/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.jaxws/pom.xml b/org.eclipse.scout.rt.server.jaxws/pom.xml
index a1be4c2..c695334 100644
--- a/org.eclipse.scout.rt.server.jaxws/pom.xml
+++ b/org.eclipse.scout.rt.server.jaxws/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/consumer/auth/handler/WsseUsernameTokenAuthenticationHandler.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/consumer/auth/handler/WsseUsernameTokenAuthenticationHandler.java
index 8d432be..289b976 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/consumer/auth/handler/WsseUsernameTokenAuthenticationHandler.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/consumer/auth/handler/WsseUsernameTokenAuthenticationHandler.java
@@ -43,7 +43,7 @@
   private static final String WS_SEC = "Security";
   private static final String USERNAME_TOKEN = "UsernameToken";
   private static final String USERNAME = "Username";
-  private static final String PASSWORD = "Password";
+  private static final String PASSWORD = "Password"; //NOSONAR
   private static final String NAME_SPACE_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
 
   @Override
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/Authentication.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/Authentication.java
index 5e9a70a..17bee33 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/Authentication.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/Authentication.java
@@ -19,8 +19,8 @@
 
 import org.eclipse.scout.rt.platform.annotations.Internal;
 import org.eclipse.scout.rt.platform.context.RunContext;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.SimplePrincipalProducer;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.SimplePrincipalProducer;
 import org.eclipse.scout.rt.server.context.ServerRunContextProducer;
 import org.eclipse.scout.rt.server.jaxws.provider.auth.handler.AuthenticationHandler;
 import org.eclipse.scout.rt.server.jaxws.provider.auth.method.IAuthenticationMethod;
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/WebServiceEntryPoint.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/WebServiceEntryPoint.java
index 5cf7b0a..4d9f964 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/WebServiceEntryPoint.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/annotation/WebServiceEntryPoint.java
@@ -21,7 +21,7 @@
 import org.eclipse.scout.rt.platform.ApplicationScoped;
 import org.eclipse.scout.rt.platform.context.RunContext;
 import org.eclipse.scout.rt.platform.context.RunWithRunContext;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
 import org.eclipse.scout.rt.server.jaxws.provider.auth.handler.AuthenticationHandler;
 import org.eclipse.scout.rt.server.jaxws.provider.auth.method.IAuthenticationMethod;
 
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/handler/AuthenticationHandler.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/handler/AuthenticationHandler.java
index 08dbb73..9e49882 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/handler/AuthenticationHandler.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/handler/AuthenticationHandler.java
@@ -31,9 +31,9 @@
 import org.eclipse.scout.rt.platform.exception.DefaultExceptionTranslator;
 import org.eclipse.scout.rt.platform.exception.ExceptionHandler;
 import org.eclipse.scout.rt.platform.exception.PlatformExceptionTranslator;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 import org.eclipse.scout.rt.platform.util.Assertions;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.IPrincipalProducer;
 import org.eclipse.scout.rt.server.commons.authentication.ServletFilterHelper;
 import org.eclipse.scout.rt.server.jaxws.JaxWsConfigProperties.JaxWsAuthenticatorSubjectProperty;
 import org.eclipse.scout.rt.server.jaxws.MessageContexts;
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/BasicAuthenticationMethod.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/BasicAuthenticationMethod.java
index a4ca170..cd78810 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/BasicAuthenticationMethod.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/BasicAuthenticationMethod.java
@@ -21,9 +21,9 @@
 
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.config.CONFIG;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 import org.eclipse.scout.rt.platform.util.Base64Utility;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.IPrincipalProducer;
 import org.eclipse.scout.rt.server.jaxws.JaxWsConfigProperties.JaxWsBasicAuthRealmProperty;
 import org.eclipse.scout.rt.server.jaxws.implementor.JaxWsImplementorSpecifics;
 
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/ContainerBasedAuthenticationMethod.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/ContainerBasedAuthenticationMethod.java
index 3247d8c..b407241 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/ContainerBasedAuthenticationMethod.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/ContainerBasedAuthenticationMethod.java
@@ -22,8 +22,8 @@
 import javax.xml.ws.handler.soap.SOAPMessageContext;
 
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 import org.eclipse.scout.rt.server.commons.authentication.ServletFilterHelper;
 import org.eclipse.scout.rt.server.jaxws.implementor.JaxWsImplementorSpecifics;
 import org.slf4j.Logger;
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/IAuthenticationMethod.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/IAuthenticationMethod.java
index 689bc3a..8d17e6c 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/IAuthenticationMethod.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/IAuthenticationMethod.java
@@ -17,8 +17,8 @@
 import javax.xml.ws.handler.soap.SOAPMessageContext;
 
 import org.eclipse.scout.rt.platform.ApplicationScoped;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 
 /**
  * Functionality to challenge the webservice client to provide credentials, like <i>Basic Access Authentication</i> or
diff --git a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/WsseUsernameTokenMethod.java b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/WsseUsernameTokenMethod.java
index 8dd902a..1971fa2 100644
--- a/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/WsseUsernameTokenMethod.java
+++ b/org.eclipse.scout.rt.server.jaxws/src/main/java/org/eclipse/scout/rt/server/jaxws/provider/auth/method/WsseUsernameTokenMethod.java
@@ -27,8 +27,8 @@
 
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.annotations.Internal;
-import org.eclipse.scout.rt.server.commons.authentication.ICredentialVerifier;
-import org.eclipse.scout.rt.server.commons.authentication.IPrincipalProducer;
+import org.eclipse.scout.rt.platform.security.ICredentialVerifier;
+import org.eclipse.scout.rt.platform.security.IPrincipalProducer;
 import org.eclipse.scout.rt.server.jaxws.implementor.JaxWsImplementorSpecifics;
 
 /**
diff --git a/org.eclipse.scout.rt.server.jdbc.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.jdbc.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.jdbc.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.jdbc.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.jdbc.test/pom.xml b/org.eclipse.scout.rt.server.jdbc.test/pom.xml
index d2b7f56..ef05da3 100644
--- a/org.eclipse.scout.rt.server.jdbc.test/pom.xml
+++ b/org.eclipse.scout.rt.server.jdbc.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlFormatterTest.java b/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlFormatterTest.java
index 0e7fa8e..7d40c31 100644
--- a/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlFormatterTest.java
+++ b/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlFormatterTest.java
@@ -13,6 +13,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import java.io.InputStream;
+
 import org.eclipse.scout.rt.platform.util.IOUtility;
 import org.junit.Test;
 
@@ -61,7 +63,10 @@
   }
 
   protected void check(String resourceName) throws Exception {
-    String s = IOUtility.getContentUtf8(SqlFormatterTest.class.getResourceAsStream(resourceName));
+    String s;
+    try (InputStream in = SqlFormatterTest.class.getResourceAsStream(resourceName)) {
+      s = IOUtility.readStringUTF8(in);
+    }
     String w = SqlFormatter.wellform(s);
     int i = w.toLowerCase().indexOf("unparsed");
     if (i != -1) {
diff --git a/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyleTest.java b/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyleTest.java
index 4995d79..b9ee4aa 100644
--- a/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyleTest.java
+++ b/org.eclipse.scout.rt.server.jdbc.test/src/test/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyleTest.java
@@ -34,6 +34,7 @@
  * @since 3.9.0
  * @author awe, msc, kle
  */
+@SuppressWarnings("resource")
 public class AbstractSqlStyleTest {
 
   /**
diff --git a/org.eclipse.scout.rt.server.jdbc/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.jdbc/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.jdbc/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.jdbc/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.jdbc/pom.xml b/org.eclipse.scout.rt.server.jdbc/pom.xml
index f3b08dd..cdf7853 100644
--- a/org.eclipse.scout.rt.server.jdbc/pom.xml
+++ b/org.eclipse.scout.rt.server.jdbc/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/AbstractSqlService.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/AbstractSqlService.java
index 63e69e8..50272c1 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/AbstractSqlService.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/AbstractSqlService.java
@@ -161,7 +161,7 @@
     m_codeNameToDescriptor = new HashMap<>();
     ICodeService csvc = BEANS.opt(ICodeService.class);
     if (csvc != null) {
-      for (Class<?> d : csvc.getAllCodeTypeClasses("")) {
+      for (Class<?> d : csvc.getAllCodeTypeClasses()) {
         List<Class<?>> list = m_codeNameToDescriptor.get(d.getSimpleName());
         if (list == null) {
           list = new ArrayList<>();
@@ -617,6 +617,7 @@
 
     SqlTransactionMember member = (SqlTransactionMember) tx.getMember(getTransactionMemberId());
     if (member == null) {
+      @SuppressWarnings("resource")
       Connection connection = leaseConnection();
       member = new SqlTransactionMember(getTransactionMemberId(), connection);
       tx.registerMember(member);
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/SQL.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/SQL.java
index 62fb503..9bafb6d 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/SQL.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/SQL.java
@@ -66,6 +66,7 @@
   public static String getDriverName() {
     String driverName = null;
     try {
+      @SuppressWarnings("resource")
       Connection conn = getConnection();
       driverName = conn.getMetaData().getDriverName();
     }
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/csv/CsvSqlAdapter.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/csv/CsvSqlAdapter.java
index 5c0e36f..4bbb21a 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/csv/CsvSqlAdapter.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/csv/CsvSqlAdapter.java
@@ -182,7 +182,7 @@
         base = params.getBindBase();
       }
       else {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append("SELECT ");
         for (Iterator<String> it = cols.iterator(); it.hasNext();) {
           String colName = it.next();
@@ -283,7 +283,7 @@
         cols.add(params.getLineNumberColumnName());
       }
       cols.addAll(params.getCsvColumnNames()); //
-      StringBuffer buf = new StringBuffer();
+      StringBuilder buf = new StringBuilder();
       buf.append("INSERT INTO ");
       buf.append(params.getTableName());
       buf.append("(");
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/PreparedStatementCache.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/PreparedStatementCache.java
index 003804b..93e5b3b 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/PreparedStatementCache.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/PreparedStatementCache.java
@@ -43,6 +43,7 @@
     };
   }
 
+  @SuppressWarnings("resource")
   @Override
   public PreparedStatement getPreparedStatement(Connection conn, String s) throws SQLException {
     // a statement must be used at least 2 times within 2 minutes in order to be
@@ -79,6 +80,7 @@
     }
   }
 
+  @SuppressWarnings("resource")
   @Override
   public CallableStatement getCallableStatement(Connection conn, String s) throws SQLException {
     // a statement must be used at least 2 times within 2 minutes in order to be
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/StatementProcessor.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/StatementProcessor.java
index f785353..966ec04 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/StatementProcessor.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/internal/exec/StatementProcessor.java
@@ -26,8 +26,8 @@
 import java.util.TreeMap;
 
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.exception.ProcessingException;
 import org.eclipse.scout.rt.platform.exception.PlatformExceptionTranslator;
+import org.eclipse.scout.rt.platform.exception.ProcessingException;
 import org.eclipse.scout.rt.platform.holders.BeanArrayHolderFilter;
 import org.eclipse.scout.rt.platform.holders.IBeanArrayHolder;
 import org.eclipse.scout.rt.platform.holders.IHolder;
@@ -247,6 +247,7 @@
    * org.eclipse.scout.rt.
    * server.services.common.sql.internal.exec.PreparedStatementCache)
    */
+  @SuppressWarnings("resource")
   @Override
   public Object[][] processSelect(Connection conn, IStatementCache cache, IStatementProcessorMonitor monitor) {
     PreparedStatement ps = null;
@@ -302,6 +303,7 @@
    * #processSelectInto(java.sql.Connection,org.eclipse.scout.
    * rt.server.services.common.sql.internal.exec.PreparedStatementCache)
    */
+  @SuppressWarnings("resource")
   @Override
   public void processSelectInto(Connection conn, IStatementCache cache, IStatementProcessorMonitor monitor) {
     PreparedStatement ps = null;
@@ -347,6 +349,7 @@
     }
   }
 
+  @SuppressWarnings("resource")
   @Override
   public void processSelectStreaming(Connection conn, IStatementCache cache, ISelectStreamHandler handler) {
     PreparedStatement ps = null;
@@ -411,6 +414,7 @@
    * org.eclipse.scout
    * .rt.server.services.common.sql.internal.exec.PreparedStatementCache)
    */
+  @SuppressWarnings("resource")
   @Override
   public int processModification(Connection conn, IStatementCache cache, IStatementProcessorMonitor monitor) {
     PreparedStatement ps = null;
@@ -449,6 +453,7 @@
    * org.eclipse.
    * scout.rt.server.services.common.sql.internal.exec.PreparedStatementCache)
    */
+  @SuppressWarnings("resource")
   @Override
   public boolean processStoredProcedure(Connection conn, IStatementCache cache, IStatementProcessorMonitor monitor) {
     CallableStatement cs = null;
@@ -672,7 +677,7 @@
         debugBindBuf.append("\n");
       }
     }
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     if (statementWithBinds) {
       buf.append("SQL with binds:\n");
       buf.append(SqlFormatter.wellform(m_originalStm).trim());
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/BindModel.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/BindModel.java
index 63ed566..300bcd8 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/BindModel.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/BindModel.java
@@ -47,7 +47,7 @@
   }
 
   public String getFilteredStatement() {
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     for (int i = 0; i < m_allTokens.length; i++) {
       if (m_allTokens[i] instanceof ValueInputToken) {
         ValueInputToken valueInputToken = (ValueInputToken) m_allTokens[i];
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlParser.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlParser.java
index c4408c8..f97c9ac 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlParser.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/sql/SqlParser.java
@@ -865,7 +865,7 @@
   }
 
   private String flatten(List<IToken> list) {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     for (IToken item : list) {
       if (buf.length() > 0) {
         buf.append(" ");
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueInputToken.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueInputToken.java
index d522d75..a285fa0 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueInputToken.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueInputToken.java
@@ -120,7 +120,7 @@
 
   @Override
   public String toString() {
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     b.append(getClass().getSimpleName() + "[");
     b.append("parsed '");
     if (getParsedAttribute() != null) {
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueOutputToken.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueOutputToken.java
index dadb3d9..301c761 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueOutputToken.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/parsers/token/ValueOutputToken.java
@@ -78,7 +78,7 @@
 
   @Override
   public String toString() {
-    StringBuffer b = new StringBuffer();
+    StringBuilder b = new StringBuilder();
     b.append(getClass().getSimpleName() + "[");
     b.append(m_name);
     b.append(" ");
diff --git a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyle.java b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyle.java
index 7f3971f..94d6c95 100644
--- a/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyle.java
+++ b/org.eclipse.scout.rt.server.jdbc/src/main/java/org/eclipse/scout/rt/server/jdbc/style/AbstractSqlStyle.java
@@ -11,7 +11,6 @@
 package org.eclipse.scout.rt.server.jdbc.style;
 
 import java.io.ByteArrayInputStream;
-import java.io.Reader;
 import java.io.StringReader;
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
@@ -112,7 +111,7 @@
         array = value;
       }
       int n = Array.getLength(array);
-      StringBuffer buf = new StringBuffer();
+      StringBuilder buf = new StringBuilder();
       buf.append("(");
       if (n > 0) {
         for (int i = 0; i < n; i++) {
@@ -481,17 +480,11 @@
             int len = (int) c.length();
             if (len > 0) {
               // fast read
-              char[] ch = new char[len];
-              Reader r = c.getCharacterStream();
-              int processed = 0;
-              while (processed < len) {
-                processed += r.read(ch, processed, len - processed);
-              }
-              o = new String(ch);
+              o = IOUtility.readString(c.getCharacterStream(), len);
             }
             else {
               // dynamic read
-              o = IOUtility.getContent(c.getCharacterStream());
+              o = IOUtility.readString(c.getCharacterStream());
             }
           }
           catch (SQLException e) {
@@ -945,7 +938,7 @@
       return createNull(attribute);
     }
     int max = getMaxListSize();
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append("(");// bracket 1
     for (int i = 0; i < values.length; i = i + max) {
       if (i > 0) {
@@ -980,7 +973,7 @@
       return createNotNull(attribute);
     }
     int max = getMaxListSize();
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     buf.append("(");// bracket 1
     for (int i = 0; i < values.length; i = i + max) {
       if (i > 0) {
diff --git a/org.eclipse.scout.rt.server.jms/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.jms/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.jms/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.jms/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.jms/pom.xml b/org.eclipse.scout.rt.server.jms/pom.xml
index 24b029e..fefbe06 100644
--- a/org.eclipse.scout.rt.server.jms/pom.xml
+++ b/org.eclipse.scout.rt.server.jms/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server.test/pom.xml b/org.eclipse.scout.rt.server.test/pom.xml
index 6ecd263..9ef2e31 100644
--- a/org.eclipse.scout.rt.server.test/pom.xml
+++ b/org.eclipse.scout.rt.server.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server.test/src/main/java/org/eclipse/scout/rt/testing/server/runner/statement/ServerRunContextStatement.java b/org.eclipse.scout.rt.server.test/src/main/java/org/eclipse/scout/rt/testing/server/runner/statement/ServerRunContextStatement.java
index 68d833b..dc94816 100644
--- a/org.eclipse.scout.rt.server.test/src/main/java/org/eclipse/scout/rt/testing/server/runner/statement/ServerRunContextStatement.java
+++ b/org.eclipse.scout.rt.server.test/src/main/java/org/eclipse/scout/rt/testing/server/runner/statement/ServerRunContextStatement.java
@@ -20,6 +20,8 @@
 import org.eclipse.scout.rt.platform.util.Assertions;
 import org.eclipse.scout.rt.server.IServerSession;
 import org.eclipse.scout.rt.server.context.ServerRunContexts;
+import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
 import org.eclipse.scout.rt.testing.platform.runner.SafeStatementInvoker;
 import org.eclipse.scout.rt.testing.server.runner.RunWithServerSession;
@@ -57,16 +59,22 @@
       Assertions.fail("Subject must not be null. Use the annotation '{}' to execute your test under a particular user. ", RunWithSubject.class.getSimpleName());
     }
 
+    UserAgent userAgent = UserAgents.createDefault();
+
     final IBean serverSessionBean = BEANS.getBeanManager().registerBean(new BeanMetaData(m_serverSessionAnnotation.value()).withOrder(-Long.MAX_VALUE));
     try {
       // Obtain the server session for the given subject. Depending on the session provider, a new session is created or a cached session returned.
-      final IServerSession serverSession = BEANS.get(m_serverSessionAnnotation.provider()).provide(ServerRunContexts.copyCurrent().withSubject(currentSubject));
+      final IServerSession serverSession = BEANS.get(m_serverSessionAnnotation.provider()).provide(
+          ServerRunContexts.copyCurrent()
+              .withSubject(currentSubject)
+              .withUserAgent(userAgent));
 
       // Run the test on behalf of a ServerRunContext.
       final SafeStatementInvoker invoker = new SafeStatementInvoker(m_next);
       ServerRunContexts.copyCurrent()
           .withSession(serverSession)
           .withSubject(currentSubject) // set the test subject explicitly in case it is different to the session subject
+          .withUserAgent(userAgent)
           .run(invoker);
       invoker.throwOnError();
     }
diff --git a/org.eclipse.scout.rt.server.test/src/test/java/org/eclipse/scout/rt/server/context/ServerRunContextTest.java b/org.eclipse.scout.rt.server.test/src/test/java/org/eclipse/scout/rt/server/context/ServerRunContextTest.java
index 44452cb..de1952d 100644
--- a/org.eclipse.scout.rt.server.test/src/test/java/org/eclipse/scout/rt/server/context/ServerRunContextTest.java
+++ b/org.eclipse.scout.rt.server.test/src/test/java/org/eclipse/scout/rt/server/context/ServerRunContextTest.java
@@ -27,9 +27,8 @@
 import org.eclipse.scout.rt.server.transaction.TransactionScope;
 import org.eclipse.scout.rt.shared.ISession;
 import org.eclipse.scout.rt.shared.ScoutTexts;
-import org.eclipse.scout.rt.shared.ui.UiDeviceType;
-import org.eclipse.scout.rt.shared.ui.UiLayer;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.eclipse.scout.rt.testing.platform.runner.PlatformTestRunner;
 import org.junit.After;
 import org.junit.Before;
@@ -68,7 +67,7 @@
     runContext.getPropertyMap().put("A", "B");
     runContext.withSubject(new Subject());
     runContext.withSession(mock(IServerSession.class));
-    runContext.withUserAgent(UserAgent.create(UiLayer.UNKNOWN, UiDeviceType.UNKNOWN, "n/a"));
+    runContext.withUserAgent(UserAgents.create().build());
     runContext.withLocale(Locale.CANADA_FRENCH);
     runContext.withTransactionScope(TransactionScope.MANDATORY);
 
diff --git a/org.eclipse.scout.rt.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.server/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.server/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.server/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.server/pom.xml b/org.eclipse.scout.rt.server/pom.xml
index 63673e1..95846d9 100644
--- a/org.eclipse.scout.rt.server/pom.xml
+++ b/org.eclipse.scout.rt.server/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/AbstractServerSession.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/AbstractServerSession.java
index af15d9b..1738bb5 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/AbstractServerSession.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/AbstractServerSession.java
@@ -72,7 +72,7 @@
     m_eventListeners = new EventListenerList();
     m_sessionData = new SessionData();
     m_sharedVariableMap = new SharedVariableMap();
-    m_objectExtensions = new ObjectExtensions<AbstractServerSession, IServerSessionExtension<? extends AbstractServerSession>>(this);
+    m_objectExtensions = new ObjectExtensions<>(this);
     m_scoutTexts = new ScoutTexts();
     if (autoInitConfig) {
       interceptInitConfig();
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ResourceServlet.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ResourceServlet.java
index 39bb3eb..5d5524b 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ResourceServlet.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ResourceServlet.java
@@ -114,9 +114,8 @@
       return true;
     }
 
-    InputStream is = null;
-    try {
-      is = connection.getInputStream();
+    try (InputStream is = connection.getInputStream()) {
+      @SuppressWarnings("resource")
       OutputStream os = resp.getOutputStream();
       byte[] buffer = new byte[8192];
       int bytesRead = is.read(buffer);
@@ -129,13 +128,7 @@
       if (contentLength == -1 || contentLength != writtenContentLength) {
         resp.setContentLength(writtenContentLength);
       }
-
-      return true;
     }
-    finally {
-      if (is != null) {
-        is.close();
-      }
-    }
+    return true;
   }
 }
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ServiceTunnelServlet.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ServiceTunnelServlet.java
index c4cb711..7e5698c 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ServiceTunnelServlet.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/ServiceTunnelServlet.java
@@ -48,7 +48,7 @@
 import org.eclipse.scout.rt.shared.servicetunnel.IServiceTunnelContentHandler;
 import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelRequest;
 import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelResponse;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -90,7 +90,7 @@
       @Override
       public void run() throws Exception {
         ServerRunContext serverRunContext = ServerRunContexts.copyCurrent();
-        serverRunContext.withUserAgent(UserAgent.createDefault());
+        serverRunContext.withUserAgent(UserAgents.createDefault());
         serverRunContext.withSession(lookupServerSessionOnHttpSession(null, serverRunContext));
 
         invokeAdminService(serverRunContext);
@@ -136,7 +136,7 @@
     ClientNotificationCollector collector = new ClientNotificationCollector();
     ServerRunContext serverRunContext = ServerRunContexts.copyCurrent()
         .withLocale(serviceRequest.getLocale())
-        .withUserAgent(UserAgent.createByIdentifier(serviceRequest.getUserAgent()))
+        .withUserAgent(UserAgents.createByIdentifier(serviceRequest.getUserAgent()))
         .withClientNotificationCollector(collector)
         .withClientNodeId(serviceRequest.getClientNodeId());
 
@@ -174,6 +174,8 @@
         final HttpServletRequest servletRequest = IHttpServletRoundtrip.CURRENT_HTTP_SERVLET_REQUEST.get();
         final HttpServletResponse servletResponse = IHttpServletRoundtrip.CURRENT_HTTP_SERVLET_RESPONSE.get();
 
+        BEANS.get(HttpServletControl.class).doDefaults(ServiceTunnelServlet.this, servletRequest, servletResponse);
+
         AdminSession adminSession = (AdminSession) BEANS.get(IHttpSessionCacheService.class).getAndTouch(ADMIN_SESSION_KEY, servletRequest, servletResponse);
         if (adminSession == null) {
           adminSession = new AdminSession();
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticServlet.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticServlet.java
index 2cc205e..43a219a 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticServlet.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticServlet.java
@@ -27,7 +27,7 @@
 import org.eclipse.scout.rt.server.commons.servlet.ServletExceptionTranslator;
 import org.eclipse.scout.rt.server.context.ServerRunContext;
 import org.eclipse.scout.rt.server.context.ServerRunContexts;
-import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 
 public class DiagnosticServlet extends ServiceTunnelServlet {
   private static final long serialVersionUID = 1L;
@@ -51,7 +51,7 @@
       @Override
       public void run() throws Exception {
         ServerRunContext serverRunContext = ServerRunContexts.copyCurrent();
-        serverRunContext.withUserAgent(UserAgent.createDefault());
+        serverRunContext.withUserAgent(UserAgents.createDefault());
         serverRunContext.withSession(lookupServerSessionOnHttpSession(null, serverRunContext.copy()));
 
         invokeDiagnosticService(serverRunContext);
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticSession.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticSession.java
index d89a02d..3c9b6ad 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticSession.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/diagnostic/DiagnosticSession.java
@@ -69,6 +69,7 @@
     String diagnosticXML = getDiagnosticItemsXML(result);
 
     resp.setContentType("text/xml");
+    @SuppressWarnings("resource")
     ServletOutputStream out = resp.getOutputStream();
     out.println("<?xml version='1.0' encoding='UTF-8' ?>");
     out.println("<diagnosticsStatus>");
@@ -107,6 +108,7 @@
     String version = CONFIG.getPropertyValue(ApplicationVersionProperty.class);
 
     resp.setContentType("text/html");
+    @SuppressWarnings("resource")
     ServletOutputStream out = resp.getOutputStream();
     out.println("<html>");
     out.println("<head>");
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/AdminSession.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/AdminSession.java
index cb15f70..07bc3d9 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/AdminSession.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/AdminSession.java
@@ -71,6 +71,7 @@
     res.setHeader("Cache-Control", "no-cache");
     res.setHeader("pragma", "no-cache");
     // output
+    @SuppressWarnings("resource")
     ServletOutputStream out = res.getOutputStream();
     out.println("<html>");
     out.println("<head>");
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/view/ServicesView.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/view/ServicesView.java
index 8bb4fef..f4b1f80 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/view/ServicesView.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/admin/html/view/ServicesView.java
@@ -381,7 +381,7 @@
   }
 
   private String createSignature(Class[] a) {
-    StringBuffer sig = new StringBuffer();
+    StringBuilder sig = new StringBuilder();
     for (Class c : a) {
       if (sig.length() > 0) {
         sig.append(", ");
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/notification/NotificationCoalescer.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/notification/NotificationCoalescer.java
index 90e9e19..ef73a32 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/notification/NotificationCoalescer.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/notification/NotificationCoalescer.java
@@ -30,11 +30,11 @@
 @ApplicationScoped
 @CreateImmediately
 public class NotificationCoalescer {
-  private final TypeParameterBeanRegistry<ICoalescer> m_registry = new TypeParameterBeanRegistry<>();
+  private final TypeParameterBeanRegistry<ICoalescer> m_registry = new TypeParameterBeanRegistry<>(ICoalescer.class);
 
   @PostConstruct
   protected void buildCoalescerLinking() {
-    m_registry.registerBeans(ICoalescer.class, BEANS.all(ICoalescer.class));
+    m_registry.registerBeans(BEANS.all(ICoalescer.class));
   }
 
   @SuppressWarnings("unchecked")
diff --git a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/services/common/file/RemoteFileService.java b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/services/common/file/RemoteFileService.java
index 3ce5d67..3769914 100644
--- a/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/services/common/file/RemoteFileService.java
+++ b/org.eclipse.scout.rt.server/src/main/java/org/eclipse/scout/rt/server/services/common/file/RemoteFileService.java
@@ -16,6 +16,7 @@
 import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -106,8 +107,8 @@
         // no content change, keep null
       }
       else {
-        try {
-          result.readData(new FileInputStream(file), startPosition, maxBlockSize);
+        try (InputStream in = new FileInputStream(file)) {
+          result.readData(in, startPosition, maxBlockSize);
         }
         catch (IOException e) {
           throw new ProcessingException("error reading file: " + file.getAbsolutePath(), e);
@@ -211,9 +212,9 @@
   @RemoteServiceAccessDenied
   public void putRemoteFile(RemoteFile spec) {
     File file = getFileInternal(spec);
-    try {
-      file.getParentFile().mkdirs();
-      spec.writeData(new FileOutputStream(file));
+    file.getParentFile().mkdirs();
+    try (FileOutputStream out = new FileOutputStream(file)) {
+      spec.writeData(out);
       file.setLastModified(file.lastModified());
     }
     catch (Exception e) {
diff --git a/org.eclipse.scout.rt.serverbridge/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.serverbridge/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.serverbridge/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.serverbridge/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.serverbridge/pom.xml b/org.eclipse.scout.rt.serverbridge/pom.xml
index 69469a2..3301471 100644
--- a/org.eclipse.scout.rt.serverbridge/pom.xml
+++ b/org.eclipse.scout.rt.serverbridge/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/BridgeToServerBeanDecorator.java b/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/BridgeToServerBeanDecorator.java
index d076ad8..7bf4e5e 100644
--- a/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/BridgeToServerBeanDecorator.java
+++ b/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/BridgeToServerBeanDecorator.java
@@ -13,7 +13,6 @@
 import java.util.List;
 import java.util.concurrent.Callable;
 
-import org.eclipse.scout.rt.client.IClientNode;
 import org.eclipse.scout.rt.client.clientnotification.ClientNotificationDispatcher;
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.context.RunContextIdentifiers;
@@ -25,6 +24,7 @@
 import org.eclipse.scout.rt.server.context.ServerRunContexts;
 import org.eclipse.scout.rt.server.session.ServerSessionProviderWithCache;
 import org.eclipse.scout.rt.server.transaction.ITransaction;
+import org.eclipse.scout.rt.shared.INode;
 import org.eclipse.scout.rt.shared.ISession;
 import org.eclipse.scout.rt.shared.clientnotification.ClientNotificationMessage;
 
@@ -72,7 +72,7 @@
     ServerRunContext bridgeRunContext = ServerRunContexts
         .copyCurrent()
         .withClientNotificationCollector(collector)
-        .withClientNodeId(IClientNode.ID);
+        .withClientNodeId(INode.ID);
     ISession currentSession = ISession.CURRENT.get();
     IServerSession bridgeSession = null;
     if (currentSession != null) {
diff --git a/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/RegisterTunnelToServerBridgePlatformListener.java b/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/RegisterTunnelToServerBridgePlatformListener.java
index 1fad02f..8e7ccb2 100644
--- a/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/RegisterTunnelToServerBridgePlatformListener.java
+++ b/org.eclipse.scout.rt.serverbridge/src/main/java/org/eclipse/scout/rt/serverbridge/RegisterTunnelToServerBridgePlatformListener.java
@@ -12,21 +12,27 @@
 
 import java.util.List;
 
-import org.eclipse.scout.rt.client.RegisterTunnelToServerPlatformListener;
 import org.eclipse.scout.rt.platform.BeanMetaData;
 import org.eclipse.scout.rt.platform.IBean;
 import org.eclipse.scout.rt.platform.IBeanManager;
 import org.eclipse.scout.rt.platform.Replace;
 import org.eclipse.scout.rt.shared.AnnotationFactory;
+import org.eclipse.scout.rt.shared.servicetunnel.RegisterTunnelToServerPlatformListener;
 
 /**
  * Instead of registering @TunnelToServer beans using interfaces we append the @TunnelToServer annotation to all beans
  * actually implementing a @TunnelToServer marked interface.
- * 
+ *
  * @since 5.2
  */
 @Replace
 public class RegisterTunnelToServerBridgePlatformListener extends RegisterTunnelToServerPlatformListener {
+
+  @Override
+  protected boolean isEnabled() {
+    return true;
+  }
+
   @Override
   protected void registerTunnelToServerProxy(IBeanManager beanManager, Class<?> c) {
     List<? extends IBean<?>> beans = beanManager.getBeans(c);
diff --git a/org.eclipse.scout.rt.shared.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.shared.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.shared.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.shared.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.shared.test/pom.xml b/org.eclipse.scout.rt.shared.test/pom.xml
index 7623c63..54400b6 100644
--- a/org.eclipse.scout.rt.shared.test/pom.xml
+++ b/org.eclipse.scout.rt.shared.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/csv/CsvHelperTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/csv/CsvHelperTest.java
index 9f9d4aa..84fe57e 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/csv/CsvHelperTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/csv/CsvHelperTest.java
@@ -69,11 +69,10 @@
     };
     export(data);
 
-    Reader reader = new FileReader(m_testFile);
     IDataConsumer dataConsumer = mock(IDataConsumer.class);
     ProcessingException pe = new ProcessingException();
     doThrow(pe).when(dataConsumer).processRow(eq(2), anyListOf(Object.class)); //Throw an exception in the 2nd line
-    try {
+    try (Reader reader = new FileReader(m_testFile)) {
       m_csvHelper.importData(dataConsumer, reader, true, true, 1);
       fail("No exception was thrown! Expected ProcessingException");
     }
@@ -95,8 +94,7 @@
     };
     export(data);
 
-    Reader reader = new FileReader(m_testFile);
-    try {
+    try (Reader reader = new FileReader(m_testFile)) {
       m_csvHelper.importData(reader, 1, Arrays.asList(new String[]{"string", "string", "float", "string", "string"}), 4);
       fail("No exception was thrown! Expected ProcessingException");
     }
@@ -119,9 +117,10 @@
 
     export(data);
 
-    Reader reader = new FileReader(m_testFile);
-    Object[][] result = m_csvHelper.importData(reader, 1, Arrays.asList(new String[]{"string", "string", "string", "string", "string"}), 4);
-    assertArrayEquals(data, result);
+    try (Reader in = new FileReader(m_testFile)) {
+      Object[][] result = m_csvHelper.importData(in, 1, Arrays.asList(new String[]{"string", "string", "string", "string", "string"}), 4);
+      assertArrayEquals(data, result);
+    }
   }
 
   @Test
@@ -135,8 +134,10 @@
 
     export(data);
 
-    String content = IOUtility.getContent(new FileReader(m_testFile));
-    String[] lines = content.split("\n");
+    String[] lines;
+    try (Reader in = new FileReader(m_testFile)) {
+      lines = IOUtility.readString(in).split("\n");
+    }
 
     assertEquals(lines.length, 5);
 
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/data/model/DataModelUtilityTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/data/model/DataModelUtilityTest.java
index f720420..60b3ef0 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/data/model/DataModelUtilityTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/data/model/DataModelUtilityTest.java
@@ -13,8 +13,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
+import java.net.URL;
 import java.util.HashSet;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -60,13 +61,13 @@
     String s;
     //
     s = visit(dataModel, v, 2);
-    assertEquals(readTextFile(ResourceBase.class.getResourceAsStream("data/model/level2-new.txt")), s.trim());
+    assertEquals(readTextFile(ResourceBase.class.getResource("data/model/level2-new.txt")), s.trim());
     //
     s = visit(dataModel, v, 3);
-    assertEquals(readTextFile(ResourceBase.class.getResourceAsStream("data/model/level3-new.txt")), s.trim());
+    assertEquals(readTextFile(ResourceBase.class.getResource("data/model/level3-new.txt")), s.trim());
     //
     s = visit(dataModel, v, 4);
-    assertEquals(readTextFile(ResourceBase.class.getResourceAsStream("data/model/level4-new.txt")), s.trim());
+    assertEquals(readTextFile(ResourceBase.class.getResource("data/model/level4-new.txt")), s.trim());
   }
 
   @Test
@@ -112,8 +113,10 @@
     assertEquals(3545, externaIdSet.size());
   }
 
-  private String readTextFile(InputStream in) throws UnsupportedEncodingException {
-    return IOUtility.getContentUtf8(in).replaceAll("[\\n\\r]+", "\n").trim();
+  private String readTextFile(URL url) throws IOException {
+    try (InputStream in = url.openStream()) {
+      return IOUtility.readStringUTF8(in).replaceAll("[\\n\\r]+", "\n").trim();
+    }
   }
 
   private String visit(IDataModel m, IDataModelVisitor v, int maxLevel) {
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/mail/MailUtilityTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/mail/MailUtilityTest.java
index c5c24b5..fb51de2 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/mail/MailUtilityTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/mail/MailUtilityTest.java
@@ -19,6 +19,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -77,8 +78,10 @@
     assertTrue(ds instanceof ByteArrayDataSource);
     ByteArrayDataSource bds = (ByteArrayDataSource) ds;
     assertEquals("application/octet-stream", bds.getContentType());
-    byte[] data = IOUtility.getContent(bds.getInputStream());
-    assertArrayEquals(sampleData, data);
+    try (InputStream in = bds.getInputStream()) {
+      byte[] data = IOUtility.readBytes(in);
+      assertArrayEquals(sampleData, data);
+    }
   }
 
   @Test
@@ -92,8 +95,10 @@
     assertTrue(ds instanceof ByteArrayDataSource);
     ByteArrayDataSource bds = (ByteArrayDataSource) ds;
     assertEquals("application/octet-stream", bds.getContentType());
-    byte[] data = IOUtility.getContent(bds.getInputStream());
-    assertArrayEquals(sampleData, data);
+    try (InputStream in = bds.getInputStream()) {
+      byte[] data = IOUtility.readBytes(in);
+      assertArrayEquals(sampleData, data);
+    }
 
     new MailMessage().withBodyPlainText("test").withAttachment(new MailAttachment(ds));
     MimeMessage message = MailUtility.createMimeMessage(new MailMessage().withBodyPlainText("test"));
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistryTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistryTest.java
index d6d956b..3ed6e76 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistryTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistryTest.java
@@ -14,8 +14,11 @@
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
+import org.eclipse.scout.rt.platform.util.IRegistrationHandle;
 import org.junit.Test;
 
 /**
@@ -25,43 +28,74 @@
 
   @Test
   public void testEmptyRegistry() throws Exception {
-    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>();
+    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>(ITestHandler.class);
     assertTrue(reg.getBeans(String.class).isEmpty());
   }
 
   @Test
   public void testEmptyRegistration() {
-    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>();
+    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>(ITestHandler.class);
     final List<ITestHandler> l = new ArrayList<>();
-    reg.registerBeans(ITestHandler.class, l);
+    reg.registerBeans(l);
     assertTrue(reg.getBeans(String.class).isEmpty());
   }
 
   @Test
   public void testStringHandler() {
-    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>();
+    final TypeParameterBeanRegistry<ITestHandler> registry = new TypeParameterBeanRegistry<>(ITestHandler.class);
     final List<ITestHandler> l = new ArrayList<>();
     l.add(new String1Handler());
     l.add(new LongHandler());
     l.add(new String2Handler());
     l.add(new CharSequenceHandler());
-    reg.registerBeans(ITestHandler.class, l);
-    final List<ITestHandler> res = reg.getBeans(String.class);
-    assertEquals(3, res.size());
-    assertEquals(l.get(0), res.get(0));
-    assertEquals(l.get(2), res.get(1));
-    assertEquals(l.get(3), res.get(2));
+
+    IRegistrationHandle registration = registry.registerBeans(l);
+    final List<ITestHandler> stringResult = registry.getBeans(String.class);
+    assertEquals(3, stringResult.size());
+    assertEquals(l.get(0), stringResult.get(0));
+    assertEquals(l.get(2), stringResult.get(1));
+    assertEquals(l.get(3), stringResult.get(2));
+
+    List<ITestHandler> charSequenceResult = registry.getBeans(CharSequence.class);
+    assertEquals(1, charSequenceResult.size());
+    assertEquals(l.get(3), charSequenceResult.get(0));
+
+    registration.dispose();
+
+    assertEquals(0, registry.getBeans(String.class).size());
+    assertEquals(0, registry.getBeans(CharSequence.class).size());
   }
 
   @Test
-  public void testCahedCharSeqHandler() {
-    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>();
+  public void testStringHandler1() {
+    String1Handler sh1 = new String1Handler();
+    String2Handler sh2 = new String2Handler();
+    CharSequenceHandler ch1 = new CharSequenceHandler();
+
+    final TypeParameterBeanRegistry<ITestHandler> registry = new TypeParameterBeanRegistry<>(ITestHandler.class);
+
+    registry.registerBean(sh1);
+    assertEquals(Arrays.asList(sh1), registry.getBeans(String.class));
+    assertEquals(Collections.emptyList(), registry.getBeans(CharSequence.class));
+
+    registry.registerBean(sh2);
+    assertEquals(Arrays.asList(sh1, sh2), registry.getBeans(String.class));
+    assertEquals(Collections.emptyList(), registry.getBeans(CharSequence.class));
+
+    registry.registerBean(ch1);
+    assertEquals(Arrays.asList(sh1, sh2, ch1), registry.getBeans(String.class));
+    assertEquals(Arrays.asList(ch1), registry.getBeans(CharSequence.class));
+  }
+
+  @Test
+  public void testCachedCharSeqHandler() {
+    final TypeParameterBeanRegistry<ITestHandler> reg = new TypeParameterBeanRegistry<>(ITestHandler.class);
     final List<ITestHandler> l = new ArrayList<>();
     l.add(new String1Handler());
     l.add(new LongHandler());
     l.add(new String2Handler());
     l.add(new CharSequenceHandler());
-    reg.registerBeans(ITestHandler.class, l);
+    reg.registerBeans(l);
     //first lookup
     reg.getBeans(CharSequence.class);
     //get cached result
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/services/common/code/CodeServiceTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/services/common/code/CodeServiceTest.java
index 2b3bddd..7a0b959 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/services/common/code/CodeServiceTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/services/common/code/CodeServiceTest.java
@@ -51,12 +51,12 @@
   @Test
   public void testGetAllCodeTypeClasses() {
     ICodeService service = newCodeServiceInstance();
-    Collection<Class<? extends ICodeType<?, ?>>> codeTypeClasses1 = service.getAllCodeTypeClasses("");
+    Collection<Class<? extends ICodeType<?, ?>>> codeTypeClasses1 = service.getAllCodeTypeClasses();
     assertEquals("codeTypeClasses1 size", 2, codeTypeClasses1.size());
     assertEquals("codeTypeClasses1 contains AbcCodeType", true, codeTypeClasses1.contains(AbcCodeType.class));
     assertEquals("codeTypeClasses1 contains ZyxCodeType", true, codeTypeClasses1.contains(ZyxCodeType.class));
 
-    Collection<Class<? extends ICodeType<?, ?>>> codeTypeClasses2 = service.getAllCodeTypeClasses("");
+    Collection<Class<? extends ICodeType<?, ?>>> codeTypeClasses2 = service.getAllCodeTypeClasses();
     assertEquals("codeTypeClasses2 size", 1, codeTypeClasses2.size());
     assertEquals("codeTypeClasses2 contains AbcCodeType", true, codeTypeClasses2.contains(AbcCodeType.class));
     assertEquals("codeTypeClasses2 contains ZyxCodeType", false, codeTypeClasses2.contains(ZyxCodeType.class));
@@ -69,7 +69,7 @@
   @Test
   public void testGetAllCodeTypesString() {
     ICodeService service = newCodeServiceInstance();
-    Collection<ICodeType<?, ?>> codeTypes1 = service.getAllCodeTypes("");
+    Collection<ICodeType<?, ?>> codeTypes1 = service.getAllCodeTypes();
     assertEquals("size", 2, codeTypes1.size());
     Set<Class<?>> codeTypeClasses = new HashSet<Class<?>>(2);
     for (ICodeType<?, ?> ct : codeTypes1) {
@@ -78,7 +78,7 @@
     assertTrue(codeTypeClasses.contains(AbcCodeType.class));
     assertTrue(codeTypeClasses.contains(ZyxCodeType.class));
 
-    Collection<ICodeType<?, ?>> codeTypes2 = service.getAllCodeTypes("");
+    Collection<ICodeType<?, ?>> codeTypes2 = service.getAllCodeTypes();
     assertEquals("size", 1, codeTypes2.size());
     assertEquals("codeType 2 (0)", AbcCodeType.class, CollectionUtility.firstElement(codeTypes2).getClass());
   }
@@ -89,7 +89,7 @@
   @Test
   public void testGetCodeTypeClass() {
     ICodeService service = newCodeServiceInstance();
-    service.getAllCodeTypes("");
+    service.getAllCodeTypes();
 
     AbcCodeType abcCodeType1 = service.getCodeType(AbcCodeType.class);
     AbcCodeType abcCodeType2 = service.getCodeType(AbcCodeType.class);
@@ -106,7 +106,7 @@
   @Test
   public void testGetCodeTypesList() {
     ICodeService service = newCodeServiceInstance();
-    service.getAllCodeTypes("");
+    service.getAllCodeTypes();
 
     List<Class<? extends ICodeType<?, ?>>> types1 = new ArrayList<Class<? extends ICodeType<?, ?>>>();
     types1.add(AbcCodeType.class);
@@ -145,7 +145,7 @@
   @Test
   public void testReloadCodeType() throws Exception {
     ICodeService service = newCodeServiceInstance();
-    service.getAllCodeTypes("");
+    service.getAllCodeTypes();
 
     AbcCodeType abcCodeType1 = service.getCodeType(AbcCodeType.class);
 
@@ -168,7 +168,7 @@
   @Test
   public void testReloadCodeTypes() throws Exception {
     ICodeService service = newCodeServiceInstance();
-    service.getAllCodeTypes("");
+    service.getAllCodeTypes();
 
     AbcCodeType abcCodeType1 = service.getCodeType(AbcCodeType.class);
     ZyxCodeType zyxCodeType1 = service.getCodeType(ZyxCodeType.class);
@@ -253,7 +253,7 @@
     private boolean m_isFirst = true;
 
     @Override
-    public Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses(String classPrefix) {
+    public Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses() {
       Set<Class<? extends ICodeType<?, ?>>> result = new HashSet<>();
       result.add(AbcCodeType.class);
       if (m_isFirst) {
diff --git a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListenerTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListenerTest.java
similarity index 98%
rename from org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListenerTest.java
rename to org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListenerTest.java
index 069abd8..f30f054 100644
--- a/org.eclipse.scout.rt.client.test/src/test/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListenerTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListenerTest.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client;
+package org.eclipse.scout.rt.shared.servicetunnel;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnelTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnelTest.java
new file mode 100644
index 0000000..7cf1cd2
--- /dev/null
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnelTest.java
@@ -0,0 +1,142 @@
+package org.eclipse.scout.rt.shared.servicetunnel.http;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.net.URLConnection;
+
+import org.eclipse.scout.rt.shared.SharedConfigProperties.ServiceTunnelTargetUrlProperty;
+import org.eclipse.scout.rt.shared.servicetunnel.IServiceTunnelContentHandler;
+import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelRequest;
+import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelResponse;
+import org.eclipse.scout.rt.testing.platform.mock.BeanMock;
+import org.eclipse.scout.rt.testing.platform.runner.PlatformTestRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link HttpServiceTunnel}
+ */
+@RunWith(PlatformTestRunner.class)
+public class HttpServiceTunnelTest {
+
+  @BeanMock
+  private ServiceTunnelTargetUrlProperty mockUrl;
+
+  @BeanMock
+  private IServiceTunnelContentHandler m_contentHandler;
+
+  @Test
+  public void testTunnel() throws IOException {
+    when(mockUrl.getValue()).thenReturn("http://localhost");
+
+    ServiceTunnelResponse expectedResponse = new ServiceTunnelResponse("testData", new Object[]{});
+    final URLConnection urlConnection = mock(URLConnection.class);
+    when(urlConnection.getInputStream()).thenReturn(getInputStream(expectedResponse));
+
+    HttpServiceTunnel tunnel = new HttpServiceTunnel() {
+      @Override
+      protected URLConnection createURLConnection(ServiceTunnelRequest call, byte[] callData) throws IOException {
+        return urlConnection;
+      }
+    };
+    tunnel.setContentHandler(getTestContentHandler());
+    ServiceTunnelRequest request = new ServiceTunnelRequest("IPingService", "ping", null, null);
+    ServiceTunnelResponse response = tunnel.tunnel(request);
+    assertNotNull(response);
+  }
+
+  /**
+   * {@link HttpServiceTunnel} should be inactive, if no url is defined.
+   */
+  @Test
+  public void testNullUrlConfig() {
+    HttpServiceTunnel tunnel = new HttpServiceTunnel();
+    assertNull(tunnel.getServerUrl());
+    assertFalse(tunnel.isActive());
+  }
+
+  /**
+   * {@link HttpServiceTunnel} should be inactive, if no url is defined.
+   */
+  @Test
+  public void testEmptyUrlConfig() {
+    when(mockUrl.getValue()).thenReturn(" ");
+    HttpServiceTunnel tunnel = new HttpServiceTunnel();
+    assertNull(tunnel.getServerUrl());
+    assertFalse(tunnel.isActive());
+  }
+
+  /**
+   * {@link HttpServiceTunnel} should be inactive, if no url is defined.
+   */
+  @Test(expected = RuntimeException.class)
+  public void testInvalidUrlConfig() {
+    when(mockUrl.getValue()).thenReturn("asdf");
+    new HttpServiceTunnel();
+  }
+
+  @Test
+  public void testValidUrlConfig() {
+    when(mockUrl.getValue()).thenReturn("http://localhost");
+    HttpServiceTunnel tunnel = new HttpServiceTunnel();
+    assertNotNull(tunnel.getServerUrl());
+    assertTrue(tunnel.isActive());
+  }
+
+  private ByteArrayInputStream getInputStream(ServiceTunnelResponse response) throws IOException {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+      oos.writeObject(response);
+      oos.flush();
+    }
+    return new ByteArrayInputStream(baos.toByteArray());
+  }
+
+  private IServiceTunnelContentHandler getTestContentHandler() {
+    return new IServiceTunnelContentHandler() {
+
+      @Override
+      public void writeResponse(OutputStream out, ServiceTunnelResponse msg) throws Exception {
+      }
+
+      @Override
+      public void writeRequest(OutputStream out, ServiceTunnelRequest msg) throws Exception {
+      }
+
+      @Override
+      public ServiceTunnelResponse readResponse(InputStream in) throws Exception {
+        ByteArrayInputStream bi = (ByteArrayInputStream) in;
+        ObjectInputStream in2 = new ObjectInputStream(bi);
+        Object o = in2.readObject();
+        return (ServiceTunnelResponse) o;
+      }
+
+      @Override
+      public ServiceTunnelRequest readRequest(InputStream in) throws Exception {
+        return null;
+      }
+
+      @Override
+      public void initialize() {
+      }
+
+      @Override
+      public String getContentType() {
+        return null;
+      }
+    };
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/text/HTMLTextTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/text/HTMLTextTest.java
index 03b1de5..da5b790 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/text/HTMLTextTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/text/HTMLTextTest.java
@@ -53,7 +53,7 @@
 
   @Test
   public void testBoldHtmlText() {
-    IHtmlContent boldText = HTML.bold(HTML.raw(TEXTS.get("key6", HTML.appLink("REF", "text").toEncodedHtml())));
-    assertEquals("<b>value <span class=\"app-link\" data-ref=\"REF\">text</span></b>", boldText.toEncodedHtml());
+    IHtmlContent boldText = HTML.bold(HTML.raw(TEXTS.get("key6", HTML.appLink("REF", "text").toHtml())));
+    assertEquals("<b>value <span class=\"app-link\" data-ref=\"REF\">text</span></b>", boldText.toHtml());
   }
 }
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParserTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParserTest.java
new file mode 100644
index 0000000..c26c588
--- /dev/null
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParserTest.java
@@ -0,0 +1,75 @@
+package org.eclipse.scout.rt.shared.ui;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * <h3>{@link DefaultUserAgentParser}</h3>
+ */
+public class DefaultUserAgentParserTest {
+  private UserAgent m_defaultAgent;
+
+  @Before
+  public void before() {
+    m_defaultAgent = UserAgents.createDefault();
+  }
+
+  @Test
+  public void testInvalidId() {
+    UserAgent parsedAgent = UserAgents.createByIdentifier(new DefaultUserAgentParser(), "XY|DESKTOP|UNKNOWN|Windows7");
+    assertEquals(m_defaultAgent, parsedAgent);
+  }
+
+  @Test()
+  public void testEmptyId() {
+    UserAgent parsedAgent = UserAgents.createByIdentifier(new DefaultUserAgentParser(), "");
+    assertEquals(m_defaultAgent, parsedAgent);
+  }
+
+  @Test
+  public void testDefaultAgent() {
+    DefaultUserAgentParser parser = new DefaultUserAgentParser();
+    String id = m_defaultAgent.createIdentifier(parser);
+    UserAgent parsedAgent = UserAgents.createByIdentifier(parser, id);
+    assertEquals(m_defaultAgent, parsedAgent);
+  }
+
+  @Test
+  public void testParsingCustomAgent() {
+    UserAgent testUserAgent = UserAgents
+        .create()
+        .withUiLayer(UiLayer.HTML)
+        .withUiDeviceType(UiDeviceType.MOBILE)
+        .withUiEngineType(UiEngineType.ANDROID)
+        .withUiSystem(UiSystem.ANDROID)
+        .withDeviceId("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30")
+        .build();
+    DefaultUserAgentParser parser = new DefaultUserAgentParser();
+    String id = testUserAgent.createIdentifier(parser);
+
+    UserAgent parsedAgent = UserAgents.createByIdentifier(parser, id);
+    assertEquals(testUserAgent, parsedAgent);
+  }
+
+  @Test
+  public void testParseInvalidDeviceId() {
+    UserAgent testUserAgent = UserAgents
+        .create()
+        .withUiLayer(UiLayer.HTML)
+        .withUiDeviceType(UiDeviceType.MOBILE)
+        .withUiEngineType(UiEngineType.ANDROID)
+        .withUiSystem(UiSystem.ANDROID)
+        .withDeviceId("xxx|yyy")
+        .build();
+    DefaultUserAgentParser parser = new DefaultUserAgentParser();
+    String id = testUserAgent.createIdentifier(parser);
+
+    UserAgent parsedAgent = UserAgents.createByIdentifier(parser, id);
+    assertEquals(testUserAgent.getUiDeviceType(), parsedAgent.getUiDeviceType());
+    assertEquals(testUserAgent.getUiLayer(), parsedAgent.getUiLayer());
+
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/UserAgentTest.java b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/UserAgentTest.java
index db7aedc..c2f5d3a 100644
--- a/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/UserAgentTest.java
+++ b/org.eclipse.scout.rt.shared.test/src/test/java/org/eclipse/scout/rt/shared/ui/UserAgentTest.java
@@ -24,9 +24,9 @@
 
   @Test
   public void testEqualsAndHashCode() {
-    UserAgent userAgentHtml = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP);
-    UserAgent userAgentHtml2 = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP);
-    UserAgent userAgentHtmlMobile = UserAgent.create(UiLayer.HTML, UiDeviceType.MOBILE);
+    UserAgent userAgentHtml = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.DESKTOP).build();
+    UserAgent userAgentHtml2 = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.DESKTOP).build();
+    UserAgent userAgentHtmlMobile = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.MOBILE).build();
 
     assertEquals(userAgentHtml, userAgentHtml2);
     assertEquals(userAgentHtml.hashCode(), userAgentHtml2.hashCode());
@@ -36,9 +36,9 @@
 
     String chromeUserAgentStr = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19";
     String firefoxUserAgentStr = "Mozilla/5.0 .. Firefox ..";
-    UserAgent userAgentHtmlChrome = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP, chromeUserAgentStr);
-    UserAgent userAgentHtmlChrome2 = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP, chromeUserAgentStr);
-    UserAgent userAgentHtmlFirefox = UserAgent.create(UiLayer.HTML, UiDeviceType.DESKTOP, firefoxUserAgentStr);
+    UserAgent userAgentHtmlChrome = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.DESKTOP).withDeviceId(chromeUserAgentStr).build();
+    UserAgent userAgentHtmlChrome2 = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.DESKTOP).withDeviceId(chromeUserAgentStr).build();
+    UserAgent userAgentHtmlFirefox = UserAgents.create().withUiLayer(UiLayer.HTML).withUiDeviceType(UiDeviceType.DESKTOP).withDeviceId(firefoxUserAgentStr).build();
 
     assertEquals(userAgentHtmlChrome, userAgentHtmlChrome2);
     assertEquals(userAgentHtmlChrome.hashCode(), userAgentHtmlChrome2.hashCode());
diff --git a/org.eclipse.scout.rt.shared/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.shared/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.shared/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.shared/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.shared/pom.xml b/org.eclipse.scout.rt.shared/pom.xml
index ca6e2b5..d539773 100644
--- a/org.eclipse.scout.rt.shared/pom.xml
+++ b/org.eclipse.scout.rt.shared/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/AbstractIcons.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/AbstractIcons.java
index d0885cd..4c71139 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/AbstractIcons.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/AbstractIcons.java
@@ -15,6 +15,7 @@
 /**
  * See also icons.css.
  */
+//SONAR:OFF
 public abstract class AbstractIcons implements Serializable {
   private static final long serialVersionUID = 1L;
 
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/IClientNode.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/INode.java
similarity index 82%
rename from org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/IClientNode.java
rename to org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/INode.java
index 8adb538..db7f4c6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/IClientNode.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/INode.java
@@ -8,16 +8,16 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client;
+package org.eclipse.scout.rt.shared;
 
 import java.util.UUID;
 
 /**
- * Represents a client node which typically hosts multiple client sessions.
+ * Represents a server or client node
  *
  * @since 5.2
  */
-public interface IClientNode {
+public interface INode {
 
   /**
    * Unique ID to identify this node.
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/OfficialVersion.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/OfficialVersion.java
index 115541d..a97fa8a 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/OfficialVersion.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/OfficialVersion.java
@@ -17,7 +17,7 @@
   private OfficialVersion() {
   }
 
-  public static final String VERSION = "5.2.0";
+  public static final String VERSION = "6.0.0";
 
   public static final String COPYRIGHT = "Scout " + VERSION + ", &copy; BSI Business Systems Integration AG " + 2001 + "," + Calendar.getInstance().get(Calendar.YEAR) + " EPL";
 
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/SharedConfigProperties.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/SharedConfigProperties.java
index 35b9735..c6794bd 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/SharedConfigProperties.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/SharedConfigProperties.java
@@ -160,9 +160,7 @@
 
     @Override
     protected Subject getDefaultValue() {
-//TODO [5.2] jgu: ???
-//      return convertToSubject("notification-authenticator");
-      return convertToSubject("system");
+      return convertToSubject("notification-authenticator");
     }
   }
 
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/csv/CsvHelper.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/csv/CsvHelper.java
index 39d2208..66cedbe 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/csv/CsvHelper.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/csv/CsvHelper.java
@@ -78,7 +78,7 @@
     m_separatorChar = separatorChar != 0x00 ? separatorChar : ';';
     m_textDelimiterChar = textDelimiterChar != 0x00 ? textDelimiterChar : '"';
     m_lineSeparator = lineSeparator != null ? lineSeparator : "\n";
-    m_colFormat = new ArrayList<Format>();
+    m_colFormat = new ArrayList<>();
   }
 
   public Locale getLocale() {
@@ -421,7 +421,7 @@
   protected List<String> importRow(Reader reader) throws IOException {
     List<String> cellList = new ArrayList<String>(Math.max(m_colCount, 2));
     boolean inString = false;
-    StringBuffer curBuf = new StringBuffer();
+    StringBuilder curBuf = new StringBuilder();
     String token;
     int ch = reader.read();
 
@@ -487,7 +487,7 @@
   }
 
   protected String exportRow(Collection<String> strings) {
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     if (strings != null) {
       for (Iterator<String> it = strings.iterator(); it.hasNext();) {
         buf.append(encodeText(it.next()));
@@ -556,7 +556,7 @@
     if (s == null || sOld == null) {
       return s;
     }
-    StringBuffer buf = new StringBuffer();
+    StringBuilder buf = new StringBuilder();
     int oldLen = sOld.length();
     int pos = 0;
     int i = s.indexOf(sOld);
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractFormFieldData.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractFormFieldData.java
index 4f20625..89cca20 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractFormFieldData.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractFormFieldData.java
@@ -17,6 +17,7 @@
 
 import org.eclipse.scout.rt.platform.Replace;
 import org.eclipse.scout.rt.platform.reflect.ConfigurationUtility;
+import org.eclipse.scout.rt.platform.util.BeanUtility;
 import org.eclipse.scout.rt.shared.data.form.FormDataUtility;
 import org.eclipse.scout.rt.shared.data.form.IPropertyHolder;
 import org.eclipse.scout.rt.shared.data.form.properties.AbstractPropertyData;
@@ -30,9 +31,6 @@
   private Map<Class<? extends AbstractFormFieldData>, AbstractFormFieldData> m_fieldMap;
   private boolean m_valueSet;
 
-  public AbstractFormFieldData() {
-  }
-
   private List<Class<AbstractPropertyData>> getConfiguredPropertyDatas() {
     Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
     return ConfigurationUtility.filterClasses(dca, AbstractPropertyData.class);
@@ -44,6 +42,18 @@
     return ConfigurationUtility.removeReplacedClasses(fca);
   }
 
+  /**
+   * When importing form data, this class is used as a stop class for
+   * {@link BeanUtility#getProperties(Object, Class, org.eclipse.scout.rt.platform.reflect.IPropertyFilter)}.
+   * <p>
+   * If a subclass of {@link AbstractFormFieldData} implements this method, it must return its own class. When
+   * implementing, the class must make sure that it handles the import of properties itself by providing an appropriate
+   * implementation of 'AbstractFormField#importFormFieldData' (if required).
+   */
+  public Class<?> getFieldStopClass() {
+    return AbstractFormFieldData.class;
+  }
+
   @Override
   protected void initConfig() {
     // add properties
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractValueFieldData.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractValueFieldData.java
index 255dbda..c9e97b4 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractValueFieldData.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/AbstractValueFieldData.java
@@ -22,8 +22,9 @@
 
   private T m_value;
 
-  public AbstractValueFieldData() {
-    super();
+  @Override
+  public Class<?> getFieldStopClass() {
+    return AbstractValueFieldData.class;
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/browserfield/AbstractBrowserFieldData.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/browserfield/AbstractBrowserFieldData.java
index 5ab0c61..b82c4bd 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/browserfield/AbstractBrowserFieldData.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/browserfield/AbstractBrowserFieldData.java
@@ -23,8 +23,9 @@
   private BinaryResource m_binaryResource;
   private Set<BinaryResource> m_attachments;
 
-  public AbstractBrowserFieldData() {
-    super();
+  @Override
+  public Class<?> getFieldStopClass() {
+    return AbstractBrowserFieldData.class;
   }
 
   public String getLocation() {
@@ -33,6 +34,7 @@
 
   public void setLocation(String location) {
     m_location = location;
+    setValueSet(true);
   }
 
   public BinaryResource getBinaryResource() {
@@ -41,6 +43,7 @@
 
   public void setBinaryResource(BinaryResource binaryResource) {
     m_binaryResource = binaryResource;
+    setValueSet(true);
   }
 
   public Set<BinaryResource> getAttachments() {
@@ -49,5 +52,6 @@
 
   public void setAttachments(Set<BinaryResource> attachments) {
     m_attachments = attachments;
+    setValueSet(true);
   }
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/tablefield/AbstractTableFieldData.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/tablefield/AbstractTableFieldData.java
index 6c28deb..1cac660 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/tablefield/AbstractTableFieldData.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/form/fields/tablefield/AbstractTableFieldData.java
@@ -20,12 +20,9 @@
 
   private ArrayList<Object[]> m_rowList = new ArrayList<Object[]>();
 
-  public AbstractTableFieldData() {
-  }
-
   @Override
-  protected void initConfig() {
-    super.initConfig();
+  public Class<?> getFieldStopClass() {
+    return AbstractTableFieldData.class;
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/model/DataModelUtility.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/model/DataModelUtility.java
index 9b580fb..9527817 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/model/DataModelUtility.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/data/model/DataModelUtility.java
@@ -280,7 +280,7 @@
     if (map == null || map.size() == 0) {
       return "";
     }
-    StringBuffer buf = new StringBuffer(16);
+    StringBuilder buf = new StringBuilder(16);
     for (Map.Entry<String, String> e : map.entrySet()) {
       buf.append(";");
       buf.append(e.getKey());
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUrlParameter.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUrlParameter.java
new file mode 100644
index 0000000..1019876
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUrlParameter.java
@@ -0,0 +1,19 @@
+package org.eclipse.scout.rt.shared.deeplink;
+
+public final class DeepLinkUrlParameter {
+
+  /**
+   * Name of the URL parameter which contains the deep-link path in the format
+   * <code>[handler name]-[handler data]</code>.
+   */
+  public final static String DEEP_LINK = "dl";
+
+  /**
+   * Name of the optional URL parameter which contains a human readable, informative text about the deep-link.
+   */
+  public final static String INFO = "i";
+
+  private DeepLinkUrlParameter() {
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUtility.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUtility.java
new file mode 100644
index 0000000..ddae860
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/deeplink/DeepLinkUtility.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+ * http://www.bsiag.com/
+ */
+package org.eclipse.scout.rt.shared.deeplink;
+
+import java.text.Normalizer;
+import java.text.Normalizer.Form;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+public final class DeepLinkUtility {
+
+  private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
+  private static final Pattern WHITESPACE = Pattern.compile("[\\s]");
+
+  private DeepLinkUtility() {
+  }
+
+  /**
+   * Slug implementation as proposed from Stackoverflow.
+   *
+   * @see http://stackoverflow.com/questions/1657193/java-code-library-for-generating-slugs-for-use-in-pretty-urls
+   */
+  public static String toSlug(String input) {
+    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
+    String normalized = Normalizer.normalize(nowhitespace, Form.NFD);
+    String slug = NONLATIN.matcher(normalized).replaceAll("");
+    return slug.toLowerCase(Locale.ENGLISH);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailAttachment.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailAttachment.java
index 439c8aa..8c8c072 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailAttachment.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailAttachment.java
@@ -11,6 +11,7 @@
 package org.eclipse.scout.rt.shared.mail;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Arrays;
 
 import javax.activation.DataSource;
@@ -59,8 +60,8 @@
 
   public byte[] getContent() {
     if (m_content == null) {
-      try {
-        m_content = IOUtility.getContent(m_dataSource.getInputStream());
+      try (InputStream in = m_dataSource.getInputStream()) {
+        m_content = IOUtility.readBytes(in);
       }
       catch (IOException e) {
         throw new ProcessingException("Failed to get content", e);
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailUtility.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailUtility.java
index e665404..07ba41d 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailUtility.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/mail/MailUtility.java
@@ -204,15 +204,16 @@
 
       if (plainTextPart instanceof MimePart) {
         MimePart mimePart = (MimePart) plainTextPart;
-        byte[] content = IOUtility.getContent(mimePart.getInputStream());
-        if (content != null) {
-          try {
-            text = new String(content, getCharacterEncodingOfMimePart(mimePart));
+        try (InputStream in = mimePart.getInputStream()) {
+          if (in != null) {
+            byte[] content = IOUtility.readBytes(in);
+            try {
+              text = new String(content, getCharacterEncodingOfMimePart(mimePart));
+            }
+            catch (UnsupportedEncodingException e) {
+              text = new String(content);
+            }
           }
-          catch (UnsupportedEncodingException e) {
-            text = new String(content);
-          }
-
         }
       }
     }
@@ -251,12 +252,12 @@
   }
 
   public static DataSource createDataSource(File file) {
-    try {
+    try (InputStream in = new FileInputStream(file)) {
       int indexDot = file.getName().lastIndexOf('.');
       if (indexDot > 0) {
         String fileName = file.getName();
         String ext = fileName.substring(indexDot + 1);
-        return createDataSource(new FileInputStream(file), fileName, ext);
+        return createDataSource(in, fileName, ext);
       }
       else {
         return null;
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/NotificationHandlerRegistry.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/NotificationHandlerRegistry.java
index bb438f6..6353b3d 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/NotificationHandlerRegistry.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/NotificationHandlerRegistry.java
@@ -26,11 +26,11 @@
 @ApplicationScoped
 public class NotificationHandlerRegistry {
   private static final Logger LOG = LoggerFactory.getLogger(NotificationHandlerRegistry.class);
-  private final TypeParameterBeanRegistry<INotificationHandler> m_registry = new TypeParameterBeanRegistry<>();
+  private final TypeParameterBeanRegistry<INotificationHandler> m_registry = new TypeParameterBeanRegistry<>(INotificationHandler.class);
 
   @PostConstruct
   protected void buildHandlerLinking() {
-    m_registry.registerBeans(INotificationHandler.class, BEANS.all(INotificationHandler.class));
+    m_registry.registerBeans(BEANS.all(INotificationHandler.class));
   }
 
   /**
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistry.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistry.java
index 3ede9ed..6df22d8 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistry.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/notification/TypeParameterBeanRegistry.java
@@ -1,124 +1,205 @@
 /*******************************************************************************
- * Copyright (c) 2010-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
+* Copyright (c) 2010-2015 BSI Business Systems Integration AG.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+*     BSI Business Systems Integration AG - initial API and implementation
+******************************************************************************/
 package org.eclipse.scout.rt.shared.notification;
 
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import org.eclipse.scout.rt.platform.util.Assertions;
+import org.eclipse.scout.rt.platform.index.AbstractMultiValuesIndex;
+import org.eclipse.scout.rt.platform.index.IMultiValueIndex;
+import org.eclipse.scout.rt.platform.index.IndexedStore;
+import org.eclipse.scout.rt.platform.util.IRegistrationHandle;
 import org.eclipse.scout.rt.platform.util.TypeCastUtility;
 
 /**
- * A registry for beans implementing an interface with one generic parameter type B&ltT&gt that allows querying beans
- * with a given parameter type.
- *
- * @param B
- *          bean type
+ * A registry for beans implementing an interface with one generic type parameter, and which allows to lookup beans by
+ * its generic parameter type.
  */
-public class TypeParameterBeanRegistry<B> {
+public class TypeParameterBeanRegistry<BEAN> {
 
-  private final Map<Class<?>, List<B>> m_typeParamToBeans = new LinkedHashMap<>();
-  protected final ReadWriteLock m_typeParamToBeansLock = new ReentrantReadWriteLock();
+  protected final ReadWriteLock m_lock = new ReentrantReadWriteLock();
 
-  private final Map<Class<?>, List<B>> m_typeParamSubclassToBeans = new LinkedHashMap<>();
-  protected final ReadWriteLock m_typeParamSubclassToBeansLock = new ReentrantReadWriteLock();
+  protected final Class<BEAN> m_beanType;
+
+  protected final IndexedStore<BeanRegistration<BEAN>> m_inventory = new IndexedStore<>();
+  protected final IMultiValueIndex<Class<?>, BeanRegistration<BEAN>> m_genericTypeIndex;
+  protected final Set<Class<?>> m_computedLookupTypes = Collections.synchronizedSet(new HashSet<Class<?>>());
+
+  public TypeParameterBeanRegistry(final Class<BEAN> beanType) {
+    m_beanType = beanType;
+
+    // Register the index to lookup beans by their generic parameter type, or by a super type of that generic parameter type.
+    m_genericTypeIndex = m_inventory.registerIndex(new AbstractMultiValuesIndex<Class<?>, BeanRegistration<BEAN>>() {
+
+      @Override
+      protected Set<Class<?>> calculateIndexesFor(final BeanRegistration<BEAN> beanRegistration) {
+        final Set<Class<?>> indexValues = new HashSet<>();
+        indexValues.add(beanRegistration.getGenericTypeParameter());
+        indexValues.addAll(beanRegistration.getLazyLookupSubTypes());
+        return indexValues;
+      }
+    });
+  }
 
   /**
-   * Register beans
+   * Registers the given beans.
    *
-   * @param definingInterface
-   *          interface B&ltT&gt with a type parameter used in this registry
-   * @param beans
-   *          beans to register
+   * @return A token representing the registration of the given beans. This token can later be used to unregister the
+   *         beans.
    */
-  public void registerBeans(Class<B> definingInterface, List<B> beans) {
-    m_typeParamToBeansLock.writeLock().lock();
-    try {
-      for (B b : beans) {
-        Class typeParam = TypeCastUtility.getGenericsParameterClass(b.getClass(), definingInterface);
-        List<B> handlerList = m_typeParamToBeans.get(typeParam);
-        if (handlerList == null) {
-          handlerList = new LinkedList<>();
-          m_typeParamToBeans.put(typeParam, handlerList);
+  public IRegistrationHandle registerBeans(final List<BEAN> beans) {
+    final List<IRegistrationHandle> registrations = new ArrayList<>();
+
+    for (final BEAN bean : beans) {
+      registrations.add(registerBean(bean));
+    }
+
+    return new IRegistrationHandle() {
+
+      @Override
+      public void dispose() {
+        for (final IRegistrationHandle registration : registrations) {
+          registration.dispose();
         }
-        handlerList.add(b);
       }
+    };
+  }
+
+  /**
+   * Registers the given bean.
+   *
+   * @return A token representing the registration of the given bean. This token can later be used to unregister the
+   *         bean.
+   */
+  public IRegistrationHandle registerBean(final BEAN bean) {
+    m_computedLookupTypes.clear();
+
+    m_lock.writeLock().lock();
+    try {
+      final Class genericParameterType = TypeCastUtility.getGenericsParameterClass(bean.getClass(), m_beanType);
+      final BeanRegistration<BEAN> beanRegistration = new BeanRegistration<>(bean, genericParameterType);
+
+      // Add the bean to the inventory. Thereby, the indexes are computed for that element.
+      m_inventory.add(beanRegistration);
+
+      return new IRegistrationHandle() {
+
+        @Override
+        public void dispose() {
+          m_inventory.remove(beanRegistration);
+        }
+      };
     }
     finally {
-      m_typeParamToBeansLock.writeLock().unlock();
+      m_lock.writeLock().unlock();
     }
   }
 
   /**
-   * Returns all beans B&ltT&gt in this registry with the given generic parameter type &ltT&gt or a supertype of the
-   * given generic parameter type.
+   * Returns all beans with the given generic type parameter, or which are declared with a super type of that parameter.
    * <p>
    * The beans are returned in the original order (see {@link #registerBeans(Class, List)}).
    * </p>
    *
-   * @param typeParamClass
-   *          generic parameter type, not <code>null</code>
+   * @param lookupType
+   *          generic parameter type, not <code>null</code>.
    */
-  public List<B> getBeans(Class<?> typeParamClass) {
-    List<B> beans = getCached(Assertions.assertNotNull(typeParamClass));
-    if (beans != null) {
-      return new ArrayList<>(beans);
-    }
-    else {
-      beans = findBeansForTypeParam(typeParamClass);
-      cacheTypeParamSubclass(typeParamClass, beans);
-      return new ArrayList<B>(beans);
-    }
-  }
+  public List<BEAN> getBeans(final Class<?> lookupType) {
+    updateLookupTypeHierarchyIndex(lookupType);
 
-  private List<B> getCached(Class<?> clazz) {
-    m_typeParamSubclassToBeansLock.readLock().lock();
+    m_lock.readLock().lock();
     try {
-      return m_typeParamSubclassToBeans.get(clazz);
-    }
-    finally {
-      m_typeParamSubclassToBeansLock.readLock().unlock();
-    }
-  }
-
-  protected List<B> findBeansForTypeParam(Class<?> typeParam) {
-    List<B> beans = new LinkedList<>();
-    m_typeParamToBeansLock.readLock().lock();
-    try {
-      for (Entry<Class<?>, List<B>> e : m_typeParamToBeans.entrySet()) {
-        if (e.getKey().isAssignableFrom(typeParam)) {
-          beans.addAll(e.getValue());
-        }
+      final List<BEAN> beans = new ArrayList<>();
+      for (final BeanRegistration<BEAN> registration : m_genericTypeIndex.get(lookupType)) {
+        beans.add(registration.getBean());
       }
       return beans;
     }
     finally {
-      m_typeParamToBeansLock.readLock().unlock();
+      m_lock.readLock().unlock();
     }
   }
 
-  private void cacheTypeParamSubclass(Class<?> clazz, List<B> beans) {
-    m_typeParamSubclassToBeansLock.writeLock().lock();
+  /**
+   * Registers the given lookup type with beans which have a generic type parameter that is a super type of the given
+   * lookup type.
+   * <p>
+   * This is done only the first time a lookup for that lookup type is done.
+   */
+  protected void updateLookupTypeHierarchyIndex(final Class<?> lookupType) {
+    if (m_computedLookupTypes.contains(lookupType)) {
+      return;
+    }
+
+    m_lock.writeLock().lock();
     try {
-      m_typeParamSubclassToBeans.put(clazz, beans);
+      if (m_computedLookupTypes.contains(lookupType)) {
+        return; // double checked locking
+      }
+
+      for (final BeanRegistration<BEAN> element : m_inventory.values()) {
+        if (element.getGenericTypeParameter().isAssignableFrom(lookupType)) {
+          element.registerLazyLookupSubType(lookupType);
+
+          // Replace the element in the inventory to update the index.
+          m_inventory.remove(element);
+          m_inventory.add(element);
+        }
+      }
+      m_computedLookupTypes.add(lookupType);
     }
     finally {
-      m_typeParamSubclassToBeansLock.writeLock().unlock();
+      m_lock.writeLock().unlock();
     }
   }
 
+  protected static class BeanRegistration<T> {
+
+    private final T m_bean;
+    private final Class<?> m_genericTypeParameter;
+
+    private final Set<Class<?>> m_lazyLookupSubTypes;
+
+    public BeanRegistration(final T bean, final Class<?> genericTypeParameter) {
+      m_bean = bean;
+      m_genericTypeParameter = genericTypeParameter;
+      m_lazyLookupSubTypes = new HashSet<>();
+    }
+
+    public void registerLazyLookupSubType(final Class<?> lookupType) {
+      m_lazyLookupSubTypes.add(lookupType);
+    }
+
+    public T getBean() {
+      return m_bean;
+    }
+
+    /**
+     * Returns the generic bean type.
+     */
+    public Class<?> getGenericTypeParameter() {
+      return m_genericTypeParameter;
+    }
+
+    /**
+     * Returns the sub-types of the bean's generic type parameter. Those sub types are only populated upon a bean lookup
+     * for such a sub type, and which is remembered to speed up subsequent lookups.
+     */
+    public Set<Class<?>> getLazyLookupSubTypes() {
+      return m_lazyLookupSubTypes;
+    }
+  }
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/calendar/RecurrencePattern.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/calendar/RecurrencePattern.java
index 6c79cf2..80037a9 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/calendar/RecurrencePattern.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/calendar/RecurrencePattern.java
@@ -641,7 +641,7 @@
 
   @Override
   public String toString() {
-    StringBuffer buf = new StringBuffer("Pattern[");
+    StringBuilder buf = new StringBuilder("Pattern[");
     buf.append("startTimeMinutes=" + m_startTimeMinutes + ",");
     buf.append("endTimeMinutes=" + m_endTimeMinutes + ",");
     buf.append("durationMinutes=" + m_durationMinutes + ",");
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CODES.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CODES.java
index b047afb..7439fd8 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CODES.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CODES.java
@@ -86,6 +86,7 @@
     return BEANS.get(ICodeService.class).reloadCodeTypes(types);
   }
 
+  @SuppressWarnings("deprecation")
   public static Collection<ICodeType<?, ?>> getAllCodeTypes(String classPrefix) {
     return BEANS.get(ICodeService.class).getAllCodeTypes(classPrefix);
   }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CodeService.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CodeService.java
index 2bc17bb..f43e090 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CodeService.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/CodeService.java
@@ -120,7 +120,7 @@
       return ct;
     }
     // populate code type cache
-    getAllCodeTypes("");
+    getAllCodeTypes();
     return findCodeTypeByIdInternal(id);
   }
 
@@ -253,6 +253,8 @@
     return getCodeTypes(types);
   }
 
+  @SuppressWarnings("deprecation")
+  @Deprecated
   @Override
   public Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses(String classPrefix) {
     final Set<Class<? extends ICodeType<?, ?>>> filteredClasses = new LinkedHashSet<>();
@@ -265,12 +267,22 @@
     return filteredClasses;
   }
 
+  @Override
   public Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses() {
     return BEANS.get(CodeTypeClassInventory.class).getClasses();
   }
 
   @Override
+  public List<ICodeType<?, ?>> getAllCodeTypes() {
+    Set<Class<? extends ICodeType<?, ?>>> allCodeTypeClasses = getAllCodeTypeClasses();
+    List<Class<? extends ICodeType<?, ?>>> list = CollectionUtility.arrayList(allCodeTypeClasses);
+    return getCodeTypes(list);
+  }
+
+  @SuppressWarnings("deprecation")
+  @Override
   @RemoteServiceAccessDenied
+  @Deprecated
   public List<ICodeType<?, ?>> getAllCodeTypes(String classPrefix) {
     Set<Class<? extends ICodeType<?, ?>>> allCodeTypeClasses = getAllCodeTypeClasses(classPrefix);
     List<Class<? extends ICodeType<?, ?>>> list = CollectionUtility.arrayList(allCodeTypeClasses);
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/ICodeService.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/ICodeService.java
index b4a6249..ddc30a3 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/ICodeService.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/code/ICodeService.java
@@ -55,9 +55,22 @@
 
   /**
    * @return all code type classes with classPrefix
+   * @deprecated use {@link #getAllCodeTypeClasses()}. Will be removed in Scout 7.
    */
+  @Deprecated
   Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses(String classPrefix);
 
+  /**
+   * @return all code type classes
+   */
+  Set<Class<? extends ICodeType<?, ?>>> getAllCodeTypeClasses();
+
+  /**
+   * @deprecated use {@link #getAllCodeTypes()}. Will be removed in Scout 7.
+   */
+  @Deprecated
   @RemoteServiceAccessDenied
   Collection<ICodeType<?, ?>> getAllCodeTypes(String classPrefix);
+
+  Collection<ICodeType<?, ?>> getAllCodeTypes();
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/context/SharedContextChangedNotification.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/context/SharedContextChangedNotification.java
index 43d61e9..c0ae380 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/context/SharedContextChangedNotification.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/context/SharedContextChangedNotification.java
@@ -27,7 +27,7 @@
 
   @Override
   public String toString() {
-    StringBuffer b = new StringBuffer(getClass().getSimpleName());
+    StringBuilder b = new StringBuilder(getClass().getSimpleName());
     b.append("[");
     b.append("]");
     return b.toString();
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/file/RemoteFile.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/file/RemoteFile.java
index 993f674..a14b2ad 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/file/RemoteFile.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/services/common/file/RemoteFile.java
@@ -298,6 +298,7 @@
     return new DecompressedInputStream(this);
   }
 
+  @SuppressWarnings("resource")
   public long/* crc */ writeData(File f) throws IOException {
     return writeData(new FileOutputStream(f));
   }
@@ -326,6 +327,13 @@
     return getCRC();
   }
 
+  /**
+   * Write data and close stream
+   *
+   * @param os
+   * @return
+   * @throws IOException
+   */
   public long/* crc */ writeData(OutputStream os) throws IOException {
     InputStream in = null;
     BufferedOutputStream out = null;
@@ -350,10 +358,25 @@
     return getCRC();
   }
 
+  /**
+   * Read data from file
+   *
+   * @param f
+   * @return
+   * @throws IOException
+   */
+  @SuppressWarnings("resource")
   public long/* crc */ readData(File f) throws IOException {
     return readData(new FileInputStream(f));
   }
 
+  /**
+   * Read data and close stream
+   *
+   * @param f
+   * @return
+   * @throws IOException
+   */
   public long/* crc */ readData(Reader r) throws IOException {
     Writer out = null;
     BufferedReader in = null;
@@ -379,10 +402,26 @@
     return getCRC();
   }
 
+  /**
+   * Read data and close stream
+   *
+   * @param is
+   * @return
+   * @throws IOException
+   */
   public long/* crc */ readData(InputStream is) throws IOException {
     return readData(is, 0, -1);
   }
 
+  /**
+   * Read data and close stream
+   *
+   * @param is
+   * @param startPosition
+   * @param maxReadSize
+   * @return
+   * @throws IOException
+   */
   public long/* crc */ readData(InputStream is, long startPosition, long maxReadSize) throws IOException {
     OutputStream out = null;
     BufferedInputStream in = null;
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/AbstractServiceTunnel.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/AbstractServiceTunnel.java
index fd19a71..d259284 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/AbstractServiceTunnel.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/AbstractServiceTunnel.java
@@ -14,10 +14,13 @@
 
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.context.RunMonitor;
-import org.eclipse.scout.rt.platform.exception.PlatformException;
 import org.eclipse.scout.rt.platform.exception.DefaultRuntimeExceptionTranslator;
+import org.eclipse.scout.rt.platform.exception.PlatformException;
 import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedException;
+import org.eclipse.scout.rt.shared.INode;
+import org.eclipse.scout.rt.shared.ISession;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,16 +35,15 @@
   }
 
   @Override
-  public Object invokeService(Class serviceInterfaceClass, Method operation, Object[] callerArgs) {
-    long t0 = System.nanoTime();
-    if (callerArgs == null) {
-      callerArgs = new Object[0];
-    }
+  public Object invokeService(Class<?> serviceInterfaceClass, Method operation, Object[] callerArgs) {
     LOG.debug("{}.{}({})", serviceInterfaceClass, operation, callerArgs);
+    ServiceTunnelRequest request = createRequest(serviceInterfaceClass, operation, callerArgs);
+    interceptRequest(request);
+    return invokeService(request);
+  }
 
-    ServiceUtility serviceUtility = BEANS.get(ServiceUtility.class);
-    Object[] serializableArgs = serviceUtility.filterHolderArguments(callerArgs);
-    ServiceTunnelRequest request = createServiceTunnelRequest(serviceInterfaceClass, operation, serializableArgs);
+  public Object invokeService(ServiceTunnelRequest request) {
+    long t0 = System.nanoTime();
     beforeTunnel(request);
     ServiceTunnelResponse response = tunnel(request);
     afterTunnel(t0, response);
@@ -53,8 +55,8 @@
       RuntimeException serviceException = interceptException(t);
       if (serviceException instanceof PlatformException) {
         ((PlatformException) serviceException)
-            .withContextInfo("remote-service.name", serviceInterfaceClass.getSimpleName())
-            .withContextInfo("remote-service.operation", operation.getName());
+            .withContextInfo("remote-service.name", request.getServiceInterfaceClassName())
+            .withContextInfo("remote-service.operation", request.getOperation());
       }
 
       // Combine local and remote stacktraces.
@@ -66,22 +68,31 @@
       serviceException.setStackTrace(both);
       throw serviceException;
     }
-    serviceUtility.updateHolderArguments(callerArgs, response.getOutVars(), false);
+    BEANS.get(ServiceUtility.class).updateHolderArguments(request.getArgs(), response.getOutVars(), false);
     return response.getData();
   }
 
-  protected ServiceTunnelRequest createServiceTunnelRequest(Class serviceInterfaceClass, Method operation, Object[] args) {
+  public ServiceTunnelRequest createRequest(Class<?> interfaceClass, Method operation, Object[] args) {
+    if (args == null) {
+      args = new Object[0];
+    }
+    Object[] serializableArgs = BEANS.get(ServiceUtility.class).filterHolderArguments(args);
+    return new ServiceTunnelRequest(interfaceClass.getName(), operation.getName(), operation.getParameterTypes(), serializableArgs);
+  }
+
+  protected void interceptRequest(ServiceTunnelRequest request) {
     UserAgent userAgent = UserAgent.CURRENT.get();
     if (userAgent == null) {
       LOG.warn("No UserAgent set on calling context; include default in service-request");
-      userAgent = UserAgent.createDefault();
+      userAgent = UserAgents.createDefault();
     }
+    request.setUserAgent(userAgent.createIdentifier());
 
-    // default implementation
-    ServiceTunnelRequest call = new ServiceTunnelRequest(serviceInterfaceClass.getName(), operation.getName(), operation.getParameterTypes(), args);
-    call.setUserAgent(userAgent.createIdentifier());
-
-    return call;
+    ISession session = ISession.CURRENT.get();
+    if (session != null) {
+      request.setSessionId(session.getId());
+    }
+    request.setClientNodeId(INode.ID);
   }
 
   /**
diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListener.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListener.java
similarity index 90%
rename from org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListener.java
rename to org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListener.java
index a0035b2..63a5ad6 100644
--- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/RegisterTunnelToServerPlatformListener.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/RegisterTunnelToServerPlatformListener.java
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.client;
+package org.eclipse.scout.rt.shared.servicetunnel;
 
 import java.util.List;
 
@@ -30,7 +30,7 @@
 import org.slf4j.LoggerFactory;
 
 /**
- * Platform listener that registers proxy instances for interfaces annotated with {@link TunnelToServer}.
+ * {@link IPlatformListener} to register proxy instances for interfaces annotated with {@link TunnelToServer}.
  */
 public class RegisterTunnelToServerPlatformListener implements IPlatformListener {
   private static final Logger LOG = LoggerFactory.getLogger(RegisterTunnelToServerPlatformListener.class);
@@ -38,7 +38,7 @@
   @Override
   public void stateChanged(PlatformEvent event) throws PlatformException {
     if (event.getState() == IPlatform.State.BeanManagerPrepared) {
-      if (!CONFIG.getPropertyValue(CreateTunnelToServerBeansProperty.class)) {
+      if (!isEnabled()) {
         return;
       }
       //register all tunnels to server
@@ -48,6 +48,10 @@
     }
   }
 
+  protected boolean isEnabled() {
+    return CONFIG.getPropertyValue(CreateTunnelToServerBeansProperty.class);
+  }
+
   protected void registerTunnelToServerProxies(final IBeanManager beanManager, final IClassInventory classInventory) {
     for (IClassInfo ci : classInventory.getKnownAnnotatedTypes(TunnelToServer.class)) {
       if (!ci.isInterface() || !ci.isPublic()) {
@@ -63,6 +67,7 @@
         LOG.warn("could not load class [{}]", ci.name(), e);
       }
     }
+    LOG.info("Tunnel to server proxies registered.");
   }
 
   protected void registerTunnelToServerProxy(final IBeanManager beanManager, Class<?> c) {
@@ -72,6 +77,7 @@
     }
 
     beanManager.registerBean(createBeanMetaData(c));
+    LOG.debug("Registered [{}}", c);
   }
 
   /**
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/ServiceTunnelRequest.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/ServiceTunnelRequest.java
index 2164609..bb33eeb 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/ServiceTunnelRequest.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/ServiceTunnelRequest.java
@@ -19,6 +19,7 @@
 import org.eclipse.scout.rt.platform.util.VerboseUtility;
 import org.eclipse.scout.rt.shared.services.common.context.IRunMonitorCancelService;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 
 @Bean
 public class ServiceTunnelRequest implements Serializable {
@@ -59,10 +60,17 @@
     return m_requestSequence;
   }
 
+  /**
+   * @return Session id or <code>null</code>, if not defined
+   */
   public String getSessionId() {
     return m_sessionId;
   }
 
+  /**
+   * @param sessionId
+   *          (<code>null</code>, if not defined)
+   */
   public void setSessionId(String sessionId) {
     m_sessionId = sessionId;
   }
@@ -92,7 +100,7 @@
 
   /**
    * Represents the user interface on client side.<br/>
-   * To parse an identifier use {@link UserAgent#createByIdentifier(String)}
+   * To parse an identifier use {@link UserAgents#createByIdentifier(String)}
    */
   public String getUserAgent() {
     return m_userAgent;
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/SoapServiceTunnelContentHandler.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/SoapServiceTunnelContentHandler.java
index 1b427fc..41fb1a5 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/SoapServiceTunnelContentHandler.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/SoapServiceTunnelContentHandler.java
@@ -279,6 +279,7 @@
     return (ServiceTunnelResponse) read(in);
   }
 
+  @SuppressWarnings("resource")
   protected Object/* msg */ read(InputStream in) throws Exception {
     if (LOG.isDebugEnabled()) {
       in = new DebugInputStream(in);
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/AbstractHttpServiceTunnel.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnel.java
similarity index 81%
rename from org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/AbstractHttpServiceTunnel.java
rename to org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnel.java
index 6714af5..efd90ea 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/AbstractHttpServiceTunnel.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/HttpServiceTunnel.java
@@ -21,7 +21,6 @@
 import javax.security.auth.Subject;
 
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.config.IConfigProperty;
 import org.eclipse.scout.rt.platform.context.CorrelationId;
 import org.eclipse.scout.rt.platform.context.RunContext;
 import org.eclipse.scout.rt.platform.context.RunContexts;
@@ -47,7 +46,7 @@
 /**
  * Abstract tunnel used to invoke a service through HTTP.
  */
-public abstract class AbstractHttpServiceTunnel extends AbstractServiceTunnel {
+public class HttpServiceTunnel extends AbstractServiceTunnel {
 
   public static final String TOKEN_AUTH_HTTP_HEADER = "X-ScoutAccessToken";
 
@@ -55,28 +54,23 @@
   private final URL m_serverUrl;
   private final boolean m_active;
 
-  public AbstractHttpServiceTunnel() {
+  public HttpServiceTunnel() {
     this(getConfiguredServerUrl());
   }
 
-  public AbstractHttpServiceTunnel(URL url) {
+  public HttpServiceTunnel(URL url) {
     m_serverUrl = url;
     m_active = url != null;
   }
 
   protected static URL getConfiguredServerUrl() {
-    IConfigProperty<String> targetUrlProperty = BEANS.get(ServiceTunnelTargetUrlProperty.class);
-    String url = targetUrlProperty.getValue();
-    if (StringUtility.hasText(url)) {
-      try {
-        URL targetUrl = UriUtility.toUrl(url);
-        return targetUrl;
-      }
-      catch (RuntimeException e) {
-        throw new IllegalArgumentException("targetUrl: " + url, e);
-      }
+    String url = BEANS.get(ServiceTunnelTargetUrlProperty.class).getValue();
+    try {
+      return UriUtility.toUrl(url);
     }
-    return null;
+    catch (RuntimeException e) {
+      throw new IllegalArgumentException("targetUrl: " + url, e);
+    }
   }
 
   @Override
@@ -211,46 +205,37 @@
   protected ServiceTunnelResponse tunnel(final ServiceTunnelRequest serviceRequest) {
     final long requestSequence = serviceRequest.getRequestSequence();
 
-    // RunContext to run the service call.
-    final RunContext executionContext = createCurrentRunContext();
-
     // Create the Callable to be given to the job manager for execution.
     final RemoteServiceInvocationCallable remoteInvocationCallable = createRemoteServiceInvocationCallable(serviceRequest);
 
     // Register the execution monitor as child monitor of the current monitor so that the service request is cancelled once the current monitor gets cancelled.
-    RunMonitor.CURRENT.get().registerCancellable(executionContext.getRunMonitor());
-
     // Invoke the service operation asynchronously (to enable cancellation) and wait until completed or cancelled.
-    IFuture<ServiceTunnelResponse> future = null;
-    try {
-      future = Jobs.schedule(remoteInvocationCallable, Jobs.newInput()
-          .withRunContext(executionContext.copy())
-          .withName(createServiceRequestName(requestSequence))
-          .withExceptionHandling(null, false)) // do not handle uncaught exceptions because typically invoked from within a model job (might cause a deadlock, because ClientExceptionHandler schedules and waits for a model job to visualize the exception).
-          .whenDone(new IDoneHandler<ServiceTunnelResponse>() {
+    final IFuture<ServiceTunnelResponse> future = Jobs
+        .schedule(remoteInvocationCallable,
+            Jobs.newInput().withRunContext(createRunContext())
+                .withName(createServiceRequestName(requestSequence))
+                .withExceptionHandling(null, false)) // do not handle uncaught exceptions because typically invoked from within a model job (might cause a deadlock, because ClientExceptionHandler schedules and waits for a model job to visualize the exception).
+        .whenDone(new IDoneHandler<ServiceTunnelResponse>() {
 
-            @Override
-            public void onDone(DoneEvent<ServiceTunnelResponse> event) {
-              if (event.isCancelled()) {
-                remoteInvocationCallable.cancel(executionContext.copy()
-                    .withRunMonitor(BEANS.get(RunMonitor.class))); // separate monitor to not cancel this cancellation action.
-              }
+          @Override
+          public void onDone(DoneEvent<ServiceTunnelResponse> event) {
+            if (event.isCancelled()) {
+              remoteInvocationCallable.cancel();
             }
-          }, null);
+          }
+        }, createRunContext()
+            .withRunMonitor(BEANS.get(RunMonitor.class))); // separate monitor to not cancel this cancellation action.
+
+    try {
       return future.awaitDoneAndGet();
     }
     catch (ThreadInterruptedException e) {
-      if (future != null) {
-        future.cancel(true); // Ensure the monitor to be cancelled once this thread is interrupted to cancel the remote call.
-      }
+      future.cancel(true); // Ensure the monitor to be cancelled once this thread is interrupted to cancel the remote call.
       return new ServiceTunnelResponse(new ThreadInterruptedException(ScoutTexts.get("UserInterrupted"))); // Interruption has precedence over computation result or computation error.
     }
     catch (FutureCancelledException e) {
       return new ServiceTunnelResponse(new ThreadInterruptedException(ScoutTexts.get("UserInterrupted"))); // Cancellation has precedence over computation result or computation error.
     }
-    catch (final RuntimeException e) {
-      return new ServiceTunnelResponse(e);
-    }
   }
 
   /**
@@ -261,13 +246,6 @@
   }
 
   /**
-   * @return a copy of the current calling context to be used to invoke the remote service operation.
-   */
-  protected RunContext createCurrentRunContext() {
-    return RunContexts.copyCurrent();
-  }
-
-  /**
    * Returns the name to decorate the thread's name while executing the service request.
    */
   protected String createServiceRequestName(final long requestSequence) {
@@ -275,4 +253,9 @@
     final String submitter = (currentFuture != null ? currentFuture.getJobInput().getName() : Thread.currentThread().getName());
     return String.format("Tunneling service request [seq=%s, submitter=%s]", requestSequence, submitter);
   }
+
+  public RunContext createRunContext() {
+    return RunContexts.copyCurrent();
+  }
+
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/RemoteServiceInvocationCallable.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/RemoteServiceInvocationCallable.java
index f6e6aff..1a91502 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/RemoteServiceInvocationCallable.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/servicetunnel/http/RemoteServiceInvocationCallable.java
@@ -18,11 +18,9 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
-import org.eclipse.scout.rt.platform.context.RunContext;
 import org.eclipse.scout.rt.platform.context.RunMonitor;
 import org.eclipse.scout.rt.platform.util.concurrent.FutureCancelledException;
 import org.eclipse.scout.rt.platform.util.concurrent.ICancellable;
-import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
 import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedException;
 import org.eclipse.scout.rt.shared.services.common.context.IRunMonitorCancelService;
 import org.eclipse.scout.rt.shared.servicetunnel.HttpException;
@@ -45,10 +43,10 @@
 
   private static final Logger LOG = LoggerFactory.getLogger(RemoteServiceInvocationCallable.class);
 
-  private final AbstractHttpServiceTunnel m_tunnel;
+  private final HttpServiceTunnel m_tunnel;
   private final ServiceTunnelRequest m_serviceRequest;
 
-  public RemoteServiceInvocationCallable(final AbstractHttpServiceTunnel tunnel, final ServiceTunnelRequest serviceRequest) {
+  public RemoteServiceInvocationCallable(final HttpServiceTunnel tunnel, final ServiceTunnelRequest serviceRequest) {
     m_tunnel = tunnel;
     m_serviceRequest = serviceRequest;
   }
@@ -96,23 +94,21 @@
   /**
    * Cancels the remote service operation on server side.
    */
-  public void cancel(final RunContext cancellationRunContext) {
-    cancellationRunContext.run(new IRunnable() {
-
-      @Override
-      public void run() throws Exception {
-        try {
-          final Method serviceMethod = IRunMonitorCancelService.class.getMethod(IRunMonitorCancelService.CANCEL_METHOD, long.class);
-          final Object[] serviceArgs = new Object[]{m_serviceRequest.getRequestSequence()};
-          m_tunnel.invokeService(IRunMonitorCancelService.class, serviceMethod, serviceArgs);
-        }
-        catch (final FutureCancelledException | ThreadInterruptedException e) {
-          // NOOP: Do not cancel 'cancel-request' to prevent loop.
-        }
-        catch (RuntimeException | NoSuchMethodException e) {
-          LOG.warn("Failed to cancel server processing [requestSequence={}]", m_serviceRequest.getRequestSequence(), e);
-        }
-      }
-    });
+  public void cancel() {
+    try {
+      final Method serviceMethod = IRunMonitorCancelService.class.getMethod(IRunMonitorCancelService.CANCEL_METHOD, long.class);
+      final Object[] serviceArgs = new Object[]{m_serviceRequest.getRequestSequence()};
+      ServiceTunnelRequest request = m_tunnel.createRequest(IRunMonitorCancelService.class, serviceMethod, serviceArgs);
+      request.setClientNodeId(m_serviceRequest.getClientNodeId());
+      request.setSessionId(m_serviceRequest.getSessionId());
+      request.setUserAgent(m_serviceRequest.getUserAgent());
+      m_tunnel.invokeService(request);
+    }
+    catch (final FutureCancelledException | ThreadInterruptedException e) {
+      // NOOP: Do not cancel 'cancel-request' to prevent loop.
+    }
+    catch (RuntimeException | NoSuchMethodException e) {
+      LOG.warn("Failed to cancel server processing [requestSequence={}]", m_serviceRequest.getRequestSequence(), e);
+    }
   }
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParser.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParser.java
index bd84567..b2bd69b 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParser.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/DefaultUserAgentParser.java
@@ -10,19 +10,24 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.shared.ui;
 
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.exception.PlatformException;
+import org.eclipse.scout.rt.platform.exception.PlatformExceptionTranslator;
 import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * This default parser is able to create a string representation (identifier) of {@link UserAgent} in the form of
- * uiLayer|uiDeviceType|uiDeviceId. It is also able to parse such a identifier and create a {@link UserAgent}.
+ * This default parser is able to create a string representation (identifier) of a {@link UserAgent}, as well as parse
+ * such a string representation. It has the following form:
  * <p>
- * Examples of identifiers:
+ * uiLayer|uiDeviceType|uiEngineType|uiSystem|uiDeviceId
+ * <p>
+ * Examples:
  * <ul>
- * <li>SWING|DESKTOP|Windows7</li>
- * <li>RAP|MOBILE|Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162
- * Safari/535.19</li
+ * <li>HTML|MOBILE|CHROME|WINDOWS|Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko)
+ * Chrome/18.0.1025.162 Safari/535.19</li>
+ * <li>UNKNOWN|UNKNOWN|UNKNOWN|UNKNOWN</li>
  * </ul>
  * </p>
  *
@@ -31,26 +36,29 @@
 public class DefaultUserAgentParser implements IUserAgentParser {
   private static final Logger LOG = LoggerFactory.getLogger(DefaultUserAgentParser.class);
 
-  public static String DELIMITER = "|";
+  public static final String DELIMITER = "|";
 
   @Override
   public UserAgent parseIdentifier(String userAgent) {
     String[] tokens = StringUtility.tokenize(userAgent, DELIMITER.charAt(0));
-    if (tokens.length != 3) {
-      LOG.warn("UserAgentIdentifier could not be parsed. Invalid number of tokens. UserAgent: {}", userAgent);
-      return UserAgent.createDefault();
+    if (tokens.length != 5) {
+      throw new PlatformException("Invalid number of tokens");
     }
 
     try {
-      IUiLayer uiLayer = UiLayer.createByIdentifier(tokens[0]);
-      IUiDeviceType uiDeviceType = UiDeviceType.createByIdentifier(tokens[1]);
-      String uiDeviceId = tokens[2];
-
-      return UserAgent.create(uiLayer, uiDeviceType, uiDeviceId);
+      return UserAgents
+          .create()
+          .withUiLayer(UiLayer.createByIdentifier(tokens[0]))
+          .withUiDeviceType(UiDeviceType.createByIdentifier(tokens[1]))
+          .withUiEngineType(UiEngineType.createByIdentifier(tokens[2]))
+          .withUiSystem(UiSystem.createByIdentifier(tokens[3]))
+          .withDeviceId(tokens[4])
+          .build();
     }
-    catch (Exception t) {
-      LOG.warn("UserAgentIdentifier could not be parsed. Exception occured while parsing. UserAgent: {}", userAgent, t);
-      return UserAgent.createDefault();
+    catch (IllegalArgumentException e) {
+      throw BEANS.get(PlatformExceptionTranslator.class)
+          .translate(e)
+          .withContextInfo("UserAgent", userAgent);
     }
   }
 
@@ -58,12 +66,15 @@
   public String createIdentifier(UserAgent userAgent) {
     String uiDeviceId = userAgent.getUiDeviceId();
     if (uiDeviceId.contains(DELIMITER)) {
-      uiDeviceId = uiDeviceId.replaceAll(DELIMITER, "_");
-
+      uiDeviceId = uiDeviceId.replaceAll("\\" + DELIMITER, "_");
       LOG.warn("Character which is used as delimiter has been found in uiDeviceId. Replaced with '_'. Old uiDeviceId: {}. New uiDeviceId: {}", userAgent.getUiDeviceId(), uiDeviceId);
-      userAgent.setUiDeviceId(uiDeviceId);
     }
-    return StringUtility.concatenateTokens(userAgent.getUiLayer().getIdentifier(), DELIMITER + "", userAgent.getUiDeviceType().getIdentifier(), DELIMITER + "", uiDeviceId);
+    return StringUtility.concatenateTokens(
+        userAgent.getUiLayer().getIdentifier(), DELIMITER,
+        userAgent.getUiDeviceType().getIdentifier(), DELIMITER,
+        userAgent.getUiEngineType().getIdentifier(), DELIMITER,
+        userAgent.getUiSystem().getIdentifier(), DELIMITER,
+        uiDeviceId);
   }
 
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiDeviceType.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiDeviceType.java
index a7fa4e1..974b3ac 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiDeviceType.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiDeviceType.java
@@ -16,7 +16,5 @@
  * @since 3.8.0
  */
 public interface IUiDeviceType extends Serializable {
-  boolean isTouchDevice();
-
   String getIdentifier();
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiEngineType.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiEngineType.java
new file mode 100644
index 0000000..bc2d1d4
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiEngineType.java
@@ -0,0 +1,17 @@
+package org.eclipse.scout.rt.shared.ui;
+
+import java.io.Serializable;
+
+/**
+ * Browser engine type
+ *
+ * @since 6.0.0
+ */
+public interface IUiEngineType extends Serializable {
+
+  /**
+   * @return unique id
+   */
+  String getIdentifier();
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiSystem.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiSystem.java
new file mode 100644
index 0000000..64de124
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUiSystem.java
@@ -0,0 +1,7 @@
+package org.eclipse.scout.rt.shared.ui;
+
+import java.io.Serializable;
+
+public interface IUiSystem extends Serializable {
+  String getIdentifier();
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUserAgentParser.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUserAgentParser.java
index 0a4e156..d403fe5 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUserAgentParser.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/IUserAgentParser.java
@@ -10,12 +10,15 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.shared.ui;
 
+import org.eclipse.scout.rt.platform.Bean;
+
 /**
  * Is able to create a string representation (identifier) of {@link UserAgent}. It is also able to parse a identifier
  * and create a {@link UserAgent}.
- * 
+ *
  * @since 3.8.0
  */
+@Bean
 public interface IUserAgentParser {
 
   UserAgent parseIdentifier(String userAgent);
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiDeviceType.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiDeviceType.java
index 37750f7..0b721aa 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiDeviceType.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiDeviceType.java
@@ -15,25 +15,10 @@
  */
 public enum UiDeviceType implements IUiDeviceType {
   DESKTOP,
-  TABLET(true),
-  MOBILE(true),
+  TABLET,
+  MOBILE,
   UNKNOWN;
 
-  boolean m_touchDevice;
-
-  private UiDeviceType(boolean touchDevice) {
-    m_touchDevice = touchDevice;
-  }
-
-  private UiDeviceType() {
-    this(false);
-  }
-
-  @Override
-  public boolean isTouchDevice() {
-    return m_touchDevice;
-  }
-
   @Override
   public String getIdentifier() {
     return name();
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiEngineType.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiEngineType.java
new file mode 100644
index 0000000..541fed7
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiEngineType.java
@@ -0,0 +1,25 @@
+package org.eclipse.scout.rt.shared.ui;
+
+/**
+ * @since 6.0
+ */
+public enum UiEngineType implements IUiEngineType {
+  ANDROID,
+  CHROME,
+  SAFARI,
+  FIREFOX,
+  IE,
+  OPERA,
+  KONQUEROR,
+  UNKNOWN;
+
+  @Override
+  public String getIdentifier() {
+    return name();
+  }
+
+  public static UiEngineType createByIdentifier(String identifier) {
+    return valueOf(identifier);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiLayer.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiLayer.java
index 37b3974..ad4be04 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiLayer.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiLayer.java
@@ -18,7 +18,7 @@
   HTML(true),
   UNKNOWN;
 
-  boolean m_webUi;
+  final boolean m_webUi;
 
   private UiLayer(boolean webUi) {
     m_webUi = webUi;
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiSystem.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiSystem.java
new file mode 100644
index 0000000..7718526
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UiSystem.java
@@ -0,0 +1,20 @@
+package org.eclipse.scout.rt.shared.ui;
+
+public enum UiSystem implements IUiSystem {
+  WINDOWS,
+  UNIX,
+  OSX,
+  IOS,
+  ANDROID,
+  UNKNOWN;
+
+  @Override
+  public String getIdentifier() {
+    return name();
+  }
+
+  public static UiSystem createByIdentifier(String identifier) {
+    return valueOf(identifier);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgent.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgent.java
index d34d76e..a45885e 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgent.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgent.java
@@ -12,19 +12,16 @@
 
 import java.io.Serializable;
 
-import org.eclipse.scout.rt.platform.config.ConfigUtility;
+import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.util.Assertions;
 
 /**
  * Holds information about the kind of user interface used on the client side like {@link IUiLayer} and
  * {@link IUiDeviceType}. <br/>
  * There is also a device id ({@link UserAgent#getUiDeviceId()} which holds even more information about the used device.
- * As default it only provides information about the underlying operation system. In case of a web based ui
- * {@link IUiLayer#isWebUi()} it provides the original user agent string containing information about the browser.
  * <p>
  * In order to export the user agent data as string you can use {@link #createIdentifier()} which uses
- * {@link DefaultUserAgentParser}. If you would like to export it in a custom format just create a custom
- * {@link IUserAgentParser} and call {@link #createIdentifier(IUserAgentParser)}.
+ * {@link IUserAgentParser}.
  * </p>
  *
  * @since 3.8.0
@@ -37,14 +34,21 @@
   public static final ThreadLocal<UserAgent> CURRENT = new ThreadLocal<>();
 
   private static final long serialVersionUID = 6194949468393137650L;
-  private String m_uiDeviceId;
-  private IUiLayer m_uiLayer;
-  private IUiDeviceType m_uiDeviceType;
 
-  private UserAgent(IUiLayer uiLayer, IUiDeviceType uiDeviceType, String uiDeviceId) {
+  private final IUiLayer m_uiLayer;
+  private final IUiDeviceType m_uiDeviceType;
+  private final IUiEngineType m_uiEngineType;
+  private final IUiSystem m_uiSystem;
+  private final String m_uiDeviceId;
+  private final boolean m_touch;
+
+  UserAgent(IUiLayer uiLayer, IUiDeviceType uiDeviceType, IUiEngineType uiEngineType, IUiSystem uiSystem, String uiDeviceId, boolean touch) {
     m_uiLayer = Assertions.assertNotNull(uiLayer, "UI Layer must not be null");
     m_uiDeviceType = Assertions.assertNotNull(uiDeviceType, "UI device type must not be null");
     m_uiDeviceId = Assertions.assertNotNull(uiDeviceId, "UI device id must not be null");
+    m_uiEngineType = Assertions.assertNotNull(uiEngineType, "UI engineType must not be null");
+    m_uiSystem = Assertions.assertNotNull(uiSystem, "UI system must not be null");
+    m_touch = touch;
   }
 
   public IUiDeviceType getUiDeviceType() {
@@ -55,39 +59,20 @@
     return m_uiLayer;
   }
 
+  public IUiEngineType getUiEngineType() {
+    return m_uiEngineType;
+  }
+
   public String getUiDeviceId() {
     return m_uiDeviceId;
   }
 
-  public void setUiDeviceId(String uiDeviceId) {
-    m_uiDeviceId = uiDeviceId;
+  public IUiSystem getUiSystem() {
+    return m_uiSystem;
   }
 
-  @Override
-  public boolean equals(Object other) {
-    if (other == this) {
-      return true;
-    }
-
-    if (other == null || other.getClass() != getClass()) {
-      return false;
-    }
-
-    UserAgent otherUserAgent = (UserAgent) other;
-    boolean equal = otherUserAgent.getUiDeviceType().equals(getUiDeviceType());
-    equal &= otherUserAgent.getUiLayer().equals(getUiLayer());
-    equal &= otherUserAgent.getUiDeviceId().equals(getUiDeviceId());
-
-    return equal;
-  }
-
-  @Override
-  public int hashCode() {
-    int hash = 17 + getUiLayer().hashCode();
-    hash = hash * 17 + getUiDeviceType().hashCode();
-    hash = hash * 17 + getUiDeviceId().hashCode();
-
-    return hash;
+  public boolean isTouch() {
+    return m_touch;
   }
 
   @Override
@@ -96,32 +81,61 @@
   }
 
   public String createIdentifier() {
-    return createIdentifier(new DefaultUserAgentParser());
+    return createIdentifier(BEANS.get(IUserAgentParser.class));
   }
 
   public String createIdentifier(IUserAgentParser parser) {
     return parser.createIdentifier(this);
   }
 
+  /**
+   * @deprecated use {@link UserAgents#create()}. will be removed in release 6.1;
+   */
+  @Deprecated
   public static UserAgent create(IUiLayer uiLayer, IUiDeviceType uiDeviceType) {
-    String osName = ConfigUtility.getProperty("os.name");
-    return new UserAgent(uiLayer, uiDeviceType, osName);
+    return UserAgents
+        .create()
+        .withUiLayer(uiLayer)
+        .withUiDeviceType(uiDeviceType)
+        .withDefaultDeviceId()
+        .build();
   }
 
+  /**
+   * @deprecated use {@link UserAgents#create()}. will be removed in release 6.1;
+   */
+  @Deprecated
   public static UserAgent create(IUiLayer uiLayer, IUiDeviceType uiDeviceType, String uiDeviceId) {
-    return new UserAgent(uiLayer, uiDeviceType, uiDeviceId);
+    return UserAgents
+        .create()
+        .withUiLayer(uiLayer)
+        .withUiDeviceType(uiDeviceType)
+        .withDeviceId(uiDeviceId)
+        .build();
   }
 
-  public static UserAgent createDefault() {
-    return create(UiLayer.UNKNOWN, UiDeviceType.UNKNOWN);
-  }
-
+  /**
+   * @deprecated use {@link UserAgents#createByIdentifier(IUserAgentParser, String)}. will be removed in release 6.1;
+   */
+  @Deprecated
   public static UserAgent createByIdentifier(IUserAgentParser parser, String userAgent) {
-    return parser.parseIdentifier(userAgent);
+    return UserAgents.createByIdentifier(parser, userAgent);
   }
 
+  /**
+   * @deprecated use {@link UserAgents#createByIdentifier(String)}. will be removed in release 6.1;
+   */
+  @Deprecated
   public static UserAgent createByIdentifier(String userAgent) {
-    return createByIdentifier(new DefaultUserAgentParser(), userAgent);
+    return UserAgents.createByIdentifier(userAgent);
+  }
+
+  /**
+   * @deprecated use {@link UserAgents#createDefault()}. will be removed in release 6.1;
+   */
+  @Deprecated
+  public static UserAgent createDefault() {
+    return UserAgents.createDefault();
   }
 
   /**
@@ -142,4 +156,76 @@
   public static UserAgent get() {
     return UserAgent.CURRENT.get();
   }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + (m_touch ? 1231 : 1237);
+    result = prime * result + ((m_uiDeviceId == null) ? 0 : m_uiDeviceId.hashCode());
+    result = prime * result + ((m_uiDeviceType == null) ? 0 : m_uiDeviceType.hashCode());
+    result = prime * result + ((m_uiEngineType == null) ? 0 : m_uiEngineType.hashCode());
+    result = prime * result + ((m_uiLayer == null) ? 0 : m_uiLayer.hashCode());
+    result = prime * result + ((m_uiSystem == null) ? 0 : m_uiSystem.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    UserAgent other = (UserAgent) obj;
+    if (m_touch != other.m_touch) {
+      return false;
+    }
+    if (m_uiDeviceId == null) {
+      if (other.m_uiDeviceId != null) {
+        return false;
+      }
+    }
+    else if (!m_uiDeviceId.equals(other.m_uiDeviceId)) {
+      return false;
+    }
+    if (m_uiDeviceType == null) {
+      if (other.m_uiDeviceType != null) {
+        return false;
+      }
+    }
+    else if (!m_uiDeviceType.equals(other.m_uiDeviceType)) {
+      return false;
+    }
+    if (m_uiEngineType == null) {
+      if (other.m_uiEngineType != null) {
+        return false;
+      }
+    }
+    else if (!m_uiEngineType.equals(other.m_uiEngineType)) {
+      return false;
+    }
+    if (m_uiLayer == null) {
+      if (other.m_uiLayer != null) {
+        return false;
+      }
+    }
+    else if (!m_uiLayer.equals(other.m_uiLayer)) {
+      return false;
+    }
+    if (m_uiSystem == null) {
+      if (other.m_uiSystem != null) {
+        return false;
+      }
+    }
+    else if (!m_uiSystem.equals(other.m_uiSystem)) {
+      return false;
+    }
+    return true;
+  }
+
 }
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgentUtility.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgentUtility.java
index b5c8c8b..877ff43 100644
--- a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgentUtility.java
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgentUtility.java
@@ -35,7 +35,7 @@
   }
 
   public static boolean isTouchDevice() {
-    return getCurrentUiDeviceType().isTouchDevice();
+    return getCurrentUserAgent().isTouch();
   }
 
   public static IUiDeviceType getCurrentUiDeviceType() {
@@ -53,7 +53,7 @@
     }
     else {
       LOG.warn("No UserAgent in calling context found; using default UserAgent");
-      return UserAgent.createDefault();
+      return UserAgents.createDefault();
     }
   }
 
diff --git a/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgents.java b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgents.java
new file mode 100644
index 0000000..845b722
--- /dev/null
+++ b/org.eclipse.scout.rt.shared/src/main/java/org/eclipse/scout/rt/shared/ui/UserAgents.java
@@ -0,0 +1,99 @@
+package org.eclipse.scout.rt.shared.ui;
+
+import org.eclipse.scout.rt.platform.BEANS;
+import org.eclipse.scout.rt.platform.config.ConfigUtility;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory methods for {@link UserAgent}
+ *
+ * @see UserAgent
+ * @since 6.0.0
+ */
+public final class UserAgents {
+  private static final Logger LOG = LoggerFactory.getLogger(UserAgents.class);
+
+  private IUiLayer m_uiLayer = UiLayer.UNKNOWN;
+  private IUiDeviceType m_uiDeviceType = UiDeviceType.UNKNOWN;
+  private IUiEngineType m_uiEngineType = UiEngineType.UNKNOWN;
+  private IUiSystem m_uiSystem = UiSystem.UNKNOWN;
+  private String m_uiDeviceId = "n/a";
+  private boolean m_touch = false;
+
+  private UserAgents() {
+  }
+
+  public UserAgents withUiDeviceType(IUiDeviceType uiDeviceType) {
+    m_uiDeviceType = uiDeviceType;
+    return this;
+  }
+
+  public UserAgents withUiEngineType(IUiEngineType uiEngineType) {
+    m_uiEngineType = uiEngineType;
+    return this;
+  }
+
+  public UserAgents withUiSystem(IUiSystem uiSystem) {
+    m_uiSystem = uiSystem;
+    return this;
+  }
+
+  public UserAgents withUiLayer(IUiLayer uiLayer) {
+    m_uiLayer = uiLayer;
+    return this;
+  }
+
+  public UserAgents withDeviceId(String uiDeviceId) {
+    m_uiDeviceId = uiDeviceId;
+    return this;
+  }
+
+  public UserAgents withDefaultDeviceId() {
+    return withDeviceId(ConfigUtility.getProperty("os.name"));
+  }
+
+  public UserAgents withTouch(boolean touch) {
+    m_touch = touch;
+    return this;
+  }
+
+  public static UserAgents create() {
+    return new UserAgents();
+  }
+
+  public static UserAgents create(UserAgent other) {
+    return new UserAgents()
+        .withUiDeviceType(other.getUiDeviceType())
+        .withUiEngineType(other.getUiEngineType())
+        .withUiLayer(other.getUiLayer())
+        .withUiSystem(other.getUiSystem())
+        .withDeviceId(other.getUiDeviceId())
+        .withTouch(other.isTouch());
+  }
+
+  public UserAgent build() {
+    return new UserAgent(m_uiLayer, m_uiDeviceType, m_uiEngineType, m_uiSystem, m_uiDeviceId, m_touch);
+  }
+
+  public static UserAgent createDefault() {
+    return create()
+        .withDefaultDeviceId()
+        .build();
+  }
+
+  public static UserAgent createByIdentifier(IUserAgentParser parser, String userAgent) {
+    try {
+      return parser.parseIdentifier(userAgent);
+    }
+    catch (RuntimeException e) {
+      LOG.error("UserAgentIdentifier could not be parsed. Exception occured while parsing. UserAgent: {}", userAgent, e);
+    }
+    return createDefault();
+  }
+
+  public static UserAgent createByIdentifier(String userAgent) {
+    return createByIdentifier(BEANS.get(IUserAgentParser.class), userAgent);
+  }
+
+}
diff --git a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts.properties b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts.properties
index 8f6a60c..2a9e90d 100644
--- a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts.properties
+++ b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts.properties
@@ -53,7 +53,9 @@
 CopyWidthsOfColumnsMenu=Copy column widths
 Criteria=Search criteria
 CustomColumAbbreviation=C
+DateIsNotAllowed=Date is not allowed
 Day=Day
+DeepLinkError=The page you requested is not available. The resource may have been removed. Check if the URL in the address bar is spelled correctly.
 DefaultPasswordPolicyText=The password does not comply with the given policy\n\nPolicy\:\n- at least 8 characters\n- at least one number (0-9)\n- at least one non standard character (\!|@|\#|\\$|%|\\^|&|\\*|\\(|\\)|_|\\+|\\||~|-|\n- not used in the past\n- your username can't be a part of the password
 DefaultSettings=Default settings
 DeleteBookmarkMenu=Delete bookmark
@@ -268,6 +270,7 @@
 Server=Server
 ShowColumns=Show columns
 SmartFieldCannotComplete=No suggestions for "{0}"
+SmartFieldInactiveRow=Result is inactive
 SmartFieldMoreThanXRows=More than {0} data records
 SmartFieldNoDataFound=No data available
 SmartFieldNotUnique=Multiple results for "{0}"
diff --git a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_de.properties b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_de.properties
index 24d4516..31ed0eb 100644
--- a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_de.properties
+++ b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_de.properties
@@ -53,7 +53,9 @@
 CopyWidthsOfColumnsMenu=Spaltenbreiten kopieren
 Criteria=Kriterien
 CustomColumAbbreviation=C
+DateIsNotAllowed=Unzul\u00E4ssiges Datum
 Day=Tag
+DeepLinkError=Die Seite kann nicht angezeigt werden. M\u00F6glicherweise ist die gew\u00FCnschte Ressource nicht mehr verf\u00FCgbar oder die URL in der Adresszeile ist nicht korrekt.
 DefaultPasswordPolicyText=Das Passwort entspricht nicht den vorgegebenen Richtlinien.\n\nRichtlinien\:\n- mind. 8 Zeichen\n- mind. eine Ziffer (0-9)\n- mind. ein Sonderzeichen (\!|@|\#|\\$|%|\\^|&|\\*|\\(|\\)|_|\\+|\\||~|-|\n- nicht schon in der Vergangenheit verwendet\n- der Benutzername darf kein Teil davon sein
 DefaultSettings=Werkseinstellungen
 DeleteBookmarkMenu=Favorit l\u00F6schen
@@ -268,6 +270,7 @@
 Server=Server
 ShowColumns=Spalten einblenden
 SmartFieldCannotComplete=Keine Vorschl\u00E4ge f\u00FCr "{0}" gefunden
+SmartFieldInactiveRow=Ergebnis ist inaktiv
 SmartFieldMoreThanXRows=Mehr als {0} Datens\u00E4tze
 SmartFieldNoDataFound=Keine Daten vorhanden
 SmartFieldNotUnique=Mehrere Resultate f\u00FCr "{0}"
diff --git a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_fr.properties b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_fr.properties
index a9c1b53..694071f 100644
--- a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_fr.properties
+++ b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_fr.properties
@@ -29,9 +29,11 @@
 ButtonSelectAll=S\u00E9lectionner tous
 Cancel=&Annuler
 CancelButton=&Annuler
+CancelShutdownAndReturnToTheApplication=Interrompt la mise en veille et retourne \u00E0 l'application
 ChangePassword=Changer le mot de passe
 CheckAll=Tout s\u00E9lectionner
 CheckAllWithMnemonic=&Tout s\u00E9lectionner
+Clipboard=Presse-papier
 Close=Fermer
 CloseButton=&Fermer
 Column=Colonne
@@ -44,12 +46,18 @@
 ComposerFieldAggregationMedian=M\u00E9dian({0})
 ComposerFieldAggregationMin=Minimum({0})
 ComposerFieldAggregationSum=Somme({0})
+Configurations=Configurations
 Configure=Configuration
 Copy=Copier
+CopyToClipboardFromFieldBelow=Veuillez copier le contenu du champ dans le presse-paier \u00E0 l'aide du menu contextuel ou de la combianison de touches.
 CopyWidthsOfColumnsMenu=Copier les largeurs des colonnes
 Criteria=Crit\u00E8res de recherche
+CustomColumAbbreviation=C
+DateIsNotAllowed=Date incorrecte
 Day=Jour
+DeepLinkError=La page demand\u00E9e n'est pas diponible. Il se peut que la ressource ait \u00E9t\u00E9 supprim\u00E9e ou que l'URL de la ligne d'adresse soit incorrecte.
 DefaultPasswordPolicyText=Le mot de passe ne r\u00E9pond pas aux r\u00E8gles\n\nR\u00E8gles\:\n- Au moins 8 caract\u00E8res\n- Au moins un nombre (0-9)\n- Au moins un caract\u00E8re non standard (\!|@|\#|$|%|^|&|*|(|)|_|+|||~|-|
+DefaultSettings=Param\u00E8tres d'usine
 DeleteBookmarkMenu=Supprimer le favori
 DeleteConfirmationText=Voulez-vous vraiment annuler?
 DeleteConfirmationTextNoItemList=Voulez-vous supprimer ces fichiers ?
@@ -62,6 +70,7 @@
 DetailedVersion=Version d\u00E9taill\u00E9e
 Details=D\u00E9tails
 EditBookmarkMenu=Modifier le favori...
+ElementsInserted=El\u00E9ments ins\u00E9r\u00E9s
 EmailCc=CC
 EmailFrom=De
 EmailSent=Envoy\u00E9
@@ -97,6 +106,8 @@
 FileNotFoundMessage=Le fichier suivant n'a pas \u00E9t\u00E9 trouv\u00E9\:\n{0}
 FileNotFoundTitle=Fichier introuvable
 FilesOfType=Type de fichier
+Filter=Filtre
+FilterAbbreviation=F
 FilterBookmarkTree=Rechercher dans les favoris
 Folders=Classeur
 FormClosing=Fermer
@@ -111,8 +122,10 @@
 FormStateStore=Enregistrer
 FormStateStoreAs=Enregistrer sous...
 FormattingLocale=Formatage
+FormsCannotBeSaved=Les formulaires suivants ne peuvent pas \u00EAtre enregistr\u00E9s, car ils se trouvent dans un statut non valide\:
 GlobalBookmarks=Favoris Globals
 GlobalBookmarksAddMenu=Ajouter aux favoris &globals
+GroupingAbbreviation=G
 Help=Aide
 History=Historique
 Host=Ordinateur h\u00F4te
@@ -136,6 +149,7 @@
 Key=Cl\u00E9
 KeyStroke=Combinaison de touches
 Language=Langue
+Load=Charger
 LoadFormXmlFailedText=Ce fichier ne provient pas de ce formue.
 LogicBetween=est entre {0} et {1}
 LogicBetweenShort=entre
@@ -194,11 +208,13 @@
 NetErrorText=Serveur introuvable
 NetErrorTitle=Erreur r\u00E9seau
 NetworkLatency=Ralentissement du r\u00E9seau
+New=Nouveau
 NewBookmarkFolderMenu=Nouveau dossier...
 NewPassword=Mot de passe nouveau
 No=Non
 NoButton=&Non
 None=Rien
+NotAllCheckedFormsCanBeSaved=Tous les formulaires s\u00E9lectionn\u00E9s n'ont pas pu \u00EAtre enregistr\u00E9s
 NumberOfRows=Nombre d'enregistrement
 NumberTooLargeMessageX=La valeur est trop grande; doit \u00EAtre inf\u00E9rieure \u00E0 {0}.
 NumberTooLargeMessageXY=La valeur est trop grande; doit se situer entre {0} et {1}.
@@ -224,28 +240,40 @@
 PasswordWillExpireHeaderX=Votre mot de passe expire {0}.
 PasswordWillExpireInfo=Souhaitez-vous le modifier maintenant ?
 PasswordsDoNotMatch=Les deux mots de passe ne correspondons pas.
+PasteClipboardContentsInFieldBelow=A l'aide du menu contextuel, de la combinaison de touches ou de Drag & Drop ins\u00E9rer les contenus de presse papier dans le champ ci-dessous.\nEn fonction de votre navigateur, textes, illustrations et fichiers peuvent \u00EAtre ins\u00E9r\u00E9s
 Path=Chemin
 Pending=Veuillez patienter\u0085
 PrivateBookmarks=Favoris priv\u00E9s
 Refresh=Actualiser
 Remove=Supprimer
+Rename=Renommer
 RenameBookmarkFolderMenu=Renommer le dossier...
 RepeatPassword=R\u00E9p\u00E9ter
 RequestProblem=Erreur d'emploi
 ResetButton=&R\u00E9initialiser
 ResetButtonTooltip=Transforme tout les formues en valeurs vide.
+ResetTableColumnFilter=Filtre
 ResetTableColumns=R\u00E9initialiser les colonnes
 Save=Enregistrer
 SaveButton=&Enregistrer
+SaveChangesOfSelectedItems=Enregistrer les modifications des \u00E9l\u00E9ments s\u00E9lectionn\u00E9s
+SaveCheckedFormsAndShutdown=Les \u00E9l\u00E9ments s\u00E9lectionn\u00E9s sont enregistr\u00E9s et l'application se termine.
+SavedSettings=Param\u00E8tres enregistr\u00E9s
+ScoutVersion=Version scout
 Search=Chercher
 SearchButton=&Recherche
 SearchConstraints=Contrainte de recherche
 SearchTextIsTooGeneral=Pr\u00E9ciser les crit\u00E8res de recherche
 SearchWasCanceled=La recherche a \u00E9t\u00E9 interrompue. Veuillez l'effectuer de nouveau.
+SeeLogFileForColumnWidthsOutput=Voir le fichier Log pour l'\u00E9dition des largeurs de colonnes
 SelectedStates=Uniquement marqu\u00E9s
 Server=Serveur
+ShowColumns=Afficher les colonnes
 SmartFieldCannotComplete=Aucune proposition pour \u201C{0}\u201C
+SmartFieldInactiveRow=R\u00E9sultat inactif
 SmartFieldMoreThanXRows=Plus de {0} sets de donn\u00E9es. Montre seulement {0}.
+SmartFieldNoDataFound=Donn\u00E9es non disponibles
+SmartFieldNotUnique=Plusieurs r\u00E9sultats pour "{0}"
 SmartFindLabel=Notation de recherche
 Source=Code source
 StatusExportDone=Exportation termin\u00E9e
@@ -254,12 +282,14 @@
 Subject=Concerne
 TableFilterConstraints=Filtres de tableau
 TableName=Table
+TableOrganize=Organiser le tableau
 Title=Titre
 Today=aujourd\u2019hui
 Tomorrow=demain
 TooManyRows=Quantit\u00E9 des donn\u00E9es volumineux. Limiter la recherche s.v.p.
 UncheckAll=Tout d\u00E9s\u00E9lectionner
 UncheckAllWithMnemonic=&Tout d\u00E9s\u00E9lectionner
+UnsavedChangesTitle=Enregistrer les modifications
 Update=Actualiser
 UpdateBookmarkMenu=Actualiser le favori dans la vue actuelle
 UserCancelledOperation=L\u2019op\u00E9ration a \u00E9t\u00E9 interrompue manuellement
diff --git a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_it.properties b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_it.properties
index 70e665d..a372ecb 100644
--- a/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_it.properties
+++ b/org.eclipse.scout.rt.shared/src/main/resources/org/eclipse/scout/rt/shared/texts/ScoutTexts_it.properties
@@ -33,6 +33,7 @@
 ChangePassword=Cambiare la password
 CheckAll=Seleziona tutti
 CheckAllWithMnemonic=&Seleziona tutti
+Clipboard=Appunti
 Close=Chiudere
 CloseButton=&Chiudere
 Column=Colonna
@@ -45,12 +46,18 @@
 ComposerFieldAggregationMedian=Media({0})
 ComposerFieldAggregationMin=Minimo({0})
 ComposerFieldAggregationSum=Somma({0})
+Configurations=Configurazioni
 Configure=Configurazione
 Copy=Copia
+CopyToClipboardFromFieldBelow=Si prega di copiare il contenuto del campo mediante il menu contestuale o con la combinazione di tasti.
 CopyWidthsOfColumnsMenu=Copia larghezza colonne
 Criteria=Criteri
+CustomColumAbbreviation=C
+DateIsNotAllowed=Dato non ammesso
 Day=Giorno
+DeepLinkError=Impossibile visualizzare la pagina. Probabilmente la risorsa non \u00E8 pi\u00F9 disponibile oppure l'URL nella riga dell'indirizzo non \u00E8 corretto.
 DefaultPasswordPolicyText=La password non corrisponde alle regole prestabilite\:\n\nRegole\:\n- almeno 8 caratteri\n- almeno un numero (0-9)\n- almeno un carattere speciale (\!|@|\#|\\$|%|\\^|&|\\*|\\(|\\)|_|\\+|\\||~|-|\n- non pu\u00F2 corrispondere una password utilizzata in precedenza\n- non pu\u00F2 comprendere il nome utente\n
+DefaultSettings=Impostazioni di default
 DeleteBookmarkMenu=Cancellare preferito
 DeleteConfirmationText=Volete eliminare questi dati?
 DeleteConfirmationTextNoItemList=Volete eliminare questi dati?
@@ -63,6 +70,7 @@
 DetailedVersion=Versione dettagliata
 Details=Dettagli
 EditBookmarkMenu=Elabora preferiti...
+ElementsInserted=Elementi inseriti.
 EmailCc=CC
 EmailFrom=Da
 EmailSent=Inviato
@@ -98,6 +106,8 @@
 FileNotFoundMessage=Il file seguente non \u00E8 stato trovato oppure l'accesso \u00E8 stato rifiutato\:\n{0}
 FileNotFoundTitle=File non trovato
 FilesOfType=Tipo di file
+Filter=Filtro
+FilterAbbreviation=F
 FilterBookmarkTree=Sfoglia preferiti
 Folders=Cartella
 FormClosing=Chiudere
@@ -112,9 +122,10 @@
 FormStateStore=Salva
 FormStateStoreAs=Salva con nome...
 FormattingLocale=Formattazione
-FormsCannotBeSaved=I seguenti form non possono essere salvati perch\u00E8 lo stato \u00E8 invalido\n\:
+FormsCannotBeSaved=I seguenti moduli non possono essere salvati perch\u00E9 il loro stato non \u00E8 valido\:
 GlobalBookmarks=Preferiti globali
 GlobalBookmarksAddMenu=Aggiungere a preferiti &globali
+GroupingAbbreviation=G
 Help=Aiuto
 History=Cronologia
 Host=Host
@@ -138,6 +149,7 @@
 Key=Chiave
 KeyStroke=Combinazioni di tasti
 Language=Lingua
+Load=Carica
 LoadFormXmlFailedText=Questo file non \u00E8 compatibile con il form corrente.
 LogicBetween=\u00E8 tra {0} e {1}
 LogicBetweenShort=tra
@@ -196,12 +208,13 @@
 NetErrorText=Server non trovato
 NetErrorTitle=Errore rete
 NetworkLatency=Ritardo rete
+New=Nuovo
 NewBookmarkFolderMenu=Nuova cartella\u2026
 NewPassword=Nuova password
 No=No
 NoButton=&No
 None=Niente
-NotAllCheckedFormsCanBeSaved=Non tutte le form selezionate possono essere salvate
+NotAllCheckedFormsCanBeSaved=Non tutti i moduli selezionati possono essere salvati
 NumberOfRows=Numero record di dati
 NumberTooLargeMessageX=Valore troppo elevato; deve essere inferiore a {0}.
 NumberTooLargeMessageXY=Valore troppo elevato; deve essere compreso tra {0} e {1}.
@@ -227,11 +240,13 @@
 PasswordWillExpireHeaderX=La password scadr\u00E0 tra {0}.
 PasswordWillExpireInfo=Volete cambiarla ora?
 PasswordsDoNotMatch=Le due password non corrispondono.
+PasteClipboardContentsInFieldBelow=Si prega di inserire i contenuti degli appunti nel campo sottostante mediante il menu contestuale, con la combinazione di tasti o per drag'n'drop.\nSecondo il browser, possono essere inseriti testi, immagini e file.
 Path=Percorso
 Pending=In attesa\u0085
 PrivateBookmarks=Preferito privato
 Refresh=Aggiornare
 Remove=Rimuovere
+Rename=Rinomina
 RenameBookmarkFolderMenu=Rinomina cartelle\u2026
 RepeatPassword=Ripeti
 RequestProblem=Errore di elaborazione
@@ -241,17 +256,24 @@
 ResetTableColumns=Azzera le colonne
 Save=Salva
 SaveButton=&Salva
-SaveChangesOfSelectedItems=Salvataggio modifiche su elementi selezionati
-SaveCheckedFormsAndShutdown=Salvataggio elementi selezionati e successiva chiusura.
+SaveChangesOfSelectedItems=Salva modifiche su elementi selezionati
+SaveCheckedFormsAndShutdown=Salvataggio elementi selezionati e successiva chiusura dell'applicazione.
+SavedSettings=Impostazioni salvate
+ScoutVersion=Versione Scout
 Search=Ricerca
 SearchButton=&Cerca
 SearchConstraints=Condizione di ricerca
 SearchTextIsTooGeneral=Specificare i criteri di ricerca
 SearchWasCanceled=Ricerca interrotta. Si prega di eseguirla ancora.
+SeeLogFileForColumnWidthsOutput=Vedi file log per l'output delle larghezze colonne.
 SelectedStates=Soltanto selezionati
 Server=Server
+ShowColumns=Apri colonne
 SmartFieldCannotComplete=Nessuna proposta per "{0}"
+SmartFieldInactiveRow=Risultato inattivo
 SmartFieldMoreThanXRows=Pi\u00F9 di {0} record.
+SmartFieldNoDataFound=Nessun dato disponibile
+SmartFieldNotUnique=Risultati multipli per "{0}"
 SmartFindLabel=Testo di ricerca
 Source=Codice sorgente
 StatusExportDone=Esportazione completata
@@ -260,13 +282,14 @@
 Subject=Oggetto
 TableFilterConstraints=Filtri di tabella
 TableName=Tabella
+TableOrganize=Organizza tabella
 Title=Titolo
 Today=oggi
 Tomorrow=domani
 TooManyRows=Quantit\u00E0 di dati troppo vasta. Limitare la ricerca.
 UncheckAll=Deseleziona tutti
 UncheckAllWithMnemonic=&Deseleziona tutti
-UnsavedChangesTitle=Modifiche Non Salvate
+UnsavedChangesTitle=Modifiche non salvate
 Update=Aggiorna
 UpdateBookmarkMenu=Aggiornamento preferiti da vista corrente
 UserCancelledOperation=L\u2019operazione \u00E8 stata interrotta manualmente
diff --git a/org.eclipse.scout.rt.svg.client.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.svg.client.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.svg.client.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.svg.client.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.svg.client.test/pom.xml b/org.eclipse.scout.rt.svg.client.test/pom.xml
index 282ef7c..ad2ee62 100644
--- a/org.eclipse.scout.rt.svg.client.test/pom.xml
+++ b/org.eclipse.scout.rt.svg.client.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.svg.client/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.svg.client/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.svg.client/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.svg.client/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.svg.client/pom.xml b/org.eclipse.scout.rt.svg.client/pom.xml
index e1e6ff8..86dec21 100644
--- a/org.eclipse.scout.rt.svg.client/pom.xml
+++ b/org.eclipse.scout.rt.svg.client/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.svg.ui.html/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.svg.ui.html/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.svg.ui.html/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.svg.ui.html/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.svg.ui.html/pom.xml b/org.eclipse.scout.rt.svg.ui.html/pom.xml
index c0f1fea..bdbf31f 100644
--- a/org.eclipse.scout.rt.svg.ui.html/pom.xml
+++ b/org.eclipse.scout.rt.svg.ui.html/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.svg.ui.html/src/main/js/scout/svg/SvgField.js b/org.eclipse.scout.rt.svg.ui.html/src/main/js/scout/svg/SvgField.js
index ef5df99..7a04bed 100644
--- a/org.eclipse.scout.rt.svg.ui.html/src/main/js/scout/svg/SvgField.js
+++ b/org.eclipse.scout.rt.svg.ui.html/src/main/js/scout/svg/SvgField.js
@@ -19,7 +19,7 @@
   this.addField($parent.makeDiv());
   this.addMandatoryIndicator();
   this.addStatus();
-  this.loadingSupport = new scout.DefaultFieldLoadingSupport(this);
+  this.loadingSupport = new scout.DefaultFieldLoadingSupport({field: this});
 };
 
 scout.SvgField.prototype._renderProperties = function() {
diff --git a/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.css b/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.css
index b63d505..9c42a60 100644
--- a/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.css
+++ b/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.css
@@ -1,11 +1,9 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
+/*!
+* Eclipse Scout SVG
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
 //@include("scout/svg/SvgField.css")
diff --git a/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.js b/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.js
index 599d654..7916c85 100644
--- a/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.js
+++ b/org.eclipse.scout.rt.svg.ui.html/src/main/js/svg-module.js
@@ -1,11 +1,11 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-__include("scout/svg/SvgField.js");
+/*!
+* Eclipse Scout SVG
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
+(function(scout, $, undefined) {
+  __include("scout/svg/SvgField.js");
+}(scout, jQuery));
diff --git a/org.eclipse.scout.rt.team-project-set/scoutRT.psf b/org.eclipse.scout.rt.team-project-set/scoutRT.psf
index ae7deb2..aad6f21 100644
--- a/org.eclipse.scout.rt.team-project-set/scoutRT.psf
+++ b/org.eclipse.scout.rt.team-project-set/scoutRT.psf
@@ -19,7 +19,6 @@
 <item elementID="=org.eclipse.scout.rt.serverbridge" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 </workingSets>
 <workingSets editPageId="org.eclipse.jdt.ui.JavaWorkingSetPage" id="1375704042674_2" label="scout.rt.client" name="scout.rt.client">
-<item elementID="=org.eclipse.scout.rt.client.mobile.test" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.svg.ui.html" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.ui.html.scriptprocessor.test" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.svg.client.test" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
@@ -27,7 +26,6 @@
 <item elementID="=org.eclipse.scout.rt.svg.client" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.ui.html.scriptprocessor" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.client" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
-<item elementID="=org.eclipse.scout.rt.client.mobile" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.client.test" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 <item elementID="=org.eclipse.scout.rt.ui.html" factoryID="org.eclipse.jdt.ui.PersistableJavaElementFactory"/>
 </workingSets>
diff --git a/org.eclipse.scout.rt.ui.html.scriptprocessor.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.ui.html.scriptprocessor.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.ui.html.scriptprocessor.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.ui.html.scriptprocessor.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.ui.html.scriptprocessor.test/pom.xml b/org.eclipse.scout.rt.ui.html.scriptprocessor.test/pom.xml
index fe8ca70..e795a27 100644
--- a/org.eclipse.scout.rt.ui.html.scriptprocessor.test/pom.xml
+++ b/org.eclipse.scout.rt.ui.html.scriptprocessor.test/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.ui.html.scriptprocessor/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.ui.html.scriptprocessor/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.ui.html.scriptprocessor/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.ui.html.scriptprocessor/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.ui.html.scriptprocessor/pom.xml b/org.eclipse.scout.rt.ui.html.scriptprocessor/pom.xml
index dd0ddd6..b4db93c 100644
--- a/org.eclipse.scout.rt.ui.html.scriptprocessor/pom.xml
+++ b/org.eclipse.scout.rt.ui.html.scriptprocessor/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
diff --git a/org.eclipse.scout.rt.ui.html.scriptprocessor/src/main/java/org/eclipse/scout/rt/ui/html/scriptprocessor/internal/loader/ScoutClasspathResourceLoader.java b/org.eclipse.scout.rt.ui.html.scriptprocessor/src/main/java/org/eclipse/scout/rt/ui/html/scriptprocessor/internal/loader/ScoutClasspathResourceLoader.java
index 18d279b..58fdaf1 100644
--- a/org.eclipse.scout.rt.ui.html.scriptprocessor/src/main/java/org/eclipse/scout/rt/ui/html/scriptprocessor/internal/loader/ScoutClasspathResourceLoader.java
+++ b/org.eclipse.scout.rt.ui.html.scriptprocessor/src/main/java/org/eclipse/scout/rt/ui/html/scriptprocessor/internal/loader/ScoutClasspathResourceLoader.java
@@ -50,22 +50,22 @@
     throw new IOException("No such file " + resource);
   }
 
+  @SuppressWarnings("resource")
   private String load(String resourcePath, String charset) throws IOException {
     if (resourcePath != null) {
       InputStream is = openStream(resourcePath);
       if (is != null) {
-        String readStream = readStream(is, charset);
-        return readStream;
+        return readStream(is, charset);
       }
     }
     return null;
   }
 
   private boolean exists(String resourcePath) throws IOException {
-    InputStream stream = openStream(resourcePath);
-    if (stream != null) {
-      stream.close();
-      return true;
+    try (InputStream stream = openStream(resourcePath)) {
+      if (stream != null) {
+        return true;
+      }
     }
     return false;
   }
diff --git a/org.eclipse.scout.rt.ui.html.test/.classpath b/org.eclipse.scout.rt.ui.html.test/.classpath
index b2acffc..5684d43 100644
--- a/org.eclipse.scout.rt.ui.html.test/.classpath
+++ b/org.eclipse.scout.rt.ui.html.test/.classpath
@@ -1,31 +1,43 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
+  <classpathentry excluding="**" including="**/*.java" kind="src" output="target/classes" path="src/main/js">
+    <attributes>
+      <attribute name="optional" value="true"/>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="src" output="target/classes" path="src/main/java">
+    <attributes>
+      <attribute name="optional" value="true"/>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+    <attributes>
+      <attribute name="optional" value="true"/>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+    <attributes>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/js">
+    <attributes>
+      <attribute name="optional" value="true"/>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+    <attributes>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+    <attributes>
+      <attribute name="maven.pomderived" value="true"/>
+    </attributes>
+  </classpathentry>
+  <classpathentry kind="output" path="target/classes"/>
 </classpath>
diff --git a/org.eclipse.scout.rt.ui.html.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.ui.html.test/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.ui.html.test/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.ui.html.test/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git "a/org.eclipse.scout.rt.ui.html.test/Html UI Java Tests \133skip jandex rebuild\135.launch" "b/org.eclipse.scout.rt.ui.html.test/Html UI Java Tests \133skip jandex rebuild\135.launch"
deleted file mode 100644
index 22f1379..0000000
--- "a/org.eclipse.scout.rt.ui.html.test/Html UI Java Tests \133skip jandex rebuild\135.launch"
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.scout.rt.ui.html.test"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="4"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.scout.rt.ui.html.test"/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
-<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.MAIN_TYPE" value=""/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.scout.rt.ui.html.test"/>
-<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
-</launchConfiguration>
diff --git a/org.eclipse.scout.rt.ui.html.test/Html UI Tests.launch "b/org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html build tests.launch"
similarity index 92%
rename from org.eclipse.scout.rt.ui.html.test/Html UI Tests.launch
rename to "org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html build tests.launch"
index fb266b3..84cb28d 100644
--- a/org.eclipse.scout.rt.ui.html.test/Html UI Tests.launch
+++ "b/org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html build tests.launch"
@@ -12,5 +12,5 @@
 <booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/>
 <stringAttribute key="M2_USER_SETTINGS" value=""/>
 <booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false"/>
-<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/org.eclipse.scout.rt.ui.html.parent}"/>
+<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/org.eclipse.scout.rt.ui.html.test}"/>
 </launchConfiguration>
diff --git a/org.eclipse.scout.rt.ui.html.test/Html UI Jasmine Server.launch "b/org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html jasmine server.launch"
similarity index 93%
rename from org.eclipse.scout.rt.ui.html.test/Html UI Jasmine Server.launch
rename to "org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html jasmine server.launch"
index 88d81a1..3491643 100644
--- a/org.eclipse.scout.rt.ui.html.test/Html UI Jasmine Server.launch
+++ "b/org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html jasmine server.launch"
@@ -13,5 +13,5 @@
 <stringAttribute key="M2_USER_SETTINGS" value=""/>
 <booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false"/>
 <stringAttribute key="bad_container_name" value="jasmine.server"/>
-<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/org.eclipse.scout.rt.ui.html}"/>
+<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/org.eclipse.scout.rt.ui.html.test}"/>
 </launchConfiguration>
diff --git a/org.eclipse.scout.rt.ui.html.test/Html UI Java Tests.launch "b/org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html test.launch"
similarity index 100%
rename from org.eclipse.scout.rt.ui.html.test/Html UI Java Tests.launch
rename to "org.eclipse.scout.rt.ui.html.test/\133org.eclipse.scout\135 ui-html test.launch"
diff --git a/org.eclipse.scout.rt.ui.html.test/pom.xml b/org.eclipse.scout.rt.ui.html.test/pom.xml
index cb09e29..26ecf05 100644
--- a/org.eclipse.scout.rt.ui.html.test/pom.xml
+++ b/org.eclipse.scout.rt.ui.html.test/pom.xml
@@ -1,23 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    Copyright (c) 2014-2015 BSI Business Systems Integration AG.
-    All rights reserved. This program and the accompanying materials
-    are made available under the terms of the Eclipse Public License v1.0
-    which accompanies this distribution, and is available at
-    http://www.eclipse.org/legal/epl-v10.html
-
-    Contributors:
-        BSI Business Systems Integration AG - initial API and implementation
-
--->
-<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">
+<!-- Copyright (c) 2014-2015 BSI Business Systems Integration AG. All rights
+  reserved. This program and the accompanying materials are made available
+  under the terms of the Eclipse Public License v1.0 which accompanies this
+  distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+  Contributors: BSI Business Systems Integration AG - initial API and implementation -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
@@ -27,6 +21,8 @@
 
   <properties>
     <scout.script.version>5.0.0</scout.script.version>
+    <sonar.sources>src/main,pom.xml</sonar.sources>
+    <sonar.tests>src/test</sonar.tests>
   </properties>
 
   <dependencies>
@@ -56,6 +52,53 @@
     </dependency>
   </dependencies>
 
+  <build>
+
+    <plugins>
+
+      <plugin>
+        <!-- Loads phantomjs executable, necessary for jasmine plugin -->
+        <groupId>com.github.klieber</groupId>
+        <artifactId>phantomjs-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>install</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+
+
+      <!-- JS testing with Jasmine -->
+      <plugin>
+        <groupId>com.github.searls</groupId>
+        <artifactId>jasmine-maven-plugin</artifactId>
+        <configuration>
+          <additionalContexts>
+            <additionalContext>
+              <contextRoot>ext</contextRoot>
+              <directory>${project.basedir}/../org.eclipse.scout.rt.ui.html/src/main/resources/</directory>
+            </additionalContext>
+            <additionalContext>
+              <contextRoot>ext</contextRoot>
+              <directory>${project.basedir}/../org.eclipse.scout.rt.ui.html/src/main/js</directory>
+            </additionalContext>
+          </additionalContexts>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+    </plugins>
+  </build>
+
   <!-- primarily for license header generation -->
   <inceptionYear>2014</inceptionYear>
 </project>
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineMavenReporter.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineMavenReporter.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineMavenReporter.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineMavenReporter.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineScout.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineScout.js
similarity index 93%
rename from org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineScout.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineScout.js
index f660cdd..814165f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineScout.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineScout.js
@@ -9,7 +9,7 @@
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
 /* exported mostRecentJsonRequest  */
-/* global LocaleSpecHelper */
+/* global scout.LocaleSpecHelper */
 function mostRecentJsonRequest() {
   var req = jasmine.Ajax.requests.mostRecent();
   if (req) {
@@ -26,16 +26,26 @@
   options.portletPartId = options.portletPartId || '0';
   options.backgroundJobPollingEnabled = false;
   options.suppressErrors = true;
+  options.renderDesktop = scout.nvl(options.renderDesktop, true);
+
   session = new scout.Session($sandbox, options);
   // Simulate successful session initialization
   session.uiSessionId = '1.1';
   session.modelAdapterRegistry[session.uiSessionId] = session;
-  session.locale = new LocaleSpecHelper().createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
-  session.desktop = scout.create('Desktop', {
-    parent: session.rootAdapter
-  });
-  session._renderDesktop();
+  session.locale = new scout.LocaleSpecHelper().createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
 
+  var desktop = options.desktop || {};
+  desktop.navigationVisible = scout.nvl(desktop.navigationVisible, false);
+  desktop.headerVisible = scout.nvl(desktop.headerVisible, false);
+  desktop.benchVisible = scout.nvl(desktop.benchVisible, false);
+  desktop.parent = scout.nvl(desktop.parent, session.rootAdapter);
+  session.desktop = scout.create('Desktop', desktop);
+  if (options.renderDesktop) {
+    session._renderDesktop();
+  }
+
+  // Prevent exception when test window gets resized
+  $sandbox.window().off('resize', session.desktop._resizeHandler);
   return session;
 }
 
@@ -92,6 +102,17 @@
     .off('unload.' + session.uiSessionId);
 }
 
+/**
+ * Removes all open popups for the given session.
+ * May be used to make sure handlers get properly detached
+ */
+function removePopups(session) {
+  session.$entryPoint.children('.popup').each(function() {
+    var popup = scout.Widget.getWidgetFor($(this));
+    popup.remove();
+  });
+}
+
 function createPropertyChangeEvent(model, properties) {
   return {
     target: model.id,
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineScoutModuleUtil.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineScoutModuleUtil.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/jasmine/JasmineScoutModuleUtil.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/JasmineScoutModuleUtil.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jasmine/boot.ext.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/boot.ext.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/jasmine/boot.ext.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/jasmine/boot.ext.js
diff --git a/org.eclipse.scout.rt.ui.html.test/src/main/js/scout-test-module.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout-test-module.js
new file mode 100644
index 0000000..55d537a
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout-test-module.js
@@ -0,0 +1,16 @@
+  /*!
+   * Eclipse Scout
+   * https://eclipse.org/scout/
+   *
+   * Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+   * Released under the Eclipse Public License v1.0
+   * http://www.eclipse.org/legal/epl-v10.html
+   */
+  // protects $ and undefined from being redefined by another library
+  (function(scout, $, undefined) {
+    __include("scout/desktop/outline/OutlineSpecHelper.js");
+    __include("scout/form/FormSpecHelper.js");
+    __include("scout/menu/MenuSpecHelper.js");
+    __include("scout/table/TableSpecHelper.js");
+    __include("scout/text/LocaleSpecHelper.js");
+  }(window.scout = window.scout || {}, jQuery));
diff --git a/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/desktop/outline/OutlineSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/desktop/outline/OutlineSpecHelper.js
new file mode 100644
index 0000000..860b38c
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/desktop/outline/OutlineSpecHelper.js
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.OutlineSpecHelper = function(session) {
+  this.session = session;
+};
+
+scout.OutlineSpecHelper.prototype.createModelFixture = function(nodeCount, depth, expanded) {
+  return this.createModel(this.createModelNodes(nodeCount, depth, expanded));
+};
+
+scout.OutlineSpecHelper.prototype.createModel = function(nodes) {
+  var model = createSimpleModel('Outline', this.session);
+
+  if (nodes) {
+    model.nodes = nodes;
+  }
+
+  return model;
+};
+
+scout.OutlineSpecHelper.prototype.createModelNode = function (id, text) {
+  return {
+    "id": id,
+    "text": text
+  };
+};
+
+scout.OutlineSpecHelper.prototype.createModelNodes = function (nodeCount, depth, expanded) {
+  return this.createModelNodesInternal(nodeCount, depth, expanded);
+};
+
+scout.OutlineSpecHelper.prototype.createModelNodesInternal = function(nodeCount, depth, expanded, parentNode) {
+  if (!nodeCount) {
+    return;
+  }
+
+  var nodes = [],
+    nodeId;
+  if (!depth) {
+    depth = 0;
+  }
+  for (var i = 0; i < nodeCount; i++) {
+    nodeId = i;
+    if (parentNode) {
+      nodeId = parentNode.id + '_' + nodeId;
+    }
+    nodes[i] = this.createModelNode(nodeId, 'node ' + i);
+    nodes[i].expanded = expanded;
+    if (depth > 0) {
+      nodes[i].childNodes = this.createModelNodesInternal(nodeCount, depth - 1, expanded, nodes[i]);
+    }
+  }
+  return nodes;
+};
+
+scout.OutlineSpecHelper.prototype.createOutline = function(model) {
+  var tree = new scout.Outline();
+  tree.init(model);
+  return tree;
+};
+
+/**
+ * Creates an outline with 3 nodes, the first node has a visible detail form
+ */
+scout.OutlineSpecHelper.prototype.createOutlineWithOneDetailForm = function() {
+  var model = this.createModelFixture(3, 2, true);
+  var outline = this.createOutline(model);
+  var node = model.nodes[0];
+  node.detailForm = new scout.FormSpecHelper(this.session).createFormWithOneField();
+  node.detailFormVisible = true;
+  return outline;
+};
+
+/**
+ * Creates an outline with 3 nodes, the first node has a visible detail table
+ */
+scout.OutlineSpecHelper.prototype.createOutlineWithOneDetailTable = function() {
+  var model = this.createModelFixture(3, 2, true);
+  var outline = this.createOutline(model);
+  var node = model.nodes[0];
+  node.detailTable = new scout.TableSpecHelper(this.session).createTableWithOneColumn();
+  node.detailTableVisible = true;
+  return outline;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/form/FormSpecHelper.js
similarity index 70%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpecHelper.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/scout/form/FormSpecHelper.js
index ea9ac84..e65cdea 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpecHelper.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/form/FormSpecHelper.js
@@ -8,14 +8,20 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-var FormSpecHelper = function(session) {
+scout.FormSpecHelper = function(session) {
   this.session = session;
 };
 
-FormSpecHelper.prototype.createFormWithOneField = function(parentId) {
+scout.FormSpecHelper.prototype.createViewWithOneField = function(parentId) {
+  var form = this.createFormWithOneField(parentId);
+  form.displayHint = scout.Form.DisplayHint.VIEW;
+  return form;
+};
+
+scout.FormSpecHelper.prototype.createFormWithOneField = function(parentId) {
   var form = this.createFormModel();
   var rootGroupBox = this.createGroupBoxModel();
-  var field = this.createFieldModel('StringField', form);
+  var field = this.createFieldModel('StringField');
 
   form.rootGroupBox = rootGroupBox.id;
   rootGroupBox.mainBox = true;
@@ -25,7 +31,17 @@
   return createAdapter(form, this.session, [rootGroupBox, field]);
 };
 
-FormSpecHelper.prototype.createFormModel = function() {
+scout.FormSpecHelper.prototype.createGroupBoxWithOneField = function(parentId) {
+  var groupBox = this.createGroupBoxModel();
+  var field = this.createFieldModel('StringField');
+
+  groupBox.owner = parentId || this.session.rootAdapter.id;
+  groupBox.fields = [field.id];
+
+  return createAdapter(groupBox, this.session, [field]);
+};
+
+scout.FormSpecHelper.prototype.createFormModel = function() {
   var form = createSimpleModel('Form', this.session);
   // By definition, a Form must have a 'displayParent'. That is why a mocked parent is set.
   form.parent = {
@@ -43,7 +59,7 @@
   return form;
 };
 
-FormSpecHelper.prototype.createFieldModel = function(objectType, form) {
+scout.FormSpecHelper.prototype.createFieldModel = function(objectType) {
   var session = this.session;
   var model = createSimpleModel(objectType || 'StringField', session);
   model.enabled = true;
@@ -51,11 +67,11 @@
   return model;
 };
 
-FormSpecHelper.prototype.createGroupBoxModel = function() {
+scout.FormSpecHelper.prototype.createGroupBoxModel = function() {
   return this.createFieldModel('GroupBox');
 };
 
-FormSpecHelper.prototype.createFormXFields = function(x, isModal, parentId) {
+scout.FormSpecHelper.prototype.createFormXFields = function(x, isModal, parentId) {
   var form = isModal ? this.createFormModelWithDisplayHint('dialog') : this.createFormModelWithDisplayHint('view');
   var rootGroupBox = this.createGroupBoxModel();
   var fields = [];
@@ -73,7 +89,7 @@
   return createAdapter(form, this.session, fields);
 };
 
-FormSpecHelper.prototype.createFormModelWithDisplayHint = function(displayHint) {
+scout.FormSpecHelper.prototype.createFormModelWithDisplayHint = function(displayHint) {
   var model = this.createFormModel();
   model.displayHint = displayHint;
   return model;
@@ -84,7 +100,7 @@
  * Expects model.fields to be set, creates an adapter for each field.
  * Also replaces model.fields with the ids of the fields.
  */
-FormSpecHelper.prototype.createCompositeField = function(session, model) {
+scout.FormSpecHelper.prototype.createCompositeField = function(session, model) {
   var fields = model.fields || [];
   model.fields = [];
   fields.forEach(function(field) {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/menu/MenuSpecHelper.js
similarity index 83%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpecHelper.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/scout/menu/MenuSpecHelper.js
index 814e0fd..211845d 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpecHelper.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/menu/MenuSpecHelper.js
@@ -8,11 +8,11 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-var MenuSpecHelper = function(session) {
+scout.MenuSpecHelper = function(session) {
   this.session = session;
 };
 
-MenuSpecHelper.prototype.createModel = function(text, iconId, menuTypes) {
+scout.MenuSpecHelper.prototype.createModel = function(text, iconId, menuTypes) {
   var model = createSimpleModel('Menu', this.session);
   $.extend(model, {
     text: text,
@@ -23,7 +23,7 @@
   return model;
 };
 
-MenuSpecHelper.prototype.createMenu = function(model) {
+scout.MenuSpecHelper.prototype.createMenu = function(model) {
   model.objectType = model.objectType || 'Menu';
   model.session = this.session;
   model.parent = this.session.desktop;
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/table/TableSpecHelper.js
similarity index 72%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpecHelper.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/scout/table/TableSpecHelper.js
index 8848dec..b99e032 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpecHelper.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/table/TableSpecHelper.js
@@ -8,13 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global MenuSpecHelper */
-var TableSpecHelper = function(session) {
+/* global scout.MenuSpecHelper */
+scout.TableSpecHelper = function(session) {
   this.session = session;
-  this.menuHelper = new MenuSpecHelper(session);
+  this.menuHelper = new scout.MenuSpecHelper(session);
 };
 
-TableSpecHelper.prototype.createModel = function(columns, rows) {
+scout.TableSpecHelper.prototype.createModel = function(columns, rows) {
   var model = createSimpleModel('Table', this.session);
   $.extend(model, {
     headerVisible: true,
@@ -33,7 +33,7 @@
   return model;
 };
 
-TableSpecHelper.prototype.createModelRow = function(id, cells) {
+scout.TableSpecHelper.prototype.createModelRow = function(id, cells) {
   return {
     id: id || scout.objectFactory.createUniqueId(),
     cells: cells,
@@ -46,7 +46,7 @@
  * @param texts array of texts for the cells in the new row or a string if only one cell should be created.
  * @param withoutCells true if only text instead of cells should be created (server only sends text without a cell object if no other properties are set)
  */
-TableSpecHelper.prototype.createModelRowByTexts = function(id, texts, withoutCells) {
+scout.TableSpecHelper.prototype.createModelRowByTexts = function(id, texts, withoutCells) {
   texts = scout.arrays.ensure(texts);
 
   var cells = [];
@@ -64,7 +64,7 @@
  *
  * @param values array of values for the cells in the new row or a number if only one cell should be created.
  */
-TableSpecHelper.prototype.createModelRowByValues = function(id, values) {
+scout.TableSpecHelper.prototype.createModelRowByValues = function(id, values) {
   values = scout.arrays.ensure(values);
   var cells = [];
   for (var i = 0; i < values.length; i++) {
@@ -73,7 +73,7 @@
   return this.createModelRow(id, cells);
 };
 
-TableSpecHelper.prototype.createModelColumn = function(text, type) {
+scout.TableSpecHelper.prototype.createModelColumn = function(text, type) {
   var column = {
     id: scout.objectFactory.createUniqueId(),
     text: text,
@@ -85,7 +85,7 @@
   return column;
 };
 
-TableSpecHelper.prototype.createModelCell = function(text, value) {
+scout.TableSpecHelper.prototype.createModelCell = function(text, value) {
   var cell = {};
   scout.defaultValues.applyTo(cell, 'Cell');
   if (text !== undefined) {
@@ -97,15 +97,15 @@
   return cell;
 };
 
-TableSpecHelper.prototype.createMenuModel = function(text, icon) {
+scout.TableSpecHelper.prototype.createMenuModel = function(text, icon) {
   return this.menuHelper.createModel(text, icon, ['Table.SingleSelection']);
 };
 
-TableSpecHelper.prototype.createMenuModelWithSingleAndHeader = function(text, icon) {
+scout.TableSpecHelper.prototype.createMenuModelWithSingleAndHeader = function(text, icon) {
   return this.menuHelper.createModel(text, icon, ['Table.SingleSelection', 'Table.Header']);
 };
 
-TableSpecHelper.prototype.createModelColumns = function(count, columnType) {
+scout.TableSpecHelper.prototype.createModelColumns = function(count, columnType) {
   if (!count) {
     return;
   }
@@ -124,7 +124,7 @@
 /**
  * creates cells with value similar to 'cell0_0' if rowId is given, or 'cell0' if no rowId is given
  */
-TableSpecHelper.prototype.createModelCells = function(count, rowId) {
+scout.TableSpecHelper.prototype.createModelCells = function(count, rowId) {
   var cells = [];
   if (rowId === undefined) {
     rowId = '';
@@ -137,7 +137,7 @@
   return cells;
 };
 
-TableSpecHelper.prototype.createModelRows = function(colCount, rowCount) {
+scout.TableSpecHelper.prototype.createModelRows = function(colCount, rowCount) {
   if (!rowCount) {
     return;
   }
@@ -149,7 +149,7 @@
   return rows;
 };
 
-TableSpecHelper.prototype.createModelSingleColumnByTexts = function(texts) {
+scout.TableSpecHelper.prototype.createModelSingleColumnByTexts = function(texts) {
   var rows = [];
   for (var i = 0; i < texts.length; i++) {
     rows.push(this.createModelRowByTexts(null, texts[i]));
@@ -157,7 +157,7 @@
   return this.createModel(this.createModelColumns(1), rows);
 };
 
-TableSpecHelper.prototype.createModelSingleColumnByValues = function(values, columnType) {
+scout.TableSpecHelper.prototype.createModelSingleColumnByValues = function(values, columnType) {
   var rows = [];
   for (var i = 0; i < values.length; i++) {
     rows.push(this.createModelRowByValues(null, values[i]));
@@ -165,29 +165,28 @@
   return this.createModel(this.createModelColumns(1, columnType), rows);
 };
 
-TableSpecHelper.prototype.createModelFixture = function(colCount, rowCount) {
+scout.TableSpecHelper.prototype.createModelFixture = function(colCount, rowCount) {
   return this.createModel(this.createModelColumns(colCount), this.createModelRows(colCount, rowCount));
 };
 
-TableSpecHelper.prototype.createTable = function(model) {
+scout.TableSpecHelper.prototype.createTableWithOneColumn = function() {
+  var model = this.createModelFixture(1, 1);
+  return this.createTable(model);
+};
+
+scout.TableSpecHelper.prototype.createTable = function(model) {
   var table = new scout.Table();
   table.init(model);
   return table;
 };
 
-TableSpecHelper.prototype.createMobileTable = function(model) {
-  var table = new scout.MobileTable();
-  table.init(model);
-  return table;
-};
-
-TableSpecHelper.prototype.createColumnFilter = function(model) {
+scout.TableSpecHelper.prototype.createColumnFilter = function(model) {
   var filter = new scout.TextColumnUserFilter();
   filter.init(model);
   return filter;
 };
 
-TableSpecHelper.prototype.createAndRegisterColumnFilter = function(model) {
+scout.TableSpecHelper.prototype.createAndRegisterColumnFilter = function(model) {
   var filter = this.createColumnFilter(model);
   model.table.addFilter(filter);
   return filter;
@@ -197,7 +196,7 @@
  * Applies display style on rows and cells so that cells are positioned correctly in a row.<br>
  * Necessary because the stylesheet is not applied when running the specs.
  */
-TableSpecHelper.prototype.applyDisplayStyle = function(table) {
+scout.TableSpecHelper.prototype.applyDisplayStyle = function(table) {
   table.$data.css('position', 'relative');
   table.$rows().each(function() {
     var $row = $(this);
@@ -209,7 +208,7 @@
   });
 };
 
-TableSpecHelper.prototype.getRowIds = function(rows) {
+scout.TableSpecHelper.prototype.getRowIds = function(rows) {
   var rowIds = [];
   for (var i = 0; i < rows.length; i++) {
     rowIds.push(rows[i].id);
@@ -217,12 +216,12 @@
   return rowIds;
 };
 
-TableSpecHelper.prototype.selectRowsAndAssert = function(table, rows) {
+scout.TableSpecHelper.prototype.selectRowsAndAssert = function(table, rows) {
   table.selectRows(rows);
   this.assertSelection(table, rows);
 };
 
-TableSpecHelper.prototype.assertSelection = function(table, rows) {
+scout.TableSpecHelper.prototype.assertSelection = function(table, rows) {
   var $selectedRows = table.$selectedRows();
   expect($selectedRows.length).toBe(rows.length);
 
@@ -243,35 +242,35 @@
  * Asserts that the rows contain the given texts at column specified by colIndex
  * @param texts array with same length as rows.
  */
-TableSpecHelper.prototype.assertTextsInCells = function(rows, colIndex, texts) {
+scout.TableSpecHelper.prototype.assertTextsInCells = function(rows, colIndex, texts) {
   expect(rows.length).toBe(texts.length);
   for (var i = 0; i < rows.length; i++) {
     expect(rows[i].cells[colIndex].text).toBe(texts[i]);
   }
 };
 
-TableSpecHelper.prototype.assertValuesInCells = function(rows, colIndex, values) {
+scout.TableSpecHelper.prototype.assertValuesInCells = function(rows, colIndex, values) {
   expect(rows.length).toBe(values.length);
   for (var i = 0; i < rows.length; i++) {
     expect(rows[i].cells[colIndex].value).toBe(values[i]);
   }
 };
 
-TableSpecHelper.prototype.assertDatesInCells = function(rows, colIndex, dates) {
+scout.TableSpecHelper.prototype.assertDatesInCells = function(rows, colIndex, dates) {
   expect(rows.length).toBe(dates.length);
   for (var i = 0; i < rows.length; i++) {
     expect(rows[i].cells[colIndex].value.getTime()).toBe(dates[i].getTime());
   }
 };
 
-TableSpecHelper.prototype.assertSelectionEvent = function(id, rowIds) {
+scout.TableSpecHelper.prototype.assertSelectionEvent = function(id, rowIds) {
   var event = new scout.Event(id, 'rowsSelected', {
     rowIds: rowIds
   });
   expect(mostRecentJsonRequest()).toContainEvents(event);
 };
 
-TableSpecHelper.prototype.getDisplayingContextMenu = function(table) {
+scout.TableSpecHelper.prototype.getDisplayingContextMenu = function(table) {
   return $('body').find('.popup-body');
 };
 
@@ -280,7 +279,7 @@
  * we must reset the object - otherwise we could not test cases with client
  * and server side sorting.
  */
-TableSpecHelper.prototype.resetIntlCollator = function() {
+scout.TableSpecHelper.prototype.resetIntlCollator = function() {
   scout.comparators.TEXT.installed = false;
   scout.comparators.TEXT.collator = null;
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/LocaleSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/text/LocaleSpecHelper.js
similarity index 62%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/text/LocaleSpecHelper.js
rename to org.eclipse.scout.rt.ui.html.test/src/main/js/scout/text/LocaleSpecHelper.js
index 210c3ef..67e4311 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/LocaleSpecHelper.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/main/js/scout/text/LocaleSpecHelper.js
@@ -8,38 +8,38 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-var LocaleSpecHelper = function() {
+scout.LocaleSpecHelper = function() {
   this._initDecimalFormatSymbols();
   this._initDateFormatSymbols();
   this._initDateFormatDefaultPatterns();
 };
 
-LocaleSpecHelper.DEFAULT_LOCALE = 'de-CH';
-LocaleSpecHelper.GERMAN_LOCALE = 'de-DE';
-LocaleSpecHelper.DEFAULT_DATE_FORMAT_PATTERN = 'dd.MM.yyyy';
+scout.LocaleSpecHelper.DEFAULT_LOCALE = 'de-CH';
+scout.LocaleSpecHelper.GERMAN_LOCALE = 'de-DE';
+scout.LocaleSpecHelper.DEFAULT_DATE_FORMAT_PATTERN = 'dd.MM.yyyy';
 
-LocaleSpecHelper.prototype.createModel = function(languageTag) {
+scout.LocaleSpecHelper.prototype.createModel = function(languageTag) {
   var model = {};
   model.languageTag = languageTag;
   return model;
 };
 
-LocaleSpecHelper.prototype.createLocale = function(languageTag) {
+scout.LocaleSpecHelper.prototype.createLocale = function(languageTag) {
   var model = this.createModel(languageTag);
   model.decimalFormatSymbols = this.decimalFormatSymbolsByLocale[languageTag];
   model.decimalFormatPatternDefault = "#,##0.###";
   model.dateFormatSymbols = this.dateFormatSymbolsByLocale[languageTag];
-  model.dateFormatPatternDefault = this.dateFormatPatternByLocale[languageTag] || LocaleSpecHelper.DEFAULT_DATE_FORMAT_PATTERN;
+  model.dateFormatPatternDefault = this.dateFormatPatternByLocale[languageTag] || scout.LocaleSpecHelper.DEFAULT_DATE_FORMAT_PATTERN;
   return new scout.Locale(model);
 };
 
-LocaleSpecHelper.prototype._initDecimalFormatSymbols = function () {
+scout.LocaleSpecHelper.prototype._initDecimalFormatSymbols = function () {
   this.decimalFormatSymbolsByLocale = {};
-  this.decimalFormatSymbolsByLocale[LocaleSpecHelper.DEFAULT_LOCALE] = this.createDecimalFormatSymbolsForDeCH();
-  this.decimalFormatSymbolsByLocale[LocaleSpecHelper.GERMAN_LOCALE] = this.createDecimalFormatSymbolsForDeDE();
+  this.decimalFormatSymbolsByLocale[scout.LocaleSpecHelper.DEFAULT_LOCALE] = this.createDecimalFormatSymbolsForDeCH();
+  this.decimalFormatSymbolsByLocale[scout.LocaleSpecHelper.GERMAN_LOCALE] = this.createDecimalFormatSymbolsForDeDE();
 };
 
-LocaleSpecHelper.prototype.createDecimalFormatSymbolsForDeCH = function() {
+scout.LocaleSpecHelper.prototype.createDecimalFormatSymbolsForDeCH = function() {
   return {
     "digit": "#",
     "zeroDigit": "0",
@@ -50,26 +50,26 @@
   };
 };
 
-LocaleSpecHelper.prototype.createDecimalFormatSymbolsForDeDE = function() {
+scout.LocaleSpecHelper.prototype.createDecimalFormatSymbolsForDeDE = function() {
   var symbols = this.createDecimalFormatSymbolsForDeCH();
   symbols.decimalSeparator = ",";
   symbols.groupingSeparator = ".";
   return symbols;
 };
 
-LocaleSpecHelper.prototype._initDateFormatSymbols = function() {
+scout.LocaleSpecHelper.prototype._initDateFormatSymbols = function() {
   var symbols = this.createDateFormatSymbolsForDe();
   this.dateFormatSymbolsByLocale = {};
-  this.dateFormatSymbolsByLocale[LocaleSpecHelper.DEFAULT_LOCALE] = symbols;
-  this.dateFormatSymbolsByLocale[LocaleSpecHelper.GERMAN_LOCALE] = symbols;
+  this.dateFormatSymbolsByLocale[scout.LocaleSpecHelper.DEFAULT_LOCALE] = symbols;
+  this.dateFormatSymbolsByLocale[scout.LocaleSpecHelper.GERMAN_LOCALE] = symbols;
 };
 
-LocaleSpecHelper.prototype._initDateFormatDefaultPatterns = function() {
+scout.LocaleSpecHelper.prototype._initDateFormatDefaultPatterns = function() {
   this.dateFormatPatternByLocale = {};
   this.dateFormatPatternByLocale.de = "dd.MM.yyyy";
 };
 
-LocaleSpecHelper.prototype.createDateFormatSymbolsForDe = function() {
+scout.LocaleSpecHelper.prototype.createDateFormatSymbolsForDe = function() {
   return {
     "weekdays": ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
     "weekdaysShort": ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest.java
index ca2ce4d..e38f6c8 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest.java
@@ -14,6 +14,9 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 import org.eclipse.scout.rt.platform.util.IOUtility;
 import org.eclipse.scout.rt.ui.html.ResourceBase;
 import org.json.JSONArray;
@@ -22,9 +25,11 @@
 
 public class DefaultValuesFilterTest {
 
-  protected JSONObject readJsonFile(String filename) {
-    String content = IOUtility.getContentUtf8(ResourceBase.class.getResourceAsStream(filename));
-    return new JSONObject(JsonUtility.stripCommentsFromJson(content));
+  protected JSONObject readJsonFile(String filename) throws IOException {
+    try (InputStream in = ResourceBase.class.getResourceAsStream(filename)) {
+      String content = IOUtility.readStringUTF8(in);
+      return new JSONObject(JsonUtility.stripCommentsFromJson(content));
+    }
   }
 
   @Test
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/JsonUtilityTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/JsonUtilityTest.java
index 910315a..1232d89 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/JsonUtilityTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/JsonUtilityTest.java
@@ -12,6 +12,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 import org.eclipse.scout.rt.platform.util.IOUtility;
 import org.eclipse.scout.rt.ui.html.ResourceBase;
 import org.junit.Test;
@@ -19,7 +22,7 @@
 public class JsonUtilityTest {
 
   @Test
-  public void testJsonWithComments() {
+  public void testJsonWithComments() throws IOException {
     // null string
     assertEquals(null, JsonUtility.stripCommentsFromJson(null));
     // empty string
@@ -40,11 +43,16 @@
     assertEquals("", JsonUtility.stripCommentsFromJson("/*\n{\n\r\n  \"location\": \"Baden // Switzerland\" // Person's location\r}\n"));
 
     // load complex json file without comments -> verify that stripping does not change anything
-    String json = IOUtility.getContentUtf8(ResourceBase.class.getResourceAsStream("json/DefaultValuesFilterTest_defaults_simple.json"));
+    String json;
+    try (InputStream in = ResourceBase.class.getResourceAsStream("json/DefaultValuesFilterTest_defaults_simple.json")) {
+      json = IOUtility.readStringUTF8(in);
+    }
     assertEquals(json, JsonUtility.stripCommentsFromJson(json));
 
     // another tes tfile
-    json = IOUtility.getContentUtf8(ResourceBase.class.getResourceAsStream("json/DefaultValuesFilterTest_defaults_withComments.json"));
+    try (InputStream in = ResourceBase.class.getResourceAsStream("json/DefaultValuesFilterTest_defaults_withComments.json")) {
+      json = IOUtility.readStringUTF8(in);
+    }
     assertEquals("{\n  \"defaults\": {\n    \"FormField\": {\n      \"enabled\": true\n    }\n  }\n}\n", JsonUtility.stripCommentsFromJson(json));
   }
 
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/DownloadHandlerStorageTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/DownloadHandlerStorageTest.java
index cbad732..5cab169 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/DownloadHandlerStorageTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/DownloadHandlerStorageTest.java
@@ -55,7 +55,6 @@
 
     SleepUtil.sleepElseLog(100, TimeUnit.MILLISECONDS);
 
-    // FIXME awe: Improve this test (it fails sometimes because of timing issues)
     assertNull(storage.remove(KEY));
     assertEquals("futureMap must be cleared after timeout", 0, storage.futureMap().size());
   }
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktopTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktopTest.java
index 95d3a99..c192f09 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktopTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktopTest.java
@@ -23,10 +23,10 @@
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
 import org.eclipse.scout.rt.client.ui.desktop.OpenUriAction;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutlineViewButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 import org.eclipse.scout.rt.platform.job.Jobs;
 import org.eclipse.scout.rt.platform.resource.BinaryResource;
 import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
@@ -224,35 +224,35 @@
   }
 
   /**
-   * Tests whether non displayable actions are sent.
+   * Tests whether non displayable menus are sent.
    * <p>
    * This reduces response size and also leverages security because the menus are never visible to the user, not even
    * with the dev tools of the browser
    */
   @Test
-  public void testDontSendNonDisplayableActions() throws Exception {
+  public void testDontSendNonDisplayableMenus() throws Exception {
     IDesktop desktop = new DesktopWithNonDisplayableActions();
     desktop.initDesktop();
     JsonDesktop<IDesktop> jsonDesktop = createJsonDesktop(desktop);
 
     JsonMenu<IMenu> jsonDisplayableMenu = jsonDesktop.getAdapter(desktop.getMenu(DesktopWithNonDisplayableActions.DisplayableMenu.class));
     JsonMenu<IMenu> jsonNonDisplayableMenu = jsonDesktop.getAdapter(desktop.getMenu(DesktopWithNonDisplayableActions.NonDisplayableMenu.class));
-    JsonFormToolButton<IFormToolButton<IForm>> jsonDisplayableToolButton = jsonDesktop.getAdapter(desktop.getToolButton(DesktopWithNonDisplayableActions.DisplayableFormToolButton.class));
-    JsonFormToolButton<IFormToolButton<IForm>> jsonNonDisplayableToolButton = jsonDesktop.getAdapter(desktop.getToolButton(DesktopWithNonDisplayableActions.NonDisplayableFormToolButton.class));
+    JsonFormMenu<IFormMenu<IForm>> jsonDisplayableFormMenu = jsonDesktop.getAdapter(desktop.getMenu(DesktopWithNonDisplayableActions.DisplayableFormMenu.class));
+    JsonFormMenu<IFormMenu<IForm>> jsonNonDisplayableFormMenu = jsonDesktop.getAdapter(desktop.getMenu(DesktopWithNonDisplayableActions.NonDisplayableFormMenu.class));
 
-    // Adapter for NonDisplayableMenu/ToolButton must not exist
+    // Adapter for NonDisplayableMenu/Menu must not exist
     assertNull(jsonNonDisplayableMenu);
-    assertNull(jsonNonDisplayableToolButton);
+    assertNull(jsonNonDisplayableFormMenu);
 
-    // Json response must not contain NonDisplayableMenu/ToolButton
+    // Json response must not contain NonDisplayableMenu/FormMenu
     JSONObject json = jsonDesktop.toJson();
-    JSONArray jsonActions = json.getJSONArray("actions");
+    JSONArray jsonActions = json.getJSONArray("menus");
     assertEquals(2, jsonActions.length());
     List<String> ids = new ArrayList<String>();
     ids.add(jsonActions.getString(0));
     ids.add(jsonActions.getString(1));
     assertTrue(ids.contains(jsonDisplayableMenu.getId()));
-    assertTrue(ids.contains(jsonDisplayableToolButton.getId()));
+    assertTrue(ids.contains(jsonDisplayableFormMenu.getId()));
   }
 
   /**
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/DesktopWithNonDisplayableActions.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/DesktopWithNonDisplayableActions.java
index b925134..65c34e1 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/DesktopWithNonDisplayableActions.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/DesktopWithNonDisplayableActions.java
@@ -15,9 +15,9 @@
 
 import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
 import org.eclipse.scout.rt.client.ui.desktop.AbstractDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractOutlineViewButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
 import org.eclipse.scout.rt.platform.Order;
 
 public class DesktopWithNonDisplayableActions extends AbstractDesktop {
@@ -43,11 +43,11 @@
   }
 
   @Order(30)
-  public class DisplayableFormToolButton extends AbstractFormToolButton {
+  public class DisplayableFormMenu extends AbstractFormMenu {
   }
 
   @Order(40)
-  public class NonDisplayableFormToolButton extends AbstractFormToolButton {
+  public class NonDisplayableFormMenu extends AbstractFormMenu {
 
     @Override
     protected void execInitAction() {
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButtonTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/JsonFormMenuTest.java
similarity index 75%
rename from org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButtonTest.java
rename to org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/JsonFormMenuTest.java
index 253d7f0..e7e4cf6 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButtonTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/JsonFormMenuTest.java
@@ -8,20 +8,21 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.ui.html.json.desktop;
+package org.eclipse.scout.rt.ui.html.json.form;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
 import org.eclipse.scout.rt.client.testenvironment.TestEnvironmentClientSession;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 import org.eclipse.scout.rt.testing.client.runner.ClientTestRunner;
 import org.eclipse.scout.rt.testing.client.runner.RunWithClientSession;
 import org.eclipse.scout.rt.testing.platform.runner.RunWithSubject;
 import org.eclipse.scout.rt.ui.html.IUiSession;
-import org.eclipse.scout.rt.ui.html.json.desktop.fixtures.FormToolButton;
+import org.eclipse.scout.rt.ui.html.json.desktop.JsonFormMenu;
 import org.eclipse.scout.rt.ui.html.json.fixtures.UiSessionMock;
+import org.eclipse.scout.rt.ui.html.json.form.fixtures.FormMenu;
 import org.eclipse.scout.rt.ui.html.json.form.fixtures.FormWithOneField;
 import org.junit.Before;
 import org.junit.Test;
@@ -30,7 +31,7 @@
 @RunWith(ClientTestRunner.class)
 @RunWithSubject("default")
 @RunWithClientSession(TestEnvironmentClientSession.class)
-public class JsonFormToolButtonTest {
+public class JsonFormMenuTest {
   private IUiSession m_uiSession;
 
   @Before
@@ -43,20 +44,20 @@
    */
   @Test
   public void testPreventFormDisposal() {
-    FormToolButton button = new FormToolButton();
+    FormMenu button = new FormMenu();
     FormWithOneField form = new FormWithOneField();
     form.start();
     button.setForm(form);
 
-    JsonFormToolButton<IFormToolButton<IForm>> jsonFormToolButton = m_uiSession.createJsonAdapter(button, null);
+    JsonFormMenu<IFormMenu<IForm>> jsonFormMenu = m_uiSession.createJsonAdapter(button, null);
 
-    assertNotNull(jsonFormToolButton.getAdapter(form));
-    jsonFormToolButton.dispose();
+    assertNotNull(jsonFormMenu.getAdapter(form));
+    jsonFormMenu.dispose();
 
     // Form has not been closed yet -> must still be registered
-    assertNotNull(jsonFormToolButton.getAdapter(form));
+    assertNotNull(jsonFormMenu.getAdapter(form));
 
     form.doClose();
-    assertNull(jsonFormToolButton.getAdapter(form));
+    assertNull(jsonFormMenu.getAdapter(form));
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlFieldTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlFieldTest.java
index d83dfc1..1a85383 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlFieldTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlFieldTest.java
@@ -38,7 +38,7 @@
 
   @Test
   public void testToImageByIconIdReplacement() throws JSONException {
-    m_model.setDisplayText(HTML.imgByIconId("test_icon").toEncodedHtml());
+    m_model.setDisplayText(HTML.imgByIconId("test_icon").toHtml());
     JSONObject json = m_htmlField.toJson();
     // currently no icon provider services are available during html ui test, therefore any icon string should be replaced by null
     assertEquals("<img src=\"null\">", json.get(IHtmlField.PROP_DISPLAY_TEXT));
@@ -46,7 +46,7 @@
 
   @Test
   public void testToImageByBinaryResourceReplacement() throws JSONException {
-    m_model.setDisplayText(HTML.imgByBinaryResource("test_resource").toEncodedHtml());
+    m_model.setDisplayText(HTML.imgByBinaryResource("test_resource").toHtml());
     JSONObject json = m_htmlField.toJson();
     assertEquals("<img src=\"dynamic/" + m_session.getUiSessionId() + "/" + m_htmlField.getId() + "/test_resource\">", json.get(IHtmlField.PROP_DISPLAY_TEXT));
   }
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/FormToolButton.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fixtures/FormMenu.java
similarity index 74%
rename from org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/FormToolButton.java
rename to org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fixtures/FormMenu.java
index 822f428..9ff7878 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/desktop/fixtures/FormToolButton.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/form/fixtures/FormMenu.java
@@ -8,11 +8,11 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.ui.html.json.desktop.fixtures;
+package org.eclipse.scout.rt.ui.html.json.form.fixtures;
 
-import org.eclipse.scout.rt.client.ui.desktop.outline.AbstractFormToolButton;
+import org.eclipse.scout.rt.client.ui.form.AbstractFormMenu;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 
-public class FormToolButton extends AbstractFormToolButton<IForm> {
+public class FormMenu extends AbstractFormMenu<IForm> {
 
 }
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/JsonTableTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/JsonTableTest.java
index aec12d3..f2f87b7 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/JsonTableTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/JsonTableTest.java
@@ -53,7 +53,7 @@
 import org.eclipse.scout.rt.ui.html.json.menu.fixtures.Menu;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.ListBoxTable;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.Table;
-import org.eclipse.scout.rt.ui.html.json.table.fixtures.TableControl;
+import org.eclipse.scout.rt.ui.html.json.table.fixtures.FormTableControl;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.TableWith3Cols;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.TableWithNonDisplayableMenu;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.TableWithNonDisplayableMenu.DisplayableMenu;
@@ -496,7 +496,7 @@
 
     // ----------
 
-    TableControl control = new TableControl();
+    FormTableControl control = new FormTableControl();
     table.addTableControl(control);
     assertNotNull(jsonTable.getAdapter(control));
     assertTrue(jsonTable.getAdapter(control).isInitialized());
@@ -514,8 +514,8 @@
 
     // ----------
 
-    TableControl tableControl1 = new TableControl();
-    TableControl tableControl2 = new TableControl();
+    FormTableControl tableControl1 = new FormTableControl();
+    FormTableControl tableControl2 = new FormTableControl();
     table.addTableControl(tableControl1);
     table.addTableControl(tableControl2);
     assertNotNull(jsonTable.getAdapter(tableControl1));
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControlTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControlTest.java
similarity index 94%
rename from org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControlTest.java
rename to org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControlTest.java
index 29cb1d9..310ef01 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControlTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControlTest.java
@@ -25,7 +25,7 @@
 import org.eclipse.scout.rt.ui.html.json.fixtures.UiSessionMock;
 import org.eclipse.scout.rt.ui.html.json.form.fixtures.FormWithOneField;
 import org.eclipse.scout.rt.ui.html.json.table.fixtures.Table;
-import org.eclipse.scout.rt.ui.html.json.table.fixtures.TableControl;
+import org.eclipse.scout.rt.ui.html.json.table.fixtures.FormTableControl;
 import org.eclipse.scout.rt.ui.html.json.testing.JsonTestUtility;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -36,7 +36,7 @@
 @RunWith(ClientTestRunner.class)
 @RunWithSubject("default")
 @RunWithClientSession(TestEnvironmentClientSession.class)
-public class JsonTableControlTest {
+public class JsonFormTableControlTest {
 
   private UiSessionMock m_uiSession;
 
@@ -49,7 +49,7 @@
   public void testLazyLoadingForm_onModelSelectionChanged() throws JSONException {
     FormWithOneField form = new FormWithOneField();
     form.setShowOnStart(false);
-    TableControl control = new TableControl();
+    FormTableControl control = new FormTableControl();
     control.setTable(new Table());
     control.setForm(form);
     control.decorateForm();
@@ -67,7 +67,7 @@
   @Test
   public void testLazyLoadingForm_onUiSelectionChanged() throws Exception {
     FormWithOneField form = new FormWithOneField();
-    TableControl control = new TableControl();
+    FormTableControl control = new FormTableControl();
     control.setTable(new Table());
     control.setForm(form);
     control.decorateForm();
@@ -102,7 +102,7 @@
   public void testLazyLoadingForm_onModelFormChanged() throws JSONException {
     FormWithOneField form = new FormWithOneField();
     form.setShowOnStart(false);
-    TableControl control = new TableControl();
+    FormTableControl control = new FormTableControl();
     control.setTable(new Table());
     control.setForm(form);
     control.decorateForm();
@@ -131,7 +131,7 @@
   @Test
   public void testNonLazyLoadingFormWhenSelected() throws JSONException {
     FormWithOneField form = new FormWithOneField();
-    TableControl control = new TableControl();
+    FormTableControl control = new FormTableControl();
     control.setTable(new Table());
     control.setForm(form);
     control.decorateForm();
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/TableControl.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/FormTableControl.java
similarity index 88%
rename from org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/TableControl.java
rename to org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/FormTableControl.java
index 894dedd..44acf2f 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/TableControl.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/json/table/fixtures/FormTableControl.java
@@ -10,8 +10,8 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json.table.fixtures;
 
-import org.eclipse.scout.rt.client.ui.basic.table.controls.AbstractTableControl;
+import org.eclipse.scout.rt.client.ui.basic.table.controls.AbstractFormTableControl;
 
-public class TableControl extends AbstractTableControl {
+public class FormTableControl extends AbstractFormTableControl {
 
 }
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/res/BrowserInfoTest.java b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/res/BrowserInfoTest.java
index 05008e3..0f65b12 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/res/BrowserInfoTest.java
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/java/org/eclipse/scout/rt/ui/html/res/BrowserInfoTest.java
@@ -15,11 +15,11 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
+import org.eclipse.scout.rt.shared.ui.UiEngineType;
+import org.eclipse.scout.rt.shared.ui.UiSystem;
 import org.eclipse.scout.rt.ui.html.res.BrowserInfo.BrowserVersion;
-import org.eclipse.scout.rt.ui.html.res.BrowserInfo.EngineType;
 import org.junit.Test;
 
 /**
@@ -126,38 +126,38 @@
     checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Maxthon 2.0)", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML like Gecko) Maxthon/4.0.0.2000 Chrome/22.0.1229.79 Safari/537.1", FLAGS_DESKTOP_WINDOWS);
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
     checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)",
-        FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
+        FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
     checkBrowserInfoFlags("Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0",
-        FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
-    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.IE));
+        FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
+    checkBrowserInfoFlags("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.IE));
     checkBrowserInfoFlags("Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16", FLAGS_DESKTOP_WINDOWS);
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.CHROME));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.CHROME));
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.29 Safari/537.36 OPR/15.0.1147.24 (Edition Next)", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36 OPR/19.0.1326.56", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 OPR/20.0.1387.91", FLAGS_DESKTOP_WINDOWS);
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.SAFARI));
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.SAFARI));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.SAFARI));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.SAFARI));
     checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.2; es-US ) AppleWebKit/540.0 (KHTML like Gecko) Version/6.0 Safari/8900.00", FLAGS_DESKTOP_WINDOWS);
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.SAFARI));
-    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", FLAGS_DESKTOP_WINDOWS.copy().engineType(EngineType.FIREFOX));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.SAFARI));
+    checkBrowserInfoFlags("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", FLAGS_DESKTOP_WINDOWS.copy().engineType(UiEngineType.FIREFOX));
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", FLAGS_DESKTOP_WINDOWS);
     checkBrowserInfoFlags("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120422 Firefox/12.0 SeaMonkey/2.9", FLAGS_DESKTOP_WINDOWS);
 
@@ -769,7 +769,7 @@
       return;
     }
 
-    BrowserInfo info = BrowserInfo.createFrom(userAgentString, Locale.getDefault());
+    BrowserInfo info = BrowserInfo.createFrom(userAgentString);
 
     List<String> failedTests = new ArrayList<>();
     if (flags.isMobile() != null && flags.isMobile() != info.isMobile()) {
@@ -778,15 +778,15 @@
     if (flags.isTablet() != null && flags.m_isTablet != info.isTablet()) {
       failedTests.add("TABLET [expected " + flags.m_isTablet + ", but is " + info.isTablet() + "]");
     }
-    boolean isWindows = (info.getSystem() == BrowserInfo.System.WINDOWS);
+    boolean isWindows = (info.getSystem() == UiSystem.WINDOWS);
     if (flags.isWindows() != null && flags.isWindows() != isWindows) {
       failedTests.add("WINDOWS [expected " + flags.m_isWindows + ", but is " + isWindows + "; system=" + info.getSystem() + "]");
     }
-    boolean isMac = (info.getSystem() == BrowserInfo.System.OSX);
+    boolean isMac = (info.getSystem() == UiSystem.OSX);
     if (flags.isMac() != null && flags.isMac() != isMac) {
       failedTests.add("MAC [expected " + flags.m_isMac + ", but is " + isMac + "; system=" + info.getSystem() + "]");
     }
-    boolean isLinux = (info.getSystem() == BrowserInfo.System.UNIX);
+    boolean isLinux = (info.getSystem() == UiSystem.UNIX);
     if (flags.isLinux() != null && flags.isLinux() != isLinux) {
       failedTests.add("LINUX [expected " + flags.m_isLinux + ", but is " + isLinux + "; system=" + info.getSystem() + "]");
     }
@@ -818,7 +818,7 @@
     private Boolean m_isWindows;
     private Boolean m_isMac;
     private Boolean m_isLinux;
-    private EngineType m_engineType;
+    private UiEngineType m_engineType;
 
     public P_BrowserTestFlags() {
     }
@@ -858,7 +858,7 @@
       return m_isLinux;
     }
 
-    public EngineType getEngineType() {
+    public UiEngineType getEngineType() {
       return m_engineType;
     }
 
@@ -912,7 +912,7 @@
       return this;
     }
 
-    public P_BrowserTestFlags engineType(EngineType engineType) {
+    public P_BrowserTestFlags engineType(UiEngineType engineType) {
       m_engineType = engineType;
       return this;
     }
@@ -927,7 +927,7 @@
   public void testCreateBrowserInfo() {
     Map<String, BrowserInfo> testMap = initTestMap();
     for (String userAgent : testMap.keySet()) {
-      BrowserInfo createdBrowserInfo = BrowserInfo.createFrom(userAgent, null);
+      BrowserInfo createdBrowserInfo = BrowserInfo.createFrom(userAgent);
       BrowserInfo expectedBrowserInfo = testMap.get(userAgent);
 
       //Ignore versions if not explicitly set
@@ -955,9 +955,9 @@
   private void putIosBrowsers(Map<String, BrowserInfo> testMap) {
     //iPhone 4S
     String userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25";
-    BrowserInfo browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.SAFARI);
-    browserInfo.setSystem(BrowserInfo.System.IOS);
+    BrowserInfo browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.SAFARI);
+    browserInfo.setSystem(UiSystem.IOS);
     browserInfo.setWebkit(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserVersion(6, 0, 0));
@@ -965,9 +965,9 @@
 
     //iPad 3
     userAgent = "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.SAFARI);
-    browserInfo.setSystem(BrowserInfo.System.IOS);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.SAFARI);
+    browserInfo.setSystem(UiSystem.IOS);
     browserInfo.setWebkit(true);
     browserInfo.setTablet(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(5, 1, 0));
@@ -975,9 +975,9 @@
 
     //iPad 3 (home screen icon mode)
     userAgent = "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.SAFARI);
-    browserInfo.setSystem(BrowserInfo.System.IOS);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.SAFARI);
+    browserInfo.setSystem(UiSystem.IOS);
     browserInfo.setWebkit(true);
     browserInfo.setTablet(true);
     browserInfo.setStandalone(true);
@@ -988,9 +988,9 @@
   private void putAndroidBrowsers(Map<String, BrowserInfo> testMap) {
     //Samsung tablet GT P7500
     String userAgent = "Mozilla/5.0 (Linux; U; Android 3.2; de-de; GT-P7500 Build/HTJ85B) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13";
-    BrowserInfo browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.ANDROID);
-    browserInfo.setSystem(BrowserInfo.System.ANDROID);
+    BrowserInfo browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.ANDROID);
+    browserInfo.setSystem(UiSystem.ANDROID);
     browserInfo.setWebkit(true);
     browserInfo.setTablet(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(3, 2, 0));
@@ -998,9 +998,9 @@
 
     //Samsung Galaxy S2 Android Browser
     userAgent = "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; SAMSUNG GT-I9100/I9100BULPD Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.ANDROID);
-    browserInfo.setSystem(BrowserInfo.System.ANDROID);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.ANDROID);
+    browserInfo.setSystem(UiSystem.ANDROID);
     browserInfo.setWebkit(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(4, 0, 3));
@@ -1008,9 +1008,9 @@
 
     //Samsung Galaxy S2 Google Chrome
     userAgent = "Mozilla/5.0 (Linux; Android 4.0.3; GT-I9100 Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.CHROME);
-    browserInfo.setSystem(BrowserInfo.System.ANDROID);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.CHROME);
+    browserInfo.setSystem(UiSystem.ANDROID);
     browserInfo.setWebkit(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(4, 0, 3));
@@ -1018,9 +1018,9 @@
 
     //Samsung Galaxy S2 Dolphin Browser
     userAgent = "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; GT-I9100 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.ANDROID);
-    browserInfo.setSystem(BrowserInfo.System.ANDROID);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.ANDROID);
+    browserInfo.setSystem(UiSystem.ANDROID);
     browserInfo.setWebkit(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(4, 0, 3));
@@ -1028,9 +1028,9 @@
 
     //Samsung Nexus S Firefox, Android 4.1.2
     userAgent = "Mozilla/5.0 (Android; Mobile; rv:17.0) Gecko/17.0 Firefox/17.0";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.FIREFOX);
-    browserInfo.setSystem(BrowserInfo.System.ANDROID);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.FIREFOX);
+    browserInfo.setSystem(UiSystem.ANDROID);
     browserInfo.setGecko(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(null);
@@ -1040,29 +1040,29 @@
   private void putWindowsBrowsers(Map<String, BrowserInfo> testMap) {
     //Windows 7, IE 9
     String userAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
-    BrowserInfo browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.IE);
+    BrowserInfo browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.IE);
     browserInfo.setEngineVersion(new BrowserInfo.BrowserVersion(9, 0, 0));
-    browserInfo.setSystem(BrowserInfo.System.WINDOWS);
+    browserInfo.setSystem(UiSystem.WINDOWS);
     browserInfo.setMshtml(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(6, 1, 0));
     testMap.put(userAgent, browserInfo);
 
     //Windows 7, Google Chrome 22.0.1229.94
     userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.CHROME);
-    browserInfo.setSystem(BrowserInfo.System.WINDOWS);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.CHROME);
+    browserInfo.setSystem(UiSystem.WINDOWS);
     browserInfo.setWebkit(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(6, 1, 0));
     testMap.put(userAgent, browserInfo);
 
     //Nokia Lumia 800
     userAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 800)";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.IE);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.IE);
     browserInfo.setEngineVersion(new BrowserInfo.BrowserVersion(9, 0, 0));
-    browserInfo.setSystem(BrowserInfo.System.WINDOWS);
+    browserInfo.setSystem(UiSystem.WINDOWS);
     browserInfo.setMshtml(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(7, 5, 0));
@@ -1070,10 +1070,10 @@
 
     //Windows Phone 8 HTC
     userAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; HTC; Windows Phone 8X by HTC)";
-    browserInfo = new BrowserInfo(userAgent, null);
-    browserInfo.setEngineType(BrowserInfo.EngineType.IE);
+    browserInfo = new BrowserInfo(userAgent);
+    browserInfo.setEngineType(UiEngineType.IE);
     browserInfo.setEngineVersion(new BrowserInfo.BrowserVersion(10, 0, 0));
-    browserInfo.setSystem(BrowserInfo.System.WINDOWS);
+    browserInfo.setSystem(UiSystem.WINDOWS);
     browserInfo.setMshtml(true);
     browserInfo.setMobile(true);
     browserInfo.setSystemVersion(new BrowserInfo.BrowserVersion(8, 0, 0));
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/SpecRunnerMaven.html b/org.eclipse.scout.rt.ui.html.test/src/test/js/SpecRunnerMaven.html
similarity index 64%
rename from org.eclipse.scout.rt.ui.html/src/test/js/SpecRunnerMaven.html
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/SpecRunnerMaven.html
index 475b06c..447e43e 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/SpecRunnerMaven.html
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/SpecRunnerMaven.html
@@ -16,7 +16,6 @@
   You can use it too while developing by executing
   mvn jasmine:bdd and connecting to http://localhost:8234/ with your browser.
   When using mvn verify, the server is started on http://localhost:64600/.
-  //FIXME we need to find a better way to manage dependencies. At the moment we have to include the files at 3 different places.
   //FIXME Encoding in embedded jetty (started by jasmine-maven-plugin) is wrong!
  -->
 <html>
@@ -38,24 +37,25 @@
       }
     };
   </script>
-  <link rel="shortcut icon" type="image/png" href="src/main/resources/WebContent/res/jasmine-2.0.0/jasmine_favicon.png">
-  <link rel="stylesheet" type="text/css" href="src/main/resources/WebContent/res/jasmine-2.0.0/jasmine.css">
+  <link rel="shortcut icon" type="image/png" href="ext/WebContent/res/jasmine-2.0.0/jasmine_favicon.png">
+  <link rel="stylesheet" type="text/css" href="ext/WebContent/res/jasmine-2.0.0/jasmine.css">
 
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jquery-2.1.4.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jquery-ui-1.11.2.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/log4javascript.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jasmine-2.0.0/jasmine.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jasmine-2.0.0/jasmine-html.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jasmine-2.0.0/boot.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jasmine-2.0.0/plugins/jasmine-jquery.js"></script>
-  <script type="text/javascript" src="src/main/resources/WebContent/res/jasmine-2.0.0/plugins/mock-ajax.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jquery-2.1.4.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jquery-ui-1.11.2.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/log4javascript.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jasmine-2.0.0/jasmine.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jasmine-2.0.0/jasmine-html.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jasmine-2.0.0/boot.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jasmine-2.0.0/plugins/jasmine-jquery.js"></script>
+  <script type="text/javascript" src="ext/WebContent/res/jasmine-2.0.0/plugins/mock-ajax.js"></script>
   <script type="text/javascript" src="src/main/js/jasmine/JasmineScoutModuleUtil.js"></script>
   <script type="text/javascript" src="src/main/js/jasmine/JasmineScout.js"></script>
   <script type="text/javascript" src="src/main/js/jasmine/JasmineMavenReporter.js"></script>
   <script type="text/javascript" src="src/main/js/jasmine/boot.ext.js"></script>
-  <script type="text/javascript">loadDynamicScript('src/main/js/scout-module.js');</script>
-  <script type="text/javascript" src="src/main/js/scout/desktop/MobileDesktop.js"></script>
-  <script type="text/javascript" src="src/main/js/scout/table/MobileTable.js"></script>
+
+  <script type="text/javascript">loadDynamicScript('ext/scout-module.js');</script>
+  <script type="text/javascript">loadDynamicScript('src/main/js/scout-test-module.js');</script>
+
 </head>
 <body>
   <!-- Test for UTF-8 encoding: äöü -->
@@ -69,7 +69,7 @@
         dataType: 'text',
         contentType: 'text/plain; charset=UTF-8',
         cache: false,
-        url: 'src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json',
+        url: 'ext/org/eclipse/scout/rt/ui/html/json/defaultValues.json',
         data: ''
       }).done(function(data) {
         var dataWithoutComments = stripCommentsFromJson(data), dataObj = JSON.parse(dataWithoutComments);
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/jasmine/JasmineScoutSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/jasmine/JasmineScoutSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/jasmine/JasmineScoutSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/jasmine/JasmineScoutSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/jquery/jquery-scoutSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/jquery/jquery-scoutSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/jquery/jquery-scoutSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/jquery/jquery-scoutSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/ObjectFactorySpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/ObjectFactorySpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/ObjectFactorySpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/ObjectFactorySpec.js
index 4fb5414..8acbe3c 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/ObjectFactorySpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/ObjectFactorySpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global LocaleSpecHelper*/
 describe('ObjectFactory', function() {
 
   beforeEach(function() {
@@ -82,7 +81,7 @@
   it('creates objects which are registered in scout.objectFactories', function() {
     setFixtures(sandbox());
     var session = new scout.Session($('#sandbox'), '1.1');
-    session.locale = new LocaleSpecHelper().createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+    session.locale = new scout.LocaleSpecHelper().createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
 
     // When this test fails with a message like 'TypeError: scout.[ObjectType] is not a constructor...'
     // you should check if the required .js File is registered in SpecRunnerMaven.html.
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/action/ActionSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/action/ActionSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/action/ActionSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/action/ActionSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/calendar/DateRangeSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/calendar/DateRangeSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/calendar/DateRangeSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/calendar/DateRangeSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopFormControllerSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopFormControllerSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopFormControllerSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopFormControllerSpec.js
index d965d8b..3d785b3 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopFormControllerSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopFormControllerSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe('DesktopFormController', function() {
 
   var ctrl, session, $sandbox, popupWindow,
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopSpec.js
new file mode 100644
index 0000000..7c7e188
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/DesktopSpec.js
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe('Desktop', function() {
+  var session, desktop, outlineHelper, formHelper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession({
+      desktop: {
+        navigationVisible: true,
+        headerVisible: true,
+        benchVisible: true
+      },
+      renderDesktop: false
+    });
+    outlineHelper = new scout.OutlineSpecHelper(session);
+    formHelper = new scout.FormSpecHelper(session);
+    desktop = session.desktop;
+    desktop.viewButtons = [];
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    jasmine.clock().uninstall();
+  });
+
+  describe('notification', function() {
+    var ntfc,
+      parent = new scout.Widget();
+
+    beforeEach(function() {
+      session._renderDesktop();
+      parent.session = session;
+      ntfc = scout.create('DesktopNotification', {
+        id: 'theID',
+        parent: desktop,
+        status: {}
+      });
+    });
+
+    it('addNotification', function() {
+      spyOn(ntfc, 'fadeIn');
+      desktop.addNotification(ntfc);
+      expect(ntfc.fadeIn).toHaveBeenCalled();
+      expect(desktop.notifications.indexOf(ntfc)).toBe(0);
+      expect(desktop.$container.find('.notifications').length).toBe(1);
+      expect(desktop.$notification).not.toBe(null);
+    });
+
+    it('removeNotification with object', function() {
+      spyOn(ntfc, 'fadeOut');
+      desktop.addNotification(ntfc); // first add -> create $notifications DIV
+      desktop.removeNotification(ntfc);
+      expect(ntfc.fadeOut).toHaveBeenCalled();
+    });
+
+    it('removeNotification with (string) ID', function() {
+      spyOn(ntfc, 'fadeOut');
+      desktop.addNotification(ntfc); // first add -> create $notifications DIV
+      desktop.removeNotification('theID');
+      expect(ntfc.fadeOut).toHaveBeenCalled();
+    });
+
+    it('_onNotificationRemoved - last notifications removes $notifications DIV', function() {
+      desktop.addNotification(ntfc); // first add -> create $notifications DIV
+      desktop._onNotificationRemoved(ntfc);
+      expect(desktop.notifications.length).toBe(0);
+      expect(desktop.$container.find('.notifications').length).toBe(0);
+      expect(desktop.$notifications).toBe(null);
+    });
+  });
+
+  describe('outline', function() {
+
+    beforeEach(function() {
+      session._renderDesktop();
+    });
+
+    it('gets displayed in desktop navigation ', function() {
+      var model = outlineHelper.createModelFixture(3, 2);
+      var outline = outlineHelper.createOutline(model);
+
+      expect(desktop.outline).toBeFalsy();
+      expect(outline.rendered).toBe(false);
+
+      desktop.setOutline(outline);
+      expect(desktop.outline).toBe(outline);
+      expect(outline.rendered).toBe(true);
+      expect(outline.$container.parent()[0]).toBe(desktop.navigation.$body[0]);
+    });
+
+  });
+
+  describe('benchVisible', function() {
+
+    beforeEach(function() {
+      session._renderDesktop();
+    });
+
+    it('controls visibility of the bench', function() {
+      expect(desktop.benchVisible).toBe(true);
+      expect(desktop.bench.rendered).toBe(true);
+
+      desktop.bench.animateRemoval = false; // disable animation because there won't be any animationEnd event
+      desktop.setBenchVisible(false);
+      expect(desktop.benchVisible).toBe(false);
+      expect(desktop.bench).toBeFalsy();
+
+      desktop.setBenchVisible(true);
+      expect(desktop.benchVisible).toBe(true);
+      expect(desktop.bench.rendered).toBe(true);
+    });
+
+    it('removes the content after the animation', function() {
+      var form = formHelper.createFormWithOneField();
+      var tabBox = desktop.bench.getTabBox('C');
+      form.displayHint = scout.Form.DisplayHint.VIEW;
+      desktop._showForm(form, desktop);
+
+      expect(form.rendered).toBe(true);
+      expect(form.parent).toBe(tabBox);
+      expect(form.$container.parent()[0]).toBe(tabBox.$viewContent[0]);
+      expect(desktop.benchVisible).toBe(true);
+      expect(desktop.bench.rendered).toBe(true);
+
+      // Removal is animated -> does not remove it immediately but after the animation so that the content is visible while the animation runs
+      desktop.setBenchVisible(false);
+      expect(desktop.benchVisible).toBe(false);
+      desktop._hideForm(form);
+      // Not removed yet and still linked, will be done after animation
+      expect(desktop.bench.rendered).toBe(true);
+      expect(form.rendered).toBe(true);
+      expect(form.parent).toBe(tabBox);
+
+      // trigger actual remove
+      jasmine.clock().tick();
+      desktop.bench.removalPending = false;
+      desktop.bench._removeInternal();
+      expect(desktop.bench).toBeFalsy();
+      expect(form.rendered).toBe(false);
+    });
+
+  });
+
+  describe('navigationVisible', function() {
+
+    beforeEach(function() {
+      session._renderDesktop();
+    });
+
+    it('controls visibility of the navigation', function() {
+      expect(desktop.navigationVisible).toBe(true);
+      expect(desktop.navigation.rendered).toBe(true);
+
+      desktop.setNavigationVisible(false);
+      // Force removal of navigation
+      desktop.onLayoutAnimationComplete();
+      expect(desktop.navigationVisible).toBe(false);
+      expect(desktop.navigation).toBeFalsy();
+
+      desktop.setNavigationVisible(true);
+      expect(desktop.navigationVisible).toBe(true);
+      expect(desktop.navigation.rendered).toBe(true);
+    });
+
+    it('only affects content in navigation, not in bench or header', function() {
+      var outline = outlineHelper.createOutlineWithOneDetailForm();
+      var detailForm = outline.nodes[0].detailForm;
+      // because outline is the owner, it is parent as well if created by server -> simulate this
+      detailForm.setParent(outline);
+
+      desktop.setOutline(outline);
+      outline.selectNodes(outline.nodes[0]);
+
+      expect(desktop.navigationVisible).toBe(true);
+      expect(desktop.navigation.rendered).toBe(true);
+      expect(outline.rendered).toBe(true);
+      expect(outline.$container.parent()[0]).toBe(desktop.navigation.$body[0]);
+      expect(detailForm.rendered).toBe(true);
+      expect(detailForm.$container.parent()[0]).toBe(desktop.bench.getTabBox('C').$viewContent[0]);
+
+      // Outline is not visible anymore, but detail form is
+      desktop.setNavigationVisible(false);
+      // Force removal of navigation
+      desktop.onLayoutAnimationComplete();
+      expect(desktop.navigationVisible).toBe(false);
+      expect(desktop.navigation).toBeFalsy();
+      expect(outline.rendered).toBe(false);
+      expect(detailForm.rendered).toBe(true);
+      expect(detailForm.$container.parent()[0]).toBe(desktop.bench.getTabBox('C').$viewContent[0]);
+    });
+
+  });
+
+  describe('headerVisible', function() {
+
+    beforeEach(function() {
+      session._renderDesktop();
+    });
+
+    it('controls visibility of the header', function() {
+      expect(desktop.headerVisible).toBe(true);
+      expect(desktop.header.rendered).toBe(true);
+
+      desktop.setHeaderVisible(false);
+      // Force removal of header
+      desktop.onLayoutAnimationComplete();
+      expect(desktop.headerVisible).toBe(false);
+      expect(desktop.header).toBeFalsy();
+
+      desktop.setHeaderVisible(true);
+      expect(desktop.headerVisible).toBe(true);
+      expect(desktop.header.rendered).toBe(true);
+    });
+
+  });
+
+  describe('_showForm', function() {
+
+    beforeEach(function() {
+      session._renderDesktop();
+    });
+
+    it('adds a view to the bench if displayHint is View', function() {
+      var form = formHelper.createFormWithOneField();
+      var tabBox = desktop.bench.getTabBox('C');
+      form.displayHint = scout.Form.DisplayHint.VIEW;
+      desktop._showForm(form, desktop);
+
+      expect(form.rendered).toBe(true);
+      expect(form.parent).toBe(tabBox);
+      expect(form.$container.parent()[0]).toBe(tabBox.$viewContent[0]);
+    });
+
+  });
+
+  describe('displayStyle', function() {
+
+    describe('COMPACT', function() {
+
+      beforeEach(function() {
+        desktop.displayStyle = scout.Desktop.DisplayStyle.COMPACT;
+        // Flags currently only set by server, therefore we need to set them here as well
+        desktop.navigationVisible = true;
+        desktop.benchVisible = false;
+        desktop.headerVisible = false;
+        session._renderDesktop();
+      });
+
+      it('shows bench and hides navigation if a view is open', function() {
+        var form = formHelper.createViewWithOneField();
+        expect(form.rendered).toBe(false);
+        expect(desktop.navigationVisible).toBe(true);
+        expect(desktop.benchVisible).toBe(false);
+        expect(desktop.headerVisible).toBe(false);
+
+        desktop._showForm(form, desktop);
+        expect(form.rendered).toBe(true);
+        expect(desktop.navigationVisible).toBe(false);
+        expect(desktop.benchVisible).toBe(true);
+        expect(desktop.headerVisible).toBe(true);
+      });
+
+      it('hides bench and shows navigation if the last view gets closed', function() {
+        var form1 = formHelper.createViewWithOneField();
+        var form2 = formHelper.createViewWithOneField();
+        expect(form1.rendered).toBe(false);
+        expect(form2.rendered).toBe(false);
+        expect(desktop.navigationVisible).toBe(true);
+        expect(desktop.benchVisible).toBe(false);
+        expect(desktop.headerVisible).toBe(false);
+
+        // open first form, bench is shown
+        desktop._showForm(form1, desktop);
+        expect(form1.rendered).toBe(true);
+        expect(form2.rendered).toBe(false);
+        expect(desktop.navigationVisible).toBe(false);
+        expect(desktop.benchVisible).toBe(true);
+        expect(desktop.headerVisible).toBe(true);
+
+        // open second form, bench is still shown
+        desktop._showForm(form2, desktop);
+        expect(form1.rendered).toBe(true);
+        expect(form2.rendered).toBe(true);
+        expect(desktop.navigationVisible).toBe(false);
+        expect(desktop.benchVisible).toBe(true);
+        expect(desktop.headerVisible).toBe(true);
+
+        // close first form, bench is still shown
+        desktop._hideForm(form1, desktop);
+        expect(form1.rendered).toBe(false);
+        expect(form2.rendered).toBe(true);
+        expect(desktop.navigationVisible).toBe(false);
+        expect(desktop.benchVisible).toBe(true);
+        expect(desktop.headerVisible).toBe(true);
+
+        // disable remove animation, otherwise form would not be removed immediately
+        desktop.bench.animateRemoval = false;
+
+        // close second form, bench is not shown anymore
+        desktop._hideForm(form2, desktop);
+        expect(form1.rendered).toBe(false);
+        expect(form2.rendered).toBe(false);
+        expect(desktop.navigationVisible).toBe(true);
+        expect(desktop.benchVisible).toBe(false);
+        expect(desktop.headerVisible).toBe(false);
+      });
+
+    });
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/PopupWindowSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/PopupWindowSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/PopupWindowSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/PopupWindowSpec.js
index ee5bf38..ee713ff 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/PopupWindowSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/PopupWindowSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe('PopupWindow', function() {
   var session, helper, $sandbox, origDevice, myForm, myWindow,
     myErrorHandler = function() {};
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/bench/DesktopBenchSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/bench/DesktopBenchSpec.js
new file mode 100644
index 0000000..194e803
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/bench/DesktopBenchSpec.js
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("DesktopBench", function() {
+  var helper, session, desktop, formHelper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession({
+      desktop: {
+        benchVisible: true
+      }
+    });
+    desktop = session.desktop;
+    helper = new scout.OutlineSpecHelper(session);
+    formHelper = new scout.FormSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+  });
+
+  describe("updateOutlineContent", function() {
+    var outline, bench, model, node;
+
+    beforeEach(function() {
+      model = helper.createModelFixture(3, 2, true);
+      outline = helper.createOutline(model);
+      node = model.nodes[0];
+      node.detailForm = formHelper.createFormWithOneField();
+      node.detailFormVisible = true;
+      bench = desktop.bench;
+      desktop.setOutline(outline);
+    });
+
+    it("called when an outline page gets selected", function() {
+      spyOn(bench, 'updateOutlineContent');
+      outline.selectNodes(outline.nodes[1]);
+      expect(bench.updateOutlineContent.calls.count()).toEqual(1);
+    });
+
+    it("doesn't get called if page already is selected", function() {
+      spyOn(bench, 'updateOutlineContent');
+      outline.selectNodes(outline.nodes[1]);
+      expect(bench.updateOutlineContent.calls.count()).toEqual(1);
+
+      outline.selectNodes(outline.nodes[1]);
+      expect(bench.updateOutlineContent.calls.count()).toEqual(1);
+
+      outline.selectNodes([]);
+      expect(bench.updateOutlineContent.calls.count()).toEqual(2);
+
+      outline.selectNodes([]);
+      expect(bench.updateOutlineContent.calls.count()).toEqual(2);
+    });
+
+    it("sets detailForm as outlineContent if node gets selected", function() {
+      // node 0 has a detail form
+      outline.selectNodes(outline.nodes[1]);
+      expect(outline.selectedNodes[0].detailForm).toBeFalsy();
+      expect(bench.outlineContent).toBeFalsy();
+
+      outline.selectNodes(outline.nodes[0]);
+      expect(outline.selectedNodes[0].detailForm).toBeTruthy();
+      expect(bench.outlineContent).toBe(outline.selectedNodes[0].detailForm);
+
+      outline.selectNodes(outline.nodes[1]);
+      expect(outline.selectedNodes[0].detailForm).toBeFalsy();
+      expect(bench.outlineContent).toBeFalsy();
+    });
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/header/DesktopHeaderSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/header/DesktopHeaderSpec.js
new file mode 100644
index 0000000..7dd886b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/header/DesktopHeaderSpec.js
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("DesktopHeader", function() {
+  var helper, session, desktop, formHelper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession({
+      desktop: {
+        benchVisible: true,
+        headerVisible: true
+      }
+    });
+    desktop = session.desktop;
+    helper = new scout.OutlineSpecHelper(session);
+    formHelper = new scout.FormSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+  });
+
+  describe("onBenchOutlineContentChange", function() {
+    var outline, bench, model, node0, node1;
+
+    beforeEach(function() {
+      model = helper.createModelFixture(3, 2, true);
+      outline = helper.createOutline(model);
+      node0 = outline.nodes[0];
+      node0.detailForm = formHelper.createFormWithOneField();
+      node0.detailFormVisible = true;
+      node0.detailForm.rootGroupBox.menuBar.setMenuItems(scout.create('Menu', {
+        parent: node0.detailForm
+      }));
+      node1 = outline.nodes[1];
+      node1.detailForm = formHelper.createFormWithOneField();
+      node1.detailFormVisible = true;
+      node1.detailForm.rootGroupBox.menuBar.setMenuItems(scout.create('Menu', {
+        parent: node1.detailForm
+      }));
+      bench = desktop.bench;
+      desktop.setOutline(outline);
+    });
+
+    it("attaches listener to new outline content", function() {
+      var detailForm0MenuBar = node0.detailForm.rootGroupBox.menuBar;
+      var detailForm1MenuBar = node1.detailForm.rootGroupBox.menuBar;
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(0);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(0);
+      outline.selectNodes(node0);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(1);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(0);
+    });
+
+    it("removes listener from old outline content", function() {
+      var detailForm0MenuBar = node0.detailForm.rootGroupBox.menuBar;
+      var detailForm1MenuBar = node1.detailForm.rootGroupBox.menuBar;
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(0);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(0);
+      outline.selectNodes(node0);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(1);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(0);
+
+      outline.selectNodes(node1);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(0);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(1);
+
+      outline.selectNodes(node0);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(1);
+      expect(detailForm1MenuBar.events._eventListeners.length).toBe(0);
+    });
+
+    it("removes listener when getting removed", function() {
+      var detailForm0MenuBar = node0.detailForm.rootGroupBox.menuBar;
+      outline.selectNodes(node0);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(1);
+
+      desktop.setHeaderVisible(false);
+      expect(detailForm0MenuBar.events._eventListeners.length).toBe(0);
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/navigation/DesktopNavigationSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/navigation/DesktopNavigationSpec.js
new file mode 100644
index 0000000..2dfce3b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/navigation/DesktopNavigationSpec.js
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe('DesktopNavigation', function() {
+  var session, desktop, outlineHelper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession({
+      renderDesktop: false,
+      desktop: {
+        navigationVisible: true
+      }
+    });
+    desktop = session.desktop;
+  });
+
+  describe('viewButtonBox', function() {
+
+    it('is rendered if there are view buttons', function() {
+      desktop.viewButtons = [scout.create('ViewButton', {parent: desktop})];
+      desktop.render(session.$entryPoint);
+      expect(desktop.navigation.viewButtonBox.rendered).toBe(true);
+    });
+
+    it('is not rendered if there are no view buttons', function() {
+      desktop.viewButtons = [];
+      desktop.render(session.$entryPoint);
+      expect(desktop.navigation.viewButtonBox).toBeFalsy();
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopNotificationSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/notification/DesktopNotificationSpec.js
similarity index 84%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopNotificationSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/notification/DesktopNotificationSpec.js
index 92d05fc..bd6ab0a 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopNotificationSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/notification/DesktopNotificationSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe('DesktopNotification', function() {
   var session, helper, $sandbox,
     parent = new scout.Widget();
@@ -16,20 +15,17 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    $sandbox = $('#sandbox');
+    $sandbox = session.$entryPoint;
     parent.session = session;
   });
 
-  afterEach(function() {
-  });
-
   it('_init copies properties from event (model)', function() {
     var ntfc = new scout.DesktopNotification();
     ntfc.init({
       parent: parent,
       id: 'foo',
       duration: 123,
-      closeable: true,
+      closable: true,
       status: {
         message: 'bar',
         severity: scout.Status.Severity.OK
@@ -37,24 +33,24 @@
     });
     expect(ntfc.id).toBe('foo');
     expect(ntfc.duration).toBe(123);
-    expect(ntfc.closeable).toBe(true);
+    expect(ntfc.closable).toBe(true);
     expect(ntfc.status.message).toBe('bar');
     expect(ntfc.status.severity).toBe(scout.Status.Severity.OK);
   });
 
-  it('has close-icon when notification is closeable', function() {
+  it('has close-icon when notification is closable', function() {
     var ntfc = scout.create('DesktopNotification', {
       parent: parent,
       id: 'foo',
       duration: 123,
-      closeable: true,
+      closable: true,
       status: {
         message: 'bar',
         severity: scout.Status.Severity.OK
       }
     });
     ntfc.render($sandbox);
-    expect(ntfc.$container.find('.close').length).toBe(1);
+    expect(ntfc.$container.find('.closer').length).toBe(1);
     expect(ntfc.$container.find('.notification-content').text()).toBe('bar');
     expect(ntfc.$container.hasClass('ok')).toBe(true);
   });
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/OutlineSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/OutlineSpec.js
new file mode 100644
index 0000000..73f8bfe
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/OutlineSpec.js
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("Outline", function() {
+  var helper, menuHelper, session;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new scout.OutlineSpecHelper(session);
+    menuHelper = new scout.MenuSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+  });
+
+  function createNodesDeletedEvent(model, nodeIds, commonParentNodeId) {
+    return {
+      target: model.id,
+      commonParentNodeId: commonParentNodeId,
+      nodeIds: nodeIds,
+      type: 'nodesDeleted'
+    };
+  }
+
+  function createAllChildNodesDeletedEvent(model, commonParentNodeId) {
+    return {
+      target: model.id,
+      commonParentNodeId: commonParentNodeId,
+      type: 'allChildNodesDeleted'
+    };
+  }
+
+  describe("dispose", function() {
+    var model, tree, node0, node1, node2;
+
+    beforeEach(function() {
+      // A large tree is used to properly test recursion
+      model = helper.createModelFixture(3, 2, true);
+      tree = helper.createOutline(model);
+      node0 = model.nodes[0];
+      node1 = model.nodes[1];
+      node2 = model.nodes[2];
+    });
+
+    it("calls onNodeDeleted for every node to be able to cleanup", function() {
+      spyOn(tree, '_onNodeDeleted');
+      tree.destroy();
+      expect(tree._onNodeDeleted.calls.count()).toBe(39);
+    });
+
+    it("calls onNodeDeleted for every node (which was not already deleted before) to be able to cleanup", function() {
+      spyOn(tree, '_onNodeDeleted');
+
+      var message = {
+        events: [createNodesDeletedEvent(model, [node0.id])]
+      };
+      session._processSuccessResponse(message);
+      expect(tree._onNodeDeleted.calls.count()).toBe(13);
+
+      tree._onNodeDeleted.calls.reset();
+      tree.destroy();
+      expect(tree._onNodeDeleted.calls.count()).toBe(26);
+    });
+
+  });
+
+  describe("navigateToTop", function() {
+
+    it("collapses all nodes in bread crumb mode", function() {
+      var model = helper.createModelFixture(1, 1);
+      var node0 = model.nodes[0];
+
+      var tree = helper.createOutline(model);
+      tree.displayStyle = scout.Tree.DisplayStyle.BREADCRUMB;
+      tree.render(session.$entryPoint);
+
+      tree.selectNodes(node0);
+
+      expect(tree.selectedNodes.indexOf(node0) > -1).toBe(true);
+      expect(node0.expanded).toBe(true);
+
+      tree.navigateToTop();
+
+      expect(tree.selectedNodes.length).toBe(0);
+      expect(node0.expanded).toBe(false);
+    });
+  });
+
+  describe("selectNodes", function() {
+    var model, outline, node;
+
+    beforeEach(function() {
+      model = helper.createModelFixture(3, 2, true);
+      outline = helper.createOutline(model);
+      node = model.nodes[0];
+    });
+
+    it("handle navigateUp only once", function() {
+      outline.selectNodes(node);
+      outline.navigateUpInProgress = true;
+      outline.selectNodes([]);
+      expect(outline.navigateUpInProgress).toBe(false);
+    });
+
+    // we must override the _render* methods for this test-case, since we had to
+    // implement a lot more of set-up code to make these methods work.
+    it("otherwise handle single selection (or do nothing when selection is != 1 node)", function() {
+      node.detailFormVisibleByUi = false;
+      outline.navigateUpInProgress = false;
+      outline._renderSelection = function() {};
+      outline._renderMenus = function() {};
+
+      // don't change the visibleByUi flag when selection is != 1
+      outline.selectNodes([]);
+      expect(node.detailFormVisibleByUi).toBe(false);
+
+      // set the visibleByUi flag to true when selection is exactly 1
+      outline.selectNodes([node]);
+      expect(node.detailFormVisibleByUi).toBe(true);
+    });
+
+  });
+
+  describe("updateDetailMenus", function() {
+
+    it("adds the empty space menus of the detail table to the detail menu bar", function() {
+      var outline = helper.createOutlineWithOneDetailTable();
+      outline.setCompact(true);
+      outline.setEmbedDetailContent(true);
+      var node0 = outline.nodes[0];
+      node0.detailTable.menus = [
+        menuHelper.createMenu({
+          menuTypes: ['Table.SingleSelection']
+        }), menuHelper.createMenu({
+          menuTypes: ['Table.EmptySpace']
+        })
+      ];
+      expect(outline.detailMenuBarVisible).toBe(false);
+      expect(outline.detailMenuBar.menuItems.length).toBe(0);
+
+      outline.selectNodes(node0);
+      expect(outline.detailMenuBarVisible).toBe(true);
+      expect(outline.detailMenuBar.menuItems.length).toBe(1);
+      expect(outline.detailMenuBar.menuItems[0]).toBe(node0.detailTable.menus[1]);
+    });
+
+    it("adds the single selection menus of the parent detail table to the detail menu bar", function() {
+      var outline = helper.createOutlineWithOneDetailTable();
+      outline.setCompact(true);
+      outline.setEmbedDetailContent(true);
+      var node0 = outline.nodes[0];
+      node0.detailTable.menus = [
+        menuHelper.createMenu({
+          menuTypes: ['Table.SingleSelection']
+        }), menuHelper.createMenu({
+          menuTypes: ['Table.EmptySpace']
+        })
+      ];
+      expect(outline.detailMenuBarVisible).toBe(false);
+      expect(outline.detailMenuBar.menuItems.length).toBe(0);
+
+      outline.selectNodes(node0.childNodes[0]);
+      expect(outline.detailMenuBarVisible).toBe(true);
+      expect(outline.detailMenuBar.menuItems.length).toBe(1);
+      expect(outline.detailMenuBar.menuItems[0]).toBe(node0.detailTable.menus[0]);
+    });
+
+
+    it("attaches a listener to the detail table to get dynamic menu changes", function() {
+      var outline = helper.createOutlineWithOneDetailTable();
+      outline.setCompact(true);
+      outline.setEmbedDetailContent(true);
+      var node0 = outline.nodes[0];
+      expect(outline.detailMenuBarVisible).toBe(false);
+      expect(outline.detailMenuBar.menuItems.length).toBe(0);
+
+      outline.selectNodes(node0);
+      expect(outline.detailMenuBarVisible).toBe(false);
+      expect(outline.detailMenuBar.menuItems.length).toBe(0);
+
+      // Menus change on table -> detail menu bar needs to be updated as well
+      var menu = menuHelper.createModel('menu', '', ['Table.EmptySpace']);
+      var message = {
+        adapterData: createAdapterData([menu]),
+        events: [createPropertyChangeEvent(node0.detailTable, {
+          menus: [menu.id]
+        })]
+      };
+      session._processSuccessResponse(message);
+      expect(outline.detailMenuBarVisible).toBe(true);
+      expect(outline.detailMenuBar.menuItems.length).toBe(1);
+      expect(outline.detailMenuBar.menuItems[0]).toBe(node0.detailTable.menus[0]);
+    });
+
+    it("removes the listener from the detail tables on selection changes and destroy", function() {
+      var outline = helper.createOutlineWithOneDetailTable();
+      outline.setCompact(true);
+      outline.setEmbedDetailContent(true);
+      var node0 = outline.nodes[0];
+      var node1 = outline.nodes[1];
+      var initialListenerCount = node0.detailTable.events._eventListeners.length;
+
+      outline.selectNodes(node0);
+      var selectionListenerCount = node0.detailTable.events._eventListeners.length;
+      expect(selectionListenerCount).toBe(initialListenerCount + 2); // destroy and propertyChange listener
+
+      outline.selectNodes(node1);
+      selectionListenerCount = node0.detailTable.events._eventListeners.length;
+      expect(selectionListenerCount).toBe(initialListenerCount); // listeners removed
+
+      outline.selectNodes(node0);
+      selectionListenerCount = node0.detailTable.events._eventListeners.length;
+      expect(selectionListenerCount).toBe(initialListenerCount + 2); // listeners attached again
+
+      outline.nodes[0].detailTable.destroy();
+      expect(node0.detailTable.events._eventListeners.length).toBe(0); // every listener should be removed now
+    });
+  });
+
+  describe("onModelAction", function() {
+
+    describe("nodesDeleted event", function() {
+      var model, tree, node0, node1, node2;
+
+      beforeEach(function() {
+        // A large tree is used to properly test recursion
+        model = helper.createModelFixture(3, 2, true);
+        tree = helper.createOutline(model);
+        node0 = model.nodes[0];
+        node1 = model.nodes[1];
+        node2 = model.nodes[2];
+      });
+
+      it("calls onNodeDeleted for every node to be able to cleanup", function() {
+        spyOn(tree, '_onNodeDeleted');
+
+        var message = {
+          events: [createNodesDeletedEvent(model, [node0.id])]
+        };
+        session._processSuccessResponse(message);
+
+        expect(tree._onNodeDeleted.calls.count()).toBe(13);
+      });
+
+    });
+
+    describe("allChildNodesDeleted event", function() {
+      var model, tree, node0, node1, node2;
+
+      beforeEach(function() {
+        // A large tree is used to properly test recursion
+        model = helper.createModelFixture(3, 2, true);
+        tree = helper.createOutline(model);
+        node0 = model.nodes[0];
+        node1 = model.nodes[1];
+        node2 = model.nodes[2];
+      });
+
+      it("calls onNodeDeleted for every node to be able to cleanup", function() {
+        spyOn(tree, '_onNodeDeleted');
+
+        var message = {
+          events: [createAllChildNodesDeletedEvent(model)]
+        };
+        session._processSuccessResponse(message);
+
+        expect(tree._onNodeDeleted.calls.count()).toBe(39);
+        expect(scout.objects.countProperties(tree.nodesMap)).toBe(0);
+      });
+
+    });
+
+  });
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateDownMenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateDownButtonSpec.js
similarity index 82%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateDownMenuSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateDownButtonSpec.js
index 64962d0..612a628 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateDownMenuSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateDownButtonSpec.js
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-describe('NavigateDownMenu', function() {
+describe('NavigateDownButton', function() {
 
   var session, outline, menu, node = {};
 
@@ -16,13 +16,12 @@
     setFixtures(sandbox());
     session = sandboxSession();
     outline = {
-      session: session,
-      handleOutlineContent: function() {}
+      session: session
     };
-    var model = createSimpleModel('NavigateDownMenu', session);
+    var model = createSimpleModel('NavigateDownButton', session);
     model.outline = outline;
     model.node = node;
-    menu = new scout.NavigateDownMenu();
+    menu = new scout.NavigateDownButton();
     menu.init(model);
   });
 
@@ -35,7 +34,10 @@
     node.detailForm = {};
     node.detailFormVisible = true;
     node.detailFormVisibleByUi = true;
-    node.detailTable = {};
+    node.detailTable = scout.create('Table', {
+      parent: new scout.NullWidget(),
+      session: session
+    });
     node.detailTableVisible = true;
     expect(menu._isDetail()).toBe(true);
 
@@ -47,7 +49,10 @@
     // false when detailTable is absent, even when if detailTableVisible=true
     delete node.detailTable;
     expect(menu._isDetail()).toBe(false);
-    node.detailTable = {};
+    node.detailTable = scout.create('Table', {
+      parent: new scout.NullWidget(),
+      session: session
+    });
 
     // false when hidden by UI
     node.detailFormVisibleByUi = false;
@@ -82,9 +87,10 @@
       menu._isDetail = function() { // currently we're not displaying the detail-form
         return false;
       };
-      node.detailTable = {
-        selectedRows: []
-      };
+      node.detailTable = scout.create('Table', {
+        parent: new scout.NullWidget(),
+        session: session
+      });
       expect(menu._buttonEnabled()).toBe(false);
 
       node.detailTable.selectedRows = [{
@@ -96,12 +102,15 @@
 
   it('_drill drills down to first selected row in the detail table', function() {
     var drillNode = {};
-    node.detailTable = {
-      selectedRows: [{
+    node.detailTable = scout.create('Table', {
+      parent: new scout.NullWidget(),
+      session: session,
+      rows: [{
         id: '123',
         nodeId: '123'
       }]
-    };
+    });
+    node.detailTable.selectRows(node.detailTable.rows[0]);
     outline.nodesMap = {
       '123': drillNode
     };
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateUpMenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateUpButtonSpec.js
similarity index 93%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateUpMenuSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateUpButtonSpec.js
index 80c40b1..f9ab1d3 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/NavigateUpMenuSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/outline/navigation/NavigateUpButtonSpec.js
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-describe('NavigateUpMenu', function() {
+describe('NavigateUpButton', function() {
 
   var session, outline, menu, node = {};
 
@@ -17,13 +17,12 @@
     session = sandboxSession();
     outline = {
       session: session,
-      navigateToTop: function() {},
-      handleOutlineContent: function() {}
+      navigateToTop: function() {}
     };
-    var model = createSimpleModel('NavigateUpMenu', session);
+    var model = createSimpleModel('NavigateUpButton', session);
     model.outline = outline;
     model.node = node;
-    menu = new scout.NavigateUpMenu();
+    menu = new scout.NavigateUpButton();
     menu.init(model);
   });
 
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/viewbutton/ViewButtonBoxSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/viewbutton/ViewButtonBoxSpec.js
new file mode 100644
index 0000000..352acd9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/desktop/viewbutton/ViewButtonBoxSpec.js
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe('ViewButtonBox', function() {
+  var session, desktop, outlineHelper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+  });
+
+  describe('viewMenuTab', function() {
+    var viewButtonBox;
+
+    beforeEach(function() {
+      viewButtonBox = scout.create('ViewButtonBox', {
+        parent: new scout.NullWidget(),
+        session: session,
+        viewButtons: [scout.create('ViewButton', {
+          parent: new scout.NullWidget(),
+          session: session,
+          displayStyle: 'MENU',
+          visible: true
+        })]
+      });
+    });
+
+    it('is only visible if there are visible view buttons with displayStyle == "MENU"', function() {
+      viewButtonBox.render(session.$entryPoint);
+      expect(viewButtonBox.viewMenuTab.visible).toBe(true);
+    });
+
+    it('is not visible if there are no visible view buttons ith displayStyle == "MENU"', function() {
+      viewButtonBox.viewButtons[0].visible = false;
+      viewButtonBox.render(session.$entryPoint);
+      expect(viewButtonBox.viewMenuTab.visible).toBe(false);
+    });
+
+    it('is not visible if there are visible view buttons with displayStyle == "TAB"', function() {
+      viewButtonBox.viewButtons[0].displayStyle = 'TAB';
+      viewButtonBox.render(session.$entryPoint);
+      expect(viewButtonBox.viewMenuTab.visible).toBe(false);
+    });
+
+    it('is not visible if there are no view buttons at all', function() {
+      viewButtonBox.viewButtons = [];
+      viewButtonBox.render(session.$entryPoint);
+      expect(viewButtonBox.viewMenuTab.visible).toBe(false);
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/FocusManagerSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/focus/FocusManagerSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/FocusManagerSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/focus/FocusManagerSpec.js
index 322fcc8..327c3f5 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/FocusManagerSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/focus/FocusManagerSpec.js
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper, FocusManagerSpecHelper */
+/* global FocusManagerSpecHelper */
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
 describe('scout.Focusmanager', function() {
   var session, formHelper, focusHelper, form;
@@ -18,7 +18,7 @@
     jasmine.Ajax.install();
     session = sandboxSession();
     session.init();
-    formHelper = new FormSpecHelper(session);
+    formHelper = new scout.FormSpecHelper(session);
     focusHelper = new FocusManagerSpecHelper();
     jasmine.clock().install();
     uninstallUnloadHandlers(session);
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/FocusManagerSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/focus/FocusManagerSpecHelper.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/FocusManagerSpecHelper.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/focus/FocusManagerSpecHelper.js
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormMenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormMenuSpec.js
new file mode 100644
index 0000000..8a617ff
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormMenuSpec.js
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("FormMenu", function() {
+  var session, desktop, helper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new scout.FormSpecHelper(session);
+    desktop = session.desktop;
+  });
+
+  function createMenu(model) {
+    model.form = helper.createFormWithOneField();
+    model.desktop = desktop;
+
+    var menu = new scout.FormMenu();
+    menu.init(model);
+    menu.position = function() {};
+    return menu;
+  }
+
+  function findPopup() {
+    return $('.popup');
+  }
+
+  describe("setSelected", function() {
+
+    it("opens and closes the form popup", function() {
+      var menu = createMenu(createSimpleModel('FormMenu', session));
+      menu.render(session.$entryPoint);
+      expect(findPopup()).not.toExist();
+
+      menu.setSelected(true);
+      expect(findPopup()).toBeVisible();
+
+      menu.setSelected(false);
+      expect(findPopup()).not.toExist();
+    });
+
+    it("opens the popup and the ellipsis if the menu is overflown", function() {
+      var ellipsisMenu = scout.menus.createEllipsisMenu({
+        parent: new scout.NullWidget(),
+        session: session
+      });
+      ellipsisMenu.render(session.$entryPoint);
+
+      var menu = createMenu(createSimpleModel('FormMenu', session));
+      menu.render(session.$entryPoint);
+
+      scout.menus.moveMenuIntoEllipsis(menu, ellipsisMenu);
+      expect(menu.rendered).toBe(false);
+      expect(findPopup()).not.toExist();
+
+      menu.setSelected(true);
+      expect(ellipsisMenu.selected).toBe(true);
+      expect(menu.selected).toBe(true);
+      expect(findPopup()).toBeVisible();
+
+      // cleanup
+      menu.setSelected(false);
+      ellipsisMenu.setSelected(false);
+    });
+
+    it("opens the popup but not the ellipsis if the menu is overflown and mobile popup style is used", function() {
+      var ellipsisMenu = scout.menus.createEllipsisMenu({
+        parent: new scout.NullWidget(),
+        session: session
+      });
+      ellipsisMenu.render(session.$entryPoint);
+
+      var model = createSimpleModel('FormMenu', session);
+      model.popupStyle = scout.FormMenu.PopupStyle.MOBILE;
+      var menu = createMenu(model);
+      menu.render(session.$entryPoint);
+
+      scout.menus.moveMenuIntoEllipsis(menu, ellipsisMenu);
+      expect(menu.rendered).toBe(false);
+      expect(findPopup()).not.toExist();
+
+      menu.setSelected(true);
+      expect(ellipsisMenu.selected).toBe(false);
+      expect(menu.selected).toBe(true);
+      expect(findPopup()).toBeVisible();
+
+      // cleanup
+      menu.setSelected(false);
+    });
+
+  });
+
+  describe("onModelPropertyChange", function() {
+
+    describe("selected", function() {
+
+      it("calls setSelected", function() {
+        var menu = createMenu(createSimpleModel('FormMenu', session));
+        menu.render(session.$entryPoint);
+        expect(findPopup()).not.toExist();
+
+        spyOn(menu, 'setSelected');
+
+        var event = createPropertyChangeEvent(menu, {
+          "selected": true
+        });
+        menu.onModelPropertyChange(event);
+        expect(menu.setSelected).toHaveBeenCalled();
+      });
+
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormSpec.js
index 4277a8f..7d63321 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/FormSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("Form", function() {
   var session, helper;
 
@@ -18,7 +17,7 @@
     jasmine.clock().install();
     session = sandboxSession();
     session.init();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     uninstallUnloadHandlers(session);
   });
 
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/BasicFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/BasicFieldSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/BasicFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/BasicFieldSpec.js
index 395f279..f173088 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/BasicFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/BasicFieldSpec.js
@@ -8,14 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("BasicField", function() {
   var session, helper, field;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     field = createField(createModel());
     jasmine.Ajax.install();
     jasmine.clock().install();
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/FormFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/FormFieldSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/FormFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/FormFieldSpec.js
index 9dca27f..438d5b0 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/FormFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/FormFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("FormField", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
   });
 
   describe("inheritance", function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/ValueFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/ValueFieldSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/ValueFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/ValueFieldSpec.js
index 28faab7..eeecdd3 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/ValueFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/ValueFieldSpec.js
@@ -8,15 +8,15 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper, MenuSpecHelper */
+/* global removePopups */
 describe("ValueField", function() {
   var session, helper, menuHelper;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
-    menuHelper = new MenuSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
+    menuHelper = new scout.MenuSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
@@ -75,7 +75,7 @@
 
     afterEach(function() {
       // Close context menus
-      $('body').triggerClick();
+      removePopups(session);
     });
 
     it("context menu only shows visible menus", function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/browserfield/BrowserFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/browserfield/BrowserFieldSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/browserfield/BrowserFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/browserfield/BrowserFieldSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/checkbox/CheckBoxFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/checkbox/CheckBoxFieldSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/checkbox/CheckBoxFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/checkbox/CheckBoxFieldSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js
index 0fda492..adf80d5 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/clipboardfield/ClipboardFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe('ClipboardField', function() {
   var session, helper, $sandbox, origDevice;
 
@@ -16,7 +15,7 @@
     setFixtures(sandbox());
     session = sandboxSession();
     $sandbox = $('#sandbox');
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
     origDevice = scout.device;
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/datefield/DateFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/datefield/DateFieldSpec.js
similarity index 60%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/datefield/DateFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/datefield/DateFieldSpec.js
index db6cdb4..01ab653 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/datefield/DateFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/datefield/DateFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("DateField", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
@@ -49,7 +48,7 @@
   }
 
   function createModel() {
-    var model = helper.createFieldModel('scout.DateField');
+    var model = helper.createFieldModel('DateField');
     model.hasDate = true;
     model.timeFormatPattern = 'HH:mm';
     model.dateFormatPattern = 'dd.MM.yyyy';
@@ -60,6 +59,18 @@
     return $('.date-picker');
   }
 
+  // Used to expect a date.
+  // Deals with the akward 0=january behavior of the Date#getMonth() method,
+  // which means month=1 is january
+  function expectDate(date, year, month, day) {
+    if (month === 0) {
+      throw new Error('invalid month 0. Months start at 1=january');
+    }
+    expect(date.getFullYear()).toBe(year);
+    expect(date.getMonth()).toBe(month - 1);
+    expect(date.getDate()).toBe(day);
+  }
+
   describe("Clicking the field", function() {
 
     it("opens the datepicker", function() {
@@ -75,6 +86,39 @@
 
   });
 
+  describe("displayText", function() {
+
+    it("is shown correctly after rendering", function() {
+      var model = createModel();
+      model.displayText = '14.04.2016\n12:28';
+      model.hasDate = true;
+      model.hasTime = true;
+      var dateField = createField(model);
+      dateField.render(session.$entryPoint);
+      dateField.dateDisplayText = '14.04.2016';
+      dateField.timeDisplayText = '12:28';
+      expect(dateField.$dateField.val()).toBe('14.04.2016');
+      expect(dateField.$timeField.val()).toBe('12:28');
+    });
+
+    it("is removed properly when setting to ''", function() {
+      var model = createModel();
+      model.displayText = '14.04.2016\n12:28';
+      model.hasDate = true;
+      model.hasTime = true;
+      var dateField = createField(model);
+      dateField.render(session.$entryPoint);
+
+      dateField._syncDisplayText('');
+      dateField._renderDisplayText();
+      expect(dateField.dateDisplayText).toBe('');
+      expect(dateField.timeDisplayText).toBe('');
+      expect(dateField.$dateField.val()).toBe('');
+      expect(dateField.$timeField.val()).toBe('');
+    });
+
+  });
+
   describe("Leaving the field", function() {
 
     it("closes the datepicker", function() {
@@ -94,9 +138,7 @@
       // Set reference date, so result is reliable for testing
       dateField.autoTimestampAsDate = new Date(2015, 10, 1);
       dateField.$dateField.val('02');
-
       dateField._onDateFieldBlur();
-
       expect(dateField.$dateField.val()).toBe('02.11.2015');
     });
 
@@ -106,9 +148,7 @@
       var dateField = createFieldAndFocusAndOpenPicker(model);
 
       dateField.$dateField.val('02');
-
       dateField._onDateFieldBlur();
-
       expect(dateField.$dateField.val()).toBe('02.10.1999');
     });
 
@@ -117,21 +157,62 @@
       model.timestamp = '2014-10-01';
       var dateField = createFieldAndFocusAndOpenPicker(model);
       var dateBefore = dateField.timestampAsDate;
-      expect(dateBefore.getFullYear()).toBe(2014);
-      expect(dateBefore.getMonth()).toBe(9);
-      expect(dateBefore.getDate()).toBe(1);
+      expectDate(dateBefore, 2014, 10, 1);
 
       dateField.$dateField.val('11.02.2015');
       dateBefore = dateField.timestampAsDate;
-      expect(dateBefore.getFullYear()).toBe(2014);
-      expect(dateBefore.getMonth()).toBe(9);
-      expect(dateBefore.getDate()).toBe(1);
+      expectDate(dateBefore, 2014, 10, 1);
 
       dateField._onDateFieldBlur();
-      var date= dateField.timestampAsDate;
-      expect(date.getFullYear()).toBe(2015);
-      expect(date.getMonth()).toBe(1);
-      expect(date.getDate()).toBe(11);
+      var date = dateField.timestampAsDate;
+      expectDate(date, 2015, 2, 11);
+    });
+
+    it("sends timestamp and displayText", function() {
+      var model = createModel();
+      model.timestamp = '2014-10-01';
+      var dateField = createFieldAndFocusAndOpenPicker(model);
+
+      dateField.$dateField.val('11.02.2015');
+      dateField._onDateFieldBlur();
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+
+      // Order is important, displayText needs to be before timestamp
+      // Otherwise server would generate a display text as soon as timestamp changes and send it back even if it is the same as the ui is sending
+      var events = [
+        new scout.Event(dateField.id, 'displayTextChanged', {
+          displayText: "11.02.2015"
+        }),
+        new scout.Event(dateField.id, 'timestampChanged', {
+          timestamp: "2015-02-11"
+        })
+      ];
+      expect(mostRecentJsonRequest()).toContainEventsExactly(events);
+    });
+
+    it("does not send timestamp and displayText again if not changed", function() {
+      var model = createModel();
+      model.timestamp = '2014-10-01';
+      var dateField = createFieldAndFocusAndOpenPicker(model);
+
+      dateField.$dateField.val('11.02.2015');
+      dateField._onDateFieldBlur();
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+
+      dateField._onDateFieldBlur();
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(1); // still 1
+    });
+
+    it("does not send timestamp and displayText if no date was entered", function() {
+      var model = createModel();
+      var dateField = createFieldAndFocusAndOpenPicker(model);
+
+      dateField._onDateFieldBlur();
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(0);
     });
 
   });
@@ -160,6 +241,30 @@
 
   });
 
+  describe("Picker", function() {
+
+    it("sends displayText and timestamp if date was selected", function() {
+      var model = createModel();
+      var dateField = createFieldAndFocusAndOpenPicker(model);
+
+      dateField._onDatePickerDateSelect({type: 'dateSelect', date: new Date(2016,1,1)});
+      expect(dateField.$dateField.val()).toBe('01.02.2016');
+      sendQueuedAjaxCalls();
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+
+      var events = [
+        new scout.Event(dateField.id, 'displayTextChanged', {
+          displayText: "01.02.2016"
+        }),
+        new scout.Event(dateField.id, 'timestampChanged', {
+          timestamp: "2016-02-01"
+        })
+      ];
+      expect(mostRecentJsonRequest()).toContainEventsExactly(events);
+    });
+
+  });
+
   describe("Key handling", function() {
 
     describe("ESC", function() {
@@ -183,23 +288,15 @@
         model.timestamp = '2014-10-01';
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
-
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.val('11.02.2015');
-        dateBefore=dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
-
+        dateBefore = dateField.timestampAsDate;
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.ENTER);
-        var date= dateField.timestampAsDate;
-        expect(date.getFullYear()).toBe(2015);
-        expect(date.getMonth()).toBe(1);
-        expect(date.getDate()).toBe(11);
+        var date = dateField.timestampAsDate;
+        expectDate(date, 2015, 2, 11);
         expect(findPicker().length).toBe(0);
       });
 
@@ -207,58 +304,46 @@
 
     describe("DOWN", function() {
 
-      it("increases day by one", function() {
-        var model = createModel();
+      var model;
+
+      beforeEach(function() {
+        model = createModel();
         model.timestamp = '2014-10-01';
+        model.displayText = '01.10.2014\n';
+      });
+
+      it("increases day by one", function() {
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.DOWN);
 
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('02.10.2014');
       });
 
       it("increases month by one if shift is used as modifier", function() {
-        var model = createModel();
-        model.timestamp = '2014-10-01';
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.DOWN, 'shift');
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
-
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('01.11.2014');
       });
 
       it("increases year by one if ctrl is used as modifier", function() {
-        var model = createModel();
-        model.timestamp = '2014-10-01';
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.DOWN, 'ctrl');
 
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
-
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('01.10.2015');
       });
 
@@ -266,57 +351,47 @@
 
     describe("UP", function() {
 
-      it("decreases day by one", function() {
-        var model = createModel();
+      var model;
+
+      beforeEach(function() {
+        model = createModel();
         model.timestamp = '2014-10-01';
+        model.displayText = '01.10.2014\n';
+      });
+
+      it("decreases day by one", function() {
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.UP);
 
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('30.09.2014');
       });
 
       it("decreases month by one if shift is used as modifier", function() {
-        var model = createModel();
-        model.timestamp = '2014-10-01';
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.UP, 'shift');
 
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('01.09.2014');
       });
 
       it("decreases year by one if ctrl is used as modifier", function() {
-        var model = createModel();
-        model.timestamp = '2014-10-01';
         var dateField = createFieldAndFocusAndOpenPicker(model);
         var dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
 
         dateField.$dateField.triggerKeyDown(scout.keys.UP, 'ctrl');
 
         dateBefore = dateField.timestampAsDate;
-        expect(dateBefore.getFullYear()).toBe(2014);
-        expect(dateBefore.getMonth()).toBe(9);
-        expect(dateBefore.getDate()).toBe(1);
+        expectDate(dateBefore, 2014, 10, 1);
         expect(dateField.$dateField.val()).toBe('01.10.2013');
       });
 
@@ -376,4 +451,40 @@
 
   });
 
+  describe("Allowed dates", function() {
+
+    it("_referenceDate returns only allowed date - only one date", function() {
+      var model = createModel();
+      model.allowedDates = ["2016-04-15"];
+      var dateField = createField(model);
+      var date = dateField._referenceDate();
+      expectDate(date, 2016, 4, 15);
+    });
+
+    it("_referenceDate returns only allowed date - choose nearest date in the future", function() {
+      var model = createModel();
+      model.allowedDates = ["2016-03-14", "2016-04-16", "2016-04-17"];
+      model.autoTimestamp = '2016-04-15';
+      var dateField = createField(model);
+      var date = dateField._referenceDate();
+      expectDate(date, 2016, 4, 16);
+    });
+
+    it("_referenceDate returns only allowed date - when no date in future is available, choose nearest date in past", function() {
+      var model = createModel();
+      model.allowedDates = ["2016-02-14", "2016-03-16", "2016-04-03"];
+      model.autoTimestamp = '2016-04-15';
+      var dateField = createField(model);
+      var date = dateField._referenceDate();
+      expectDate(date, 2016, 4, 3);
+    });
+
+    it("_syncAllowedDates must convert date strings into Dates", function() {
+      var dateField = createField(createModel());
+      dateField._syncAllowedDates(["2016-02-14"]);
+      expectDate(dateField.allowedDates[0], 2016, 2, 14);
+    });
+
+  });
+
 });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js
similarity index 84%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js
index f5b05ad..cc437e7 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/groupbox/GroupBoxSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("GroupBox", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
   });
 
   function createField(model, parent) {
@@ -83,6 +82,19 @@
       expect(formAdapter.rootGroupBox.$container.cssHeight()).toBe(123);
       expect(formAdapter.rootGroupBox.$container.cssWidth()).toBe(97);
     });
+
+  });
+
+  describe("focus", function() {
+
+    it("focus first focusable field in groupBox", function() {
+      var groupBox = helper.createGroupBoxWithOneField();
+      groupBox.render(session.$entryPoint);
+      expect(scout.focusUtils.isActiveElement(groupBox.fields[0].$field[0])).toBe(false);
+      groupBox.focus();
+      expect(scout.focusUtils.isActiveElement(groupBox.fields[0].$field[0])).toBe(true);
+    });
+
   });
 
 });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js
index 7914cfd..9e3e62c 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/labelfield/LabelFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("LabelField", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
   });
 
   function createField(model) {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js
similarity index 92%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js
index 7c41204..a6fa89e 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/numberfield/NumberFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper,LocaleSpecHelper */
 describe("NumberField", function() {
   var session;
   var helper;
@@ -18,11 +17,11 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
-    localeHelper = new LocaleSpecHelper();
+    helper = new scout.FormSpecHelper(session);
+    localeHelper = new scout.LocaleSpecHelper();
     jasmine.Ajax.install();
     jasmine.clock().install();
-    locale = localeHelper.createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+    locale = localeHelper.createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
   });
 
   afterEach(function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js
index 71b05de..fb0833d 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/sequencebox/SequenceBoxSpec.js
@@ -8,15 +8,14 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper, MenuSpecHelper */
 describe("SequenceBox", function() {
   var session, helper, menuHelper;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
-    menuHelper = new MenuSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
+    menuHelper = new scout.MenuSpecHelper(session);
   });
 
   function createField(model) {
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js
new file mode 100644
index 0000000..877b740
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js
@@ -0,0 +1,214 @@
+ /*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe('SmartField', function() {
+  var session;
+  var smartField;
+  var helper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new scout.FormSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    session = null;
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+    $('.smart-field-popup').remove();
+    $('.touch-popup').remove();
+  });
+
+  beforeEach(function() {
+    var model = helper.createFieldModel('SmartField');
+    smartField = new scout.SmartField();
+    smartField.init(model);
+  });
+
+  describe('_onKeyUp', function() {
+
+    it('doesn not call _openProposal() when TAB has been pressed', function() {
+      smartField.render(session.$entryPoint);
+      smartField._openProposal = function(displayText, selectCurrentValue) {};
+      var event = {
+        which: scout.keys.TAB
+      };
+      spyOn(smartField, '_openProposal');
+      smartField._onKeyUp(event);
+      expect(smartField._openProposal).not.toHaveBeenCalled();
+    });
+
+    it('calls _openProposal() when a character key has been pressed', function() {
+      smartField.render(session.$entryPoint);
+      smartField._browseOnce = true;
+      smartField._popup = {};
+      smartField._openProposal = function(displayText, selectCurrentValue) {};
+      var event = {
+        which: scout.keys.A
+      };
+      spyOn(smartField, '_openProposal').and.callThrough();
+      smartField._onKeyUp(event);
+      expect(smartField._openProposal).toHaveBeenCalled();
+    });
+
+  });
+
+  describe('_syncProposalChooser', function() {
+
+    it('must reset _requestProposal property', function() {
+      smartField.render(session.$entryPoint);
+      expect(smartField._requestedProposal).toBe(false);
+      smartField._openProposal(true);
+      expect(smartField._requestedProposal).toBe(true);
+      smartField._syncProposalChooser({});
+      expect(smartField._requestedProposal).toBe(false);
+    });
+
+  }),
+
+  describe('_openProposal', function() {
+
+    var events = [null];
+
+    beforeEach(function() {
+      smartField.render(session.$entryPoint);
+      smartField.$field.val('foo');
+      smartField.remoteHandler = function(event, delay) {
+        events[0] = event;
+      };
+    });
+
+    it('must "browse all" when field is valid and browseAll parameter is true', function() {
+      smartField._openProposal(true);
+      expect(events[0].displayText).toBe('foo');
+      expect(events[0].browseAll).toBe(true);
+      expect(events[0].selectCurrentValue).toBe(true);
+    });
+
+    it('must search by display-text when field is valid and browseAll parameter is false', function() {
+      smartField._openProposal(false);
+      expect(events[0].displayText).toBe('foo');
+      expect(events[0].selectCurrentValue).toBe(false);
+    });
+
+    it('must "browseAll" when field is invalid', function() {
+      smartField.errorStatus = {};
+      smartField._openProposal(true);
+      expect(events[0].displayText).toBe('foo');
+      expect(events[0].browseAll).toBe(true);
+      expect(events[0].selectCurrentValue).toBe(false);
+    });
+  });
+
+  describe('_acceptProposal', function() {
+
+    it('must set displayText', function() {
+      smartField.render(session.$entryPoint);
+      smartField.$field.val('foo');
+      smartField._acceptProposal();
+      expect(smartField.displayText).toBe('foo');
+    });
+
+    it('must call clearTimeout() for pending typedProposal events', function() {
+      smartField.render(session.$entryPoint);
+      smartField._sendTimeoutId = null;
+      smartField.$field.val('bar');
+      smartField._proposalTyped();
+      expect(smartField._pendingProposalTyped).toBeTruthy();
+      smartField._acceptProposal();
+      expect(smartField._pendingProposalTyped).toBe(null);
+    });
+
+    it('dont send _acceptProposal when displayText has not changed', function() {
+      smartField.render(session.$entryPoint);
+      smartField._oldDisplayText = 'foo';
+      smartField.$field.val('foo');
+      spyOn(smartField, 'remoteHandler');
+      smartField._acceptProposal();
+      expect(smartField.remoteHandler).not.toHaveBeenCalled();
+    });
+
+    it('send _acceptProposal when displayText has changed', function() {
+      smartField.render(session.$entryPoint);
+      smartField._oldDisplayText = 'foo';
+      smartField.$field.val('bar');
+      spyOn(smartField, 'remoteHandler');
+      smartField._acceptProposal();
+      expect(smartField.remoteHandler).toHaveBeenCalled();
+    });
+
+    // test for ticket #168652
+    it('send deleteProposal when displayText has been deleted quickly', function() {
+      smartField.render(session.$entryPoint);
+      smartField._oldDisplayText = 'foo';
+      smartField.$field.val('');
+      smartField.proposalChooser = {}; // fake proposal-chooser is open
+      spyOn(smartField, '_sendDeleteProposal');
+      smartField._acceptProposal();
+      expect(smartField._sendDeleteProposal).toHaveBeenCalled();
+    });
+
+  });
+
+  describe('touch = true', function() {
+
+    it('opens a touch popup when smart field gets touched', function() {
+      var proposalChooser = scout.create('Table', {parent: new scout.NullWidget(), session: session, _register: true});
+
+      smartField.touch = true;
+      smartField.render(session.$entryPoint);
+      smartField.$field.click();
+      smartField.onModelPropertyChange(createPropertyChangeEvent(smartField, {
+        proposalChooser: proposalChooser.id
+      }));
+      expect(smartField._popup.rendered).toBe(true);
+      expect(smartField._popup._$widgetContainer.has(smartField.proposalChooser.$container));
+      expect($('.touch-popup').length).toBe(1);
+      expect($('.smart-field-popup').length).toBe(0);
+
+      smartField._popup.close();
+      smartField.onModelPropertyChange(createPropertyChangeEvent(smartField, {
+        proposalChooser: null
+      }));
+      expect(smartField._popup.rendered).toBe(false);
+      expect($('.touch-popup').length).toBe(0);
+      expect($('.smart-field-popup').length).toBe(0);
+
+      // Expect same behavior after a second click
+      smartField.$field.click();
+      smartField.onModelPropertyChange(createPropertyChangeEvent(smartField, {
+        proposalChooser: proposalChooser.id
+      }));
+      expect(smartField._popup.rendered).toBe(true);
+      expect(smartField._popup._$widgetContainer.has(smartField.proposalChooser.$container));
+      expect($('.touch-popup').length).toBe(1);
+      expect($('.smart-field-popup').length).toBe(0);
+      smartField._popup.close();
+    });
+
+    it('opens a touch popup if there already is a proposal chooser while rendering', function() {
+      smartField.proposalChooser = scout.create('Table', {parent: new scout.NullWidget(), session: session, _register: true});
+      smartField.touch = true;
+      smartField.render(session.$entryPoint);
+      expect(smartField._popup.rendered).toBe(true);
+      expect(smartField._popup._$widgetContainer.has(smartField.proposalChooser.$container));
+      expect($('.touch-popup').length).toBe(1);
+      expect($('.smart-field-popup').length).toBe(0);
+      expect($('.smart-field-popup').length).toBe(0);
+      smartField._popup.close();
+    });
+
+  });
+
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js
index 8c70370..4182b01 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/stringfield/StringFieldSpec.js
@@ -8,14 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("StringField", function() {
   var session, helper, field;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     field = createField(createModel());
     jasmine.Ajax.install();
     jasmine.clock().install();
@@ -228,7 +227,7 @@
       var selection = field._getSelection();
       expect(selection.start).toBe(0);
       expect(selection.end).toBe(5);
-      field._renderDisplayText('foo');
+      field.setDisplayText('foo');
 
       selection = field._getSelection();
       expect(selection.start).toBe(0);
@@ -246,7 +245,7 @@
       field.trimText = true;
       field.render(session.$entryPoint);
       field.$field.val(' ' + longText + ' ');
-      field._renderDisplayText(longText);
+      field.setDisplayText(longText);
       expect(true).toBe(true);
     });
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
index 17e7ea3..ff9cfda 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe('TabBox', function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
   });
 
   function createTabBox(tabItems) {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabItemSpec.js
similarity index 66%
copy from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
copy to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabItemSpec.js
index 17e7ea3..c86f6e9 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tabbox/TabBoxSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tabbox/TabItemSpec.js
@@ -8,15 +8,14 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
-describe('TabBox', function() {
+describe('TabItem', function() {
   var session;
   var helper;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
   });
 
   function createTabBox(tabItems) {
@@ -36,26 +35,28 @@
     return createAdapter(model, session, tabItems);
   }
 
-  describe('render', function() {
+  describe('_renderStatusVisible', function() {
     var field;
 
     beforeEach(function() {
       var groupBox = helper.createFieldModel('TabItem');
+      groupBox.label = 'Foo';
       field = createTabBox([groupBox]);
     });
 
-    it('does NOT call layout for the selected tab on initialization', function() {
-      spyOn(session.layoutValidator, 'invalidateTree').and.callThrough();
+    it('invalidates tabarea if status visibility changes', function() {
       field.render(session.$entryPoint);
-      expect(session.layoutValidator.invalidateTree).not.toHaveBeenCalled();
-    });
+      field.validateLayout();
+      expect(scout.HtmlComponent.get(field._$tabArea).valid).toBe(true);
+      expect(field.tabItems[0]._computeStatusVisible()).toBe(false);
 
-    it('must not create LogicalGridData for tab items', function() {
-      field.render(session.$entryPoint);
-      // See TabItem.js for the reason for this spec
-      expect(field.tabItems[0].htmlComp.layoutData).toBe(null);
+      // TabArea needs to be invalidated, it may necessary to show ellipsis now because status got visible
+      field.tabItems[0].setTooltipText('test');
+      expect(field.tabItems[0]._computeStatusVisible()).toBe(true);
+      expect(scout.HtmlComponent.get(field._$tabArea).valid).toBe(false);
     });
 
   });
 
+
 });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js
index 1a7532e..9f117ef 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/tablefield/TableFieldSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper, FormSpecHelper */
 describe("TableField", function() {
   var session;
   var helper;
@@ -17,8 +16,8 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    tableHelper = new TableSpecHelper(session);
-    helper = new FormSpecHelper(session);
+    tableHelper = new scout.TableSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js
new file mode 100644
index 0000000..4d0254d
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("WrappedForm", function() {
+  var session;
+  var helper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new scout.FormSpecHelper(session);
+  });
+
+  function createField(model) {
+    var field = new scout.WrappedFormField();
+    field.init(model);
+    return field;
+  }
+
+  function createModel() {
+    return helper.createFieldModel('WrappedFormField');
+  }
+
+  describe("mandatory indicator", function() {
+
+    // Must not contain an indicator to prevent a double indicator if the first field is mandatory too
+    it("does not exist", function() {
+      var model = createModel();
+      model.mandatory = true;
+      var field = createField(model);
+      field.render(session.$entryPoint);
+
+      expect(field.$mandatory).toBeUndefined();
+    });
+
+  });
+
+  describe("test initial focus disabled", function() {
+    it("string field in inner form hasn't focus", function() {
+      var model = createModel();
+      var innerForm = helper.createFormWithOneField();
+
+      model.innerForm = innerForm;
+
+      var field = createField(model);
+      expect(field.initialFocusEnabled).toBe(false);
+
+      field.render(session.$entryPoint);
+
+      var $stringField = innerForm.rootGroupBox.fields[0].$field;
+      expect(scout.focusUtils.isActiveElement($stringField)).toBe(false);
+    });
+  });
+
+  describe("test initial focus enabled", function() {
+    it("string field in inner form has focus", function() {
+      var model = createModel();
+      var innerForm = helper.createFormWithOneField();
+
+      model.initialFocusEnabled = true;
+      model.innerForm = innerForm;
+
+      var field = createField(model);
+      expect(field.initialFocusEnabled).toBe(true);
+
+      field.render(session.$entryPoint);
+
+      var $stringField = innerForm.rootGroupBox.fields[0].$field;
+      expect(scout.focusUtils.isActiveElement($stringField)).toBe(true);
+    });
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/HtmlComponentSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/HtmlComponentSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/HtmlComponentSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/HtmlComponentSpec.js
index 73281d2..1868958 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/HtmlComponentSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/HtmlComponentSpec.js
@@ -78,7 +78,7 @@
     beforeEach(function() {
       $comp = $('<div>').appendTo(session.$entryPoint);
       htmlComp = new scout.HtmlComponent($comp, session);
-      htmlComp._layout = new LayoutMock();
+      htmlComp.layout = new LayoutMock();
     });
 
     it("accepts scout.Dimension as single argument", function() {
@@ -92,9 +92,9 @@
     });
 
     it("calls invalidate on layout when size has changed", function() {
-      spyOn(htmlComp._layout, 'invalidate');
+      spyOn(htmlComp.layout, 'invalidate');
       htmlComp.setSize(new scout.Dimension(1, 2));
-      expect(htmlComp._layout.invalidate).toHaveBeenCalled();
+      expect(htmlComp.layout.invalidate).toHaveBeenCalled();
     });
 
   });
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/LayoutValidatorSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/LayoutValidatorSpec.js
new file mode 100644
index 0000000..387ba30
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/LayoutValidatorSpec.js
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe("LayoutValidator", function() {
+  var session;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    session.layoutValidator.validate();
+    // Remove root component
+    session.desktop.$container.removeData('htmlComponent');
+  });
+
+  describe("invalidateTree", function() {
+
+    it("keeps track of invalid html components", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+
+      htmlComp.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+    });
+
+    it("considers only the topmost component", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+
+      var $compChild = $('<div>').appendTo($comp);
+      var htmlCompChild = new scout.HtmlComponent($compChild, session);
+
+      htmlCompChild.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+    });
+
+    it("and validate roots", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      new scout.HtmlComponent($comp, session);
+
+      var $compChild = $('<div>').appendTo($comp);
+      var htmlCompChild = new scout.HtmlComponent($compChild, session);
+      htmlCompChild.validateRoot = true;
+
+      htmlCompChild.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlCompChild);
+    });
+
+    it("makes sure parent components are put in front of child components", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+      var $grandchild = $comp.appendDiv().appendDiv();
+      var htmlGrandChild = new scout.HtmlComponent($grandchild, session);
+
+      htmlGrandChild.invalidateLayoutTree(false);
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlGrandChild);
+
+      htmlComp.invalidateLayoutTree(false);
+      expect(session.layoutValidator._invalidComponents.length).toBe(2);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+      expect(session.layoutValidator._invalidComponents[1]).toBe(htmlGrandChild);
+    });
+  });
+
+  describe("validate", function() {
+
+    it("calls validateLayout for each invalid html component", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+      spyOn(htmlComp, 'validateLayout');
+
+      htmlComp.invalidateLayoutTree();
+      session.layoutValidator.validate();
+      expect(htmlComp.validateLayout).toHaveBeenCalled();
+      expect(htmlComp.validateLayout.calls.count()).toEqual(1);
+    });
+
+    it("does not call validateLayout if component has been removed", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+      spyOn(htmlComp, 'validateLayout');
+
+      htmlComp.invalidateLayoutTree();
+      $comp.remove();
+      session.layoutValidator.validate();
+      expect(htmlComp.validateLayout).not.toHaveBeenCalled();
+    });
+
+    it("does not call validateLayout if component has been detached, but does not remove from invalid components either", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+      spyOn(htmlComp, 'validateLayout');
+
+      htmlComp.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+
+      $comp.detach();
+      session.layoutValidator.validate();
+      expect(htmlComp.validateLayout).not.toHaveBeenCalled();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+    });
+
+    it("removes the component from the list of invalidate components after validation", function() {
+      var $comp = $('<div>').appendTo(session.$entryPoint);
+      var htmlComp = new scout.HtmlComponent($comp, session);
+      spyOn(htmlComp, 'validateLayout');
+
+      htmlComp.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
+
+      session.layoutValidator.validate();
+      expect(htmlComp.validateLayout).toHaveBeenCalled();
+      expect(htmlComp.validateLayout.calls.count()).toEqual(1);
+      expect(session.layoutValidator._invalidComponents.length).toBe(0);
+    });
+
+  });
+
+  describe("cleanupInvalidObjects", function() {
+
+    it("removes the widget from invalid components when a widget gets removed", function() {
+      var widget = scout.create('StringField', {
+        parent: new scout.NullWidget(),
+        session: session
+      });
+      widget.render(session.$entryPoint);
+
+      widget.invalidateLayoutTree();
+      expect(session.layoutValidator._invalidComponents.length).toBe(1);
+      expect(session.layoutValidator._invalidComponents[0]).toBe(widget.htmlComp);
+
+      widget.remove();
+      expect(session.layoutValidator._invalidComponents.length).toBe(0);
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/LogicalGridLayoutInfoSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/LogicalGridLayoutInfoSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/LogicalGridLayoutInfoSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/LogicalGridLayoutInfoSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/graphicsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/graphicsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/graphicsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/layout/graphicsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/mainSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/mainSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/mainSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/mainSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/ContextMenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/ContextMenuSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/ContextMenuSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/ContextMenuSpec.js
index 943e235..e14eae3 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/ContextMenuSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/ContextMenuSpec.js
@@ -8,14 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global MenuSpecHelper */
 describe("ContextMenuSpec", function() {
   var helper, session;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new MenuSpecHelper(session);
+    helper = new scout.MenuSpecHelper(session);
   });
 
   describe('renderMenuItems', function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuBarSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuBarSpec.js
similarity index 79%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuBarSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuBarSpec.js
index 8e36aeb..27d8dd2 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuBarSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuBarSpec.js
@@ -8,17 +8,16 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global MenuSpecHelper */
 describe("MenuBar", function() {
   var helper, session;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new MenuSpecHelper(session);
+    helper = new scout.MenuSpecHelper(session);
   });
 
-  describe('updateItems', function() {
+  describe('setMenuItems', function() {
 
     it('prefers EmptySpace for the left position if menu has multiple menuTypes', function() {
       var menu1 = helper.createMenu(helper.createModel('multi')),
@@ -34,7 +33,7 @@
       menu2.menuTypes = ['Table.SingleSelection'];
 
       menuBar.render(session.$entryPoint);
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
 
       expect(menuBar.menuItems.length).toBe(3); // 2 + separator
       expect(menuBar.menuItems[0]).toBe(menu1);
@@ -56,7 +55,7 @@
       menu2.menuTypes = ['Table.SingleSelection'];
 
       menuBar.render(session.$entryPoint);
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
 
       // a separator must be added between EmptySpace and Selection Menus
       expect(menuBar.menuItems.length).toBe(3);
@@ -67,7 +66,7 @@
       // when menu-bar is updated, the old separator must be destroyed
       // and a new separator with different ID should be created
       menus = [menu1, menu3];
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
       expect(separator.destroyed).toBe(true);
       expect(separator.id).not.toBe(menuBar.menuItems[1].id);
     });
@@ -87,7 +86,7 @@
         menus = [menu1, menu2];
 
       menuBar.render(session.$entryPoint);
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
 
       // <fix for layout issues>
       // Menu item DIVs are too wide, because in Jasmine tests there are no CSS rules. Therefore, all
@@ -122,7 +121,7 @@
       menu2.visible = false;
 
       menuBar.render(session.$entryPoint);
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
 
       expect(menuBar.menuItems.length).toBe(2);
       expect(menuBar.menuItems[0]).toBe(menu1);
@@ -148,7 +147,7 @@
       menu2.visible = true;
 
       menuBar.render(session.$entryPoint);
-      menuBar.updateItems(menus);
+      menuBar.setMenuItems(menus);
 
       expect(menuBar.menuItems.length).toBe(2);
       expect(menuBar.menuItems[0]).toBe(menu1);
@@ -158,4 +157,35 @@
 
   });
 
+  describe('layout', function() {
+    it('gets invalidated if a menu changes its visibility', function() {
+      var menu1 = helper.createMenu(helper.createModel('foo')),
+        menu2 = helper.createMenu(helper.createModel('bar')),
+        menuBar = scout.create('MenuBar', {
+          parent: new scout.NullWidget(),
+          session: session,
+          menuOrder: new scout.MenuItemsOrder(session, 'Table')
+        }),
+        menus = [menu1, menu2];
+
+      menu1.visible = true;
+      menu2.visible = true;
+      menuBar.setMenuItems(menus);
+      menuBar.render(session.$entryPoint);
+      menuBar.$right.setVisible(false); // Right box should not influence the layout (due to missing css)
+      menuBar.htmlComp.setSize(new scout.Dimension(500, 50));
+
+      expect(menu1.$container.isVisible()).toBe(true);
+      expect(scout.HtmlComponent.get(menuBar.$container).valid).toBe(true);
+
+      var event = createPropertyChangeEvent(menu1, {
+        "visible": false
+      });
+      menu1.onModelPropertyChange(event);
+
+      expect(menu1.$container.isVisible()).toBe(false);
+      expect(scout.HtmlComponent.get(menuBar.$container).valid).toBe(false);
+    });
+  });
+
 });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuItemsOrderSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuItemsOrderSpec.js
similarity index 92%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuItemsOrderSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuItemsOrderSpec.js
index acace98..11c952a 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuItemsOrderSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuItemsOrderSpec.js
@@ -16,6 +16,9 @@
     setFixtures(sandbox());
     session = sandboxSession();
     menuItemsOrder = new scout.MenuItemsOrder(session, 'Table');
+    var nullWidget = new scout.NullWidget();
+    nullWidget.session = session;
+    menuItemsOrder.menuBar = nullWidget;
   });
 
   it("_createSeparator", function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuSpec.js
index 8361cc4..2fdef45 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/MenuSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/MenuSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global MenuSpecHelper */
 describe("Menu", function() {
 
   var helper, session, $sandbox, modelMenu1, modelMenu2, menu1, menu2;
@@ -17,7 +16,7 @@
     setFixtures(sandbox());
     session = sandboxSession();
     $sandbox = $('#sandbox');
-    helper = new MenuSpecHelper(session);
+    helper = new scout.MenuSpecHelper(session);
     modelMenu1 = helper.createModel('foo');
     menu1 = helper.createMenu(modelMenu1);
     modelMenu2 = helper.createModel('foo');
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/menusSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/menusSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/menusSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/menusSpec.js
index b576396..233f2c5 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/menu/menusSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/menu/menusSpec.js
@@ -8,14 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global MenuSpecHelper */
 describe("menus", function() {
   var helper, session;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new MenuSpecHelper(session);
+    helper = new scout.MenuSpecHelper(session);
   });
 
   describe("filter", function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/planner/PlannerSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/planner/PlannerSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/planner/PlannerSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/planner/PlannerSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/scrollbar/scrollbarsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/scrollbar/scrollbarsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/scrollbar/scrollbarsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/scrollbar/scrollbarsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/ModelAdapterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/ModelAdapterSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/ModelAdapterSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/ModelAdapterSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/session/ResponseQueueSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/ResponseQueueSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/session/ResponseQueueSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/ResponseQueueSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/session/SessionSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/SessionSpec.js
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/session/SessionSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/SessionSpec.js
index 343a241..714a7ea 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/session/SessionSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/SessionSpec.js
@@ -8,6 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
+/*global receiveResponseForAjaxCall */
 describe('Session', function() {
 
   beforeEach(function() {
@@ -332,7 +333,7 @@
       expect(requestData.startup).toBeUndefined();
     });
 
-    it('sends user agent on startup if not desktop', function() {
+    it('sends user agent on startup', function() {
       var session = createSession(new scout.UserAgent(scout.Device.Type.MOBILE));
 
       session.init();
@@ -342,22 +343,12 @@
       var requestData = mostRecentJsonRequest();
       expect(requestData.userAgent.deviceType).toBe('MOBILE');
 
-      //don't send it on subsequent requests
+      // don't send it on subsequent requests
       send(session, 1, 'nodeClicked');
       sendQueuedAjaxCalls();
 
       requestData = mostRecentJsonRequest();
       expect(requestData.userAgent).toBeUndefined();
-
-      //device type desktop is the default, so don't send it
-      session = createSession(new scout.UserAgent(scout.Device.Type.DESKTOP));
-
-      session.init();
-      uninstallUnloadHandlers(session);
-      sendQueuedAjaxCalls();
-
-      requestData = mostRecentJsonRequest();
-      expect(requestData.userAgent).toBeUndefined();
     });
 
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/session/TextsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/TextsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/session/TextsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/session/TextsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFilterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFilterSpec.js
similarity index 99%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFilterSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFilterSpec.js
index a95a1a1..d80d0fa 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFilterSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFilterSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe("Table Filter", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFooterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFooterSpec.js
similarity index 93%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFooterSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFooterSpec.js
index 500c1f3..3519a22 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableFooterSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableFooterSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe("TableFooterSpec", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
@@ -31,8 +30,8 @@
 
     it("attaches listener to the table but only once", function() {
       var model = helper.createModelFixture(2);
+      model.tableStatusVisible = true;
       var table = helper.createTable(model);
-      table.tableStatusVisible = true;
       table.render(session.$entryPoint);
       expect(table.footer).not.toBeUndefined();
       var listenerCount = table.events._eventListeners.length;
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderMenuSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderMenuSpec.js
similarity index 99%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderMenuSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderMenuSpec.js
index 431d9aa..a4319e7 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderMenuSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderMenuSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe('TableHeaderMenu', function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderSpec.js
similarity index 95%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderSpec.js
index 9a7b43b..11b8805 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableHeaderSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableHeaderSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe("TableHeaderSpec", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableKeyStrokesSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableKeyStrokesSpec.js
similarity index 99%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableKeyStrokesSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableKeyStrokesSpec.js
index 63e262d..c8a427d 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableKeyStrokesSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableKeyStrokesSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper */
 describe("TableKeyStrokes", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableSpec.js
similarity index 95%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableSpec.js
index 4f20b17..846539b 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/TableSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/TableSpec.js
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper, LocaleSpecHelper */
+/* global removePopups */
 describe("Table", function() {
   var session;
   var helper;
@@ -16,8 +16,8 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    session.locale = new LocaleSpecHelper().createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
-    helper = new TableSpecHelper(session);
+    session.locale = new scout.LocaleSpecHelper().createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
@@ -660,6 +660,87 @@
     });
   });
 
+  describe("doRowAction", function() {
+
+    it("sends rowAction event with row and column", function() {
+      var model = helper.createModelFixture(2, 5);
+      var table = helper.createTable(model);
+      var row0 = table.rows[0];
+      var column0 = table.columns[0];
+
+      table.selectedRows = [row0];
+      table.render(session.$entryPoint);
+      table.doRowAction(row0, column0);
+
+      sendQueuedAjaxCalls();
+
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+      expect(mostRecentJsonRequest().events.length).toBe(1);
+
+      var event = new scout.Event(table.id, 'rowAction', {
+        columnId: column0.id,
+        rowId: row0.id
+      });
+      expect(mostRecentJsonRequest()).toContainEvents(event);
+    });
+
+    it("does not send rowAction event if the row is not selected", function() {
+      var model = helper.createModelFixture(2, 5);
+      var table = helper.createTable(model);
+      var row0 = table.rows[0];
+      var column0 = table.columns[0];
+
+      // no selection at all
+      table.selectedRows = [];
+      table.render(session.$entryPoint);
+      table.doRowAction(row0, column0);
+
+      sendQueuedAjaxCalls();
+
+      expect(jasmine.Ajax.requests.count()).toBe(0);
+
+      // other row selected
+      table.selectedRows = [table.rows[1]];
+      table.doRowAction(row0, column0);
+
+      sendQueuedAjaxCalls();
+
+      expect(jasmine.Ajax.requests.count()).toBe(0);
+
+      // correct row selected -> expect event
+      table.selectedRows = [row0];
+      table.doRowAction(row0, column0);
+
+      sendQueuedAjaxCalls();
+
+      expect(jasmine.Ajax.requests.count()).toBe(1);
+      expect(mostRecentJsonRequest().events.length).toBe(1);
+
+      var event = new scout.Event(table.id, 'rowAction', {
+        columnId: column0.id,
+        rowId: row0.id
+      });
+      expect(mostRecentJsonRequest()).toContainEvents(event);
+    });
+
+    it("does not send rowAction event if it is not the only one selected row", function() {
+      var model = helper.createModelFixture(2, 5);
+      var table = helper.createTable(model);
+      var row0 = table.rows[0];
+      var column0 = table.columns[0];
+
+      // no selection at all
+      table.selectedRows = [row0, table.rows[1]];
+      table.render(session.$entryPoint);
+      table.doRowAction(row0, column0);
+
+      sendQueuedAjaxCalls();
+
+      expect(jasmine.Ajax.requests.count()).toBe(0);
+    });
+
+  });
+
   describe("resizeColumn", function() {
 
     it("updates column model and sends resize event ", function() {
@@ -731,7 +812,7 @@
       table.onModelPropertyChange(event);
 
       // Triggers TableLayout._layoutColumns()
-      session.layoutValidator.validate();
+      table.revalidateLayout();
 
       expect(table.columns[0].width).toBe(150);
       expect(table.columns[1].width).toBe(300);
@@ -754,7 +835,7 @@
       table.onModelPropertyChange(event);
 
       // Triggers TableLayout._layoutColumns()
-      session.layoutValidator.validate();
+      table.revalidateLayout();
 
       expect(table.columns[0].width).toBe(100);
       expect(table.columns[1].width).toBe(350);
@@ -774,7 +855,7 @@
       table.onModelPropertyChange(event);
 
       // Triggers TableLayout._layoutColumns()
-      session.layoutValidator.validate();
+      table.revalidateLayout();
 
       expect(table.columns[0].width).toBe(450 - scout.Column.DEFAULT_MIN_WIDTH);
       expect(table.columns[1].width).toBe(scout.Column.DEFAULT_MIN_WIDTH);
@@ -1120,7 +1201,7 @@
 
         // In order to change Collator at runtime, we must reset the "static" property
         // since it is set only once
-        session.locale = new LocaleSpecHelper().createLocale('sv');
+        session.locale = new scout.LocaleSpecHelper().createLocale('sv');
         helper.resetIntlCollator();
 
         table.sort(column0, 'desc');
@@ -1156,6 +1237,42 @@
         helper.assertDatesInCells(table.rows, 0, [new Date('1999-01-10'), new Date('2012-08-10'), new Date('2014-03-01')]);
       });
 
+      it("uses non sort columns as fallback", function() {
+        if (!scout.device.supportsInternationalization()) {
+          return;
+        }
+
+        var model = helper.createModelFixture(2, 4);
+        var table = helper.createTable(model);
+        model.rows[0].cells[0].value = 'zzz';
+        model.rows[0].cells[1].value = 'same';
+        model.rows[1].cells[0].value = 'aaa';
+        model.rows[1].cells[1].value = 'other';
+        model.rows[2].cells[0].value = 'ccc';
+        model.rows[2].cells[1].value = 'other';
+        model.rows[3].cells[0].value = 'qqq';
+        model.rows[3].cells[1].value = 'same';
+
+        column0 = model.columns[0];
+        column1 = model.columns[1];
+        table.render(session.$entryPoint);
+
+        expect(column0.sortAscending).toBe(true);
+        table.sort(column1, 'asc');
+        helper.assertValuesInCells(table.rows, 0, ['aaa', 'ccc', 'qqq', 'zzz']);
+        helper.assertValuesInCells(table.rows, 1, ['other', 'other', 'same', 'same']);
+
+        table.sort(column1, 'desc');
+        helper.assertValuesInCells(table.rows, 0, ['qqq', 'zzz', 'aaa', 'ccc']);
+        helper.assertValuesInCells(table.rows, 1, ['same', 'same', 'other', 'other']);
+
+        // sortAscending of a column with sortActive = false shouldn't have any effect
+        column0.sortAscending = false;
+        table.sort(column1, 'asc');
+        helper.assertValuesInCells(table.rows, 0, ['aaa', 'ccc', 'qqq', 'zzz']);
+        helper.assertValuesInCells(table.rows, 1, ['other', 'other', 'same', 'same']);
+      });
+
     });
 
   });
@@ -1738,7 +1855,7 @@
 
     afterEach(function() {
       // Close context menus
-      $('body').triggerClick();
+      removePopups(session);
     });
 
     it("opens context menu", function() {
@@ -2288,9 +2405,9 @@
         session._processSuccessResponse(message);
 
         var $rows = table.$rows();
-        expect($rows.eq(0).attr('data-rowid')).toBe(model.rows[2].id);
-        expect($rows.eq(1).attr('data-rowid')).toBe(model.rows[1].id);
-        expect($rows.eq(2).attr('data-rowid')).toBe(model.rows[0].id);
+        expect($rows.eq(0).data('row').id).toBe(model.rows[2].id);
+        expect($rows.eq(1).data('row').id).toBe(model.rows[1].id);
+        expect($rows.eq(2).data('row').id).toBe(model.rows[0].id);
       });
 
       it("does not animate ordering for newly inserted rows", function() {
@@ -2319,7 +2436,7 @@
         var $rows = table.$rows();
         $rows.each(function() {
           var $row = $(this);
-          var rowId = $row.attr('data-rowid');
+          var rowId = $row.data('row').id;
           if (rowId === newRows[0].id || rowId === newRows[1].id) {
             expect($row.is(':animated')).toBe(false);
           } else {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/BooleanColumSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/BooleanColumSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/BooleanColumSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/BooleanColumSpec.js
index 4adce42..7418210 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/BooleanColumSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/BooleanColumSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper */
 describe('BooleanColumn', function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/ColumnSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/ColumnSpec.js
similarity index 95%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/ColumnSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/ColumnSpec.js
index 2620829..c165d81 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/columns/ColumnSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/columns/ColumnSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper */
 describe("Column", function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
@@ -274,29 +273,21 @@
     var imageLevel50 = 'linear-gradient(to left, ' + barChartColor + ' 0%, ' + barChartColor + ' 50%, transparent 50%, transparent 100%)';
     var defaultBackgroundColor;
 
-    scout.styles.get = function style(cssClass) {
-      if (cssClass === 'column-background-effect-gradient1-start') {
-        return {
-          backgroundColor: rgbLevel0
-        };
-      } else if (cssClass === 'column-background-effect-gradient1-end') {
-        return {
-          backgroundColor: rgbLevel100
-        };
-      } else if (cssClass === 'column-background-effect-gradient2-start') {
-        return {
-          backgroundColor: rgbLevel100
-        };
-      } else if (cssClass === 'column-background-effect-gradient2-end') {
-        return {
-          backgroundColor: rgbLevel0
-        };
-      } else if (cssClass === 'column-background-effect-bar-chart') {
-        return {
-          backgroundColor: barChartColor
-        };
-      }
-    };
+    scout.styles.put('column-background-effect-gradient1-start', {
+      backgroundColor: rgbLevel0
+    });
+    scout.styles.put('column-background-effect-gradient1-end', {
+      backgroundColor: rgbLevel100
+    });
+    scout.styles.put('column-background-effect-gradient2-start', {
+      backgroundColor: rgbLevel100
+    });
+    scout.styles.put('column-background-effect-gradient2-end',  {
+      backgroundColor: rgbLevel0
+    });
+    scout.styles.put('column-background-effect-bar-chart', {
+      backgroundColor: barChartColor
+    });
 
     beforeEach(function() {
       var $div = $('<div>').appendTo(session.$entryPoint);
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/AggregateTableControlSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/AggregateTableControlSpec.js
similarity index 94%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/AggregateTableControlSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/AggregateTableControlSpec.js
index ad2eed8..7603439 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/AggregateTableControlSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/AggregateTableControlSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper, LocaleSpecHelper */
 describe("AggregateTableControl", function() {
   var session;
   var helper;
@@ -16,8 +15,8 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    session.locale = new LocaleSpecHelper().createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
-    helper = new TableSpecHelper(session);
+    session.locale = new scout.LocaleSpecHelper().createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
+    helper = new scout.TableSpecHelper(session);
 
     jasmine.Ajax.install();
     jasmine.clock().install();
@@ -90,7 +89,7 @@
 
       tableControl = createAggregateTC(createModel(table));
       tableControl.selected = true;
-      table.tableControls = [tableControl];
+      table._syncTableControls([tableControl]);
 
       column0 = model.columns[0];
       column1 = model.columns[1];
@@ -175,7 +174,7 @@
       tcModel.enabled = true;
       tcModel.selected = true;
       tableControl = createAggregateTC(createModel(table));
-      table.tableControls = [tableControl];
+      table._syncTableControls([tableControl]);
       table.render(session.$entryPoint);
 
       expect(tableControl.enabled).toBe(false);
@@ -198,7 +197,7 @@
       tcModel.enabled = false;
       tcModel.selected = true;
       tableControl = createAggregateTC(tcModel);
-      table.tableControls = [tableControl];
+      table._syncTableControls([tableControl]);
       table.render(session.$entryPoint);
 
       expect(tableControl.enabled).toBe(true);
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/TableControlSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/TableControlSpec.js
similarity index 89%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/TableControlSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/TableControlSpec.js
index d8b149b..0e165cc 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/controls/TableControlSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/controls/TableControlSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper */
 describe("TableControl", function() {
   var session;
   var tableHelper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    tableHelper = new TableSpecHelper(session);
+    tableHelper = new scout.TableSpecHelper(session);
 
     jasmine.Ajax.install();
     jasmine.clock().install();
@@ -38,23 +37,9 @@
     return model;
   }
 
-  function createFormMock() {
-    var form = {
-      render: function() {},
-      remove: function() {},
-      $container: $('<div>'),
-      rootGroupBox: {
-        fields: []
-      }
-    };
-    form.htmlComp = new scout.HtmlComponent(form.$container, session);
-    return form;
-  }
-
   function createAction(model) {
     var action = new scout.TableControl();
     action.init(model);
-    action.form = createFormMock();
     return action;
   }
 
@@ -83,7 +68,7 @@
 
       it("opens and closes the control container", function() {
         var action = createAction(createModel());
-        table.tableControls = [action];
+        table._syncTableControls([action]);
         table.render(session.$entryPoint);
         var $controlContainer = table.footer.$controlContainer;
 
@@ -105,7 +90,7 @@
       it("removes the content of the previous selected control without closing the container", function() {
         var action = createAction(createModel());
         var action2 = createAction(createModel());
-        table.tableControls = [action, action2];
+        table._syncTableControls([action, action2]);
 
         action.selected = true;
         table.render(session.$entryPoint);
@@ -155,7 +140,7 @@
     it("removes the content of the previous selected control without closing the container", function() {
       var action = createAction(createModel());
       var action2 = createAction(createModel());
-      table.tableControls = [action, action2];
+      table._syncTableControls([action, action2]);
 
       action.selected = true;
       table.render(session.$entryPoint);
@@ -177,7 +162,7 @@
     it("sends selected events (for current and previous selection)", function() {
       var action = createAction(createModel());
       var action2 = createAction(createModel());
-      table.tableControls = [action, action2];
+      table._syncTableControls([action, action2]);
 
       action.selected = true;
       table.render(session.$entryPoint);
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/editor/CellEditorPopupSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/editor/CellEditorPopupSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/editor/CellEditorPopupSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/editor/CellEditorPopupSpec.js
index abebb9f..0597d85 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/editor/CellEditorPopupSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/editor/CellEditorPopupSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper, FormSpecHelper */
 describe("CellEditor", function() {
   var session;
   var helper;
@@ -17,8 +16,8 @@
   beforeEach(function() {
     setFixtures(sandboxDesktop());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
-    formHelper = new FormSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
+    formHelper = new scout.FormSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js
index f904982..2882f16 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/DateColumnUserFilterSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe('DateColumnUserFilter', function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
   });
 
   afterEach(function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js
index 3694f78..7a3f14b 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/table/userfilter/TableTextUserFilterSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global TableSpecHelper*/
 describe('TableTextUserFilter', function() {
   var session;
   var helper;
@@ -16,7 +15,7 @@
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new TableSpecHelper(session);
+    helper = new scout.TableSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DateFormatSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DateFormatSpec.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DateFormatSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DateFormatSpec.js
index cdb7087..f8e1283 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DateFormatSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DateFormatSpec.js
@@ -8,15 +8,14 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global LocaleSpecHelper */
 describe("DateFormat", function() {
   var locale;
   var helper;
 
   beforeEach(function() {
     setFixtures(sandbox());
-    helper = new LocaleSpecHelper();
-    locale = helper.createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+    helper = new scout.LocaleSpecHelper();
+    locale = helper.createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
   });
 
   afterEach(function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DecimalFormatSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DecimalFormatSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js
index 2efd9c0..aa2f1b1 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/text/DecimalFormatSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js
@@ -8,15 +8,14 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global LocaleSpecHelper */
 describe("DecimalFormat", function() {
   var locale;
   var helper;
 
   beforeEach(function() {
     setFixtures(sandbox());
-    helper = new LocaleSpecHelper();
-    locale = helper.createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+    helper = new scout.LocaleSpecHelper();
+    locale = helper.createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
   });
 
   afterEach(function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/tooltip/TooltipSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tooltip/TooltipSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/tooltip/TooltipSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tooltip/TooltipSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/tooltipsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tooltip/tooltipsSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/tooltipsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tooltip/tooltipsSpec.js
index 59958ff..af98c6f 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/tooltipsSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tooltip/tooltipsSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global FormSpecHelper */
 describe("scout.tooltips", function() {
 
   var session, helper, formField, model;
@@ -18,7 +17,7 @@
 
     setFixtures(sandbox());
     session = sandboxSession();
-    helper = new FormSpecHelper(session);
+    helper = new scout.FormSpecHelper(session);
 
     // Add class desktop to sandbox, tooltip will be added to closest desktop
     session.$entryPoint.addClass('desktop');
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/CompactTreeSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/CompactTreeSpec.js
new file mode 100644
index 0000000..fd999d7
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/CompactTreeSpec.js
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+/* global TreeSpecHelper */
+describe("Compacttree", function() {
+  var session;
+  var helper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new TreeSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+    $.fx.off = true;
+  });
+
+  afterEach(function() {
+    session = null;
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+    $.fx.off = false;
+  });
+
+  describe("creation", function() {
+
+    it("adds no empty section node", function() {
+      //top-level node (section) is only rendered, if there are child nodes
+      var model = helper.createModelFixture(1);
+      var tree = helper.createCompactTree(model);
+      var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(0, 1));
+      tree.render(session.$entryPoint);
+      expect(tree.nodes.length).toBe(1);
+//      expect(tree.visibleNodesFlat.length).toBe(0);
+    });
+
+    it("adds a node with child node", function() {
+      var model = helper.createModelFixture(1,1, true);
+      var tree = helper.createCompactTree(model);
+      var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(0, 4));
+      tree.render(session.$entryPoint);
+      expect(tree.nodes.length).toBe(1);
+      expect(tree.visibleNodesFlat.length).toBe(2);
+    });
+
+    it("adds a node with child nodes in correct order", function() {
+      var model = helper.createModelFixture(2,1,true);
+      var tree = helper.createCompactTree(model);
+      var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(0, 5));
+      tree.render(session.$entryPoint);
+      expect(tree.nodes.length).toBe(2);
+      expect(tree.visibleNodesFlat.length).toBe(6);
+
+      //check $node
+      var firstNode = tree.nodes[0].$node.children();
+      expect($(firstNode[0]).hasClass("title")).toBe(true);
+      expect($(firstNode[0]).text()).toBe("node 0");
+      expect($(firstNode[1]).hasClass("section-node")).toBe(true);
+      expect($(firstNode[1]).text()).toBe("node 0_0");
+      expect($(firstNode[2]).hasClass("section-node")).toBe(true);
+      expect($(firstNode[2]).text()).toBe("node 0_1");
+    });
+
+    //deletion
+    it("deletes a node", function() {
+      var model = helper.createModelFixture(2,1,true);
+      var tree = helper.createCompactTree(model);
+      var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(0, 5));
+      tree.render(session.$entryPoint);
+      tree.deleteNodes([tree.nodes[0].childNodes[0]], tree.nodes[0]);
+      expect(tree.nodes.length).toBe(2);
+      expect(tree.visibleNodesFlat.length).toBe(5);
+
+      //check $node
+      var firstNode = tree.nodes[0].$node.children();
+      expect($(firstNode[0]).hasClass("title")).toBe(true);
+      expect($(firstNode[0]).text()).toBe("node 0");
+      expect($(firstNode[1]).hasClass("section-node")).toBe(true);
+      expect($(firstNode[1]).text()).toBe("node 0_1");
+    });
+
+    //insertions
+    it("inserts a child node", function() {
+      var model = helper.createModelFixture(2,1,true);
+      var tree = helper.createCompactTree(model);
+      var parent0 = tree.nodes[0];
+      var child0 = parent0.childNodes[0];
+      var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(0, 5));
+      tree.render(session.$entryPoint);
+      tree.deleteNodes([child0], parent0);
+      tree.insertNodes([child0], parent0);
+
+      expect(tree.nodes.length).toBe(2);
+      expect(tree.visibleNodesFlat.length).toBe(6);
+
+      //check $node
+      var firstNode = parent0.$node.children();
+      expect($(firstNode[0]).hasClass("title")).toBe(true);
+      expect($(firstNode[0]).text()).toBe("node 0");
+      expect($(firstNode[1]).hasClass("section-node")).toBe(true);
+      expect($(firstNode[1]).text()).toBe("node 0_0");
+      expect($(firstNode[2]).hasClass("section-node")).toBe(true);
+      expect($(firstNode[2]).text()).toBe("node 0_1");
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeKeyStrokesSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeKeyStrokesSpec.js
new file mode 100644
index 0000000..60d1666
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeKeyStrokesSpec.js
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+/* global TreeSpecHelper */
+describe("TreeKeyStrokes", function() {
+  var session;
+  var helper;
+
+  beforeEach(function() {
+    setFixtures(sandbox());
+    session = sandboxSession();
+    helper = new TreeSpecHelper(session);
+    jasmine.Ajax.install();
+    jasmine.clock().install();
+  });
+
+  afterEach(function() {
+    session = null;
+    jasmine.Ajax.uninstall();
+    jasmine.clock().uninstall();
+  });
+
+  describe("key up", function() {
+
+    it("selects the above node in collapsed tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node1 = model.nodes[1],
+        node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node2]);
+
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node1]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+    });
+
+    it("selects the above node node in expanded tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node1 = model.nodes[1],
+        node0Child2 = node0.childNodes[2],
+        node1Child0 = node1.childNodes[0],
+        node1Child1 = node1.childNodes[1];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node1Child1]);
+
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node1Child0]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node1]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0Child2]);
+    });
+
+    it("selects the last node if no node is selected yet", function() {
+      var model = helper.model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
+
+      var node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node2]);
+    });
+
+    it("selects the only node if there is only one", function() {
+      var model = helper.model = helper.createModelFixture(1, 0, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      tree.render(session.$entryPoint);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+
+      tree.deselectAll();
+
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+    });
+    it("does nothing if first node already is selected", function() {
+      var model = helper.model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
+
+      tree.render(session.$entryPoint);
+      var node0 = model.nodes[0];
+      helper.selectNodesAndAssert(tree, [node0]);
+      tree.$data.triggerKeyDown(scout.keys.UP);
+      helper.assertSelection(tree, [node0]);
+    });
+  });
+
+  describe("key down", function() {
+    it("selects the node below in collapsed tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node1 = model.nodes[1],
+        node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0]);
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node1]);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node2]);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node2]);
+    });
+
+    it("selects the first node if no row is selected yet", function() {
+      var model = helper.model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+
+      tree.render(session.$entryPoint);
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node0]);
+    });
+
+    it("selects the above node node in expanded tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node1 = model.nodes[1],
+        node0Child2 = node0.childNodes[2],
+        node1Child0 = node1.childNodes[0],
+        node1Child1 = node1.childNodes[1];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0Child2]);
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node1]);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node1Child0]);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node1Child1]);
+    });
+
+    it("selects the only node if there is only one", function() {
+      var model = helper.model = helper.createModelFixture(1, 0, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      tree.render(session.$entryPoint);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node0]);
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node0]);
+
+      tree.deselectAll();
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node0]);
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node0]);
+    });
+
+    it("does nothing if last node already is selected", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      var tree = helper.createTree(model);
+
+      var node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node2]);
+
+      tree.$data.triggerKeyDown(scout.keys.DOWN);
+      helper.assertSelection(tree, [node2]);
+    });
+  });
+
+  describe("Home", function() {
+    it("selects first node in collapsed tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node2]);
+
+      tree.$data.triggerKeyDown(scout.keys.HOME);
+      helper.assertSelection(tree, [node0]);
+    });
+    it("selects first node in expanded tree", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node0Child2 = node0.childNodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0Child2]);
+
+      tree.$data.triggerKeyDown(scout.keys.HOME);
+      helper.assertSelection(tree, [node0]);
+      tree._visitNodes(tree.nodes, function(node) {
+        expect(node.expanded).toBeFalsy();
+      });
+
+    });
+  });
+
+  describe("Subtract", function() {
+
+    it(" collapses a node", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0]);
+      expect(node0.expanded).toBeTruthy();
+
+      tree.$data.triggerKeyDown(scout.keys.SUBTRACT);
+      expect(node0.expanded).toBeFalsy();
+    });
+
+    it(" collapses a node and drill up", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0],
+        node0Child0 = node0.childNodes[0];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0Child0]);
+      expect(node0Child0.expanded).toBeTruthy();
+
+      tree.$data.triggerKeyDown(scout.keys.SUBTRACT);
+      expect(node0Child0.expanded).toBeFalsy();
+      tree.$data.triggerKeyDown(scout.keys.SUBTRACT);
+      helper.assertSelection(tree, [node0]);
+      expect(node0.expanded).toBeTruthy();
+      tree.$data.triggerKeyDown(scout.keys.SUBTRACT);
+      expect(node0.expanded).toBeFalsy();
+    });
+
+  });
+
+  describe("Add", function() {
+    it(" expands a node", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0]);
+      expect(node0.expanded).toBeFalsy();
+
+      tree.$data.triggerKeyDown(scout.keys.ADD);
+      expect(node0.expanded).toBeTruthy();
+    });
+
+    it(" expands a node and drill down", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0]);
+      expect(node0.expanded).toBeFalsy();
+
+      tree.$data.triggerKeyDown(scout.keys.ADD);
+      expect(node0.expanded).toBeTruthy();
+      tree.$data.triggerKeyDown(scout.keys.ADD);
+      helper.assertSelection(tree, [node0.childNodes[0]]);
+    });
+  });
+
+  describe("End", function() {
+    it(" jumps to last node", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      var node2 = model.nodes[2];
+
+      tree.render(session.$entryPoint);
+      helper.selectNodesAndAssert(tree, [node0]);
+      expect(node0.expanded).toBeFalsy();
+
+      tree.$data.triggerKeyDown(scout.keys.END);
+      helper.assertSelection(tree, [node2]);
+    });
+
+  });
+
+  describe("space", function() {
+
+    it("does nothing if no nodes are selected", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      model.checkable = true;
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      tree.checkNode(node0, true, false);
+      expect(node0.checked).toBeTruthy();
+      tree.render(session.$entryPoint);
+      tree.$data.triggerKeyDown(scout.keys.SPACE);
+
+      tree._visitNodes(tree.nodes, function(node) {
+        if (node === node0) {
+          expect(node.checked).toBeTruthy();
+        } else {
+          expect(node.checked).toBeFalsy();
+        }
+      });
+    });
+
+    it("checks the selected node ", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      model.checkable = true;
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      tree.render(session.$entryPoint);
+      expect(node0.checked).toBeFalsy();
+      helper.selectNodesAndAssert(tree, [node0]);
+
+      tree.$data.triggerKeyDown(scout.keys.SPACE);
+
+      tree._visitNodes(tree.nodes, function(node) {
+        if (node === node0) {
+          expect(node.checked).toBeTruthy();
+        } else {
+          expect(node.checked).toBeFalsy();
+        }
+      });
+    });
+
+    it("unchecks the selected node ", function() {
+      var model = helper.model = helper.createModelFixture(3, 1, false);
+      model.checkable = true;
+      var tree = helper.createTree(model);
+
+      var node0 = model.nodes[0];
+      tree.render(session.$entryPoint);
+      tree.checkNode(node0, true, false);
+      expect(node0.checked).toBeTruthy();
+      helper.selectNodesAndAssert(tree, [node0]);
+
+      tree.$data.triggerKeyDown(scout.keys.SPACE);
+
+      tree._visitNodes(tree.nodes, function(node) {
+        expect(node.checked).toBeFalsy();
+      });
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/tree/TreeSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpec.js
similarity index 64%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/tree/TreeSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpec.js
index 05adc93..38f150e 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/tree/TreeSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpec.js
@@ -8,14 +8,16 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
+/* global TreeSpecHelper */
 describe("Tree", function() {
   var session;
-
+  var helper;
   //TODO NBU-> write test for dynamical keystroke(menu) update.
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
+    helper = new TreeSpecHelper(session);
     jasmine.Ajax.install();
     jasmine.clock().install();
     $.fx.off = true;
@@ -28,162 +30,23 @@
     $.fx.off = false;
   });
 
-  function createModelFixture(nodeCount, depth, expanded) {
-    return createModel(createModelNodes(nodeCount, depth, expanded));
-  }
-
-  function createModel(nodes) {
-    var model = createSimpleModel('Tree', session);
-
-    if (nodes) {
-      model.nodes = nodes;
-    }
-    model.enabled = true;
-    return model;
-  }
-
-  function createModelNode(id, text, position) {
-    return {
-      id: id + '' || scout.objectFactory.createUniqueId(),
-      text: text,
-      childNodeIndex: position ? position : 0,
-      enabled: true,
-      checked: false
-    };
-  }
-
-  function createModelNodes(nodeCount, depth, expanded) {
-    return createModelNodesInternal(nodeCount, depth, expanded);
-  }
-
-  function createModelNodesInternal(nodeCount, depth, expanded, parentNode) {
-    if (!nodeCount) {
-      return;
-    }
-
-    var nodes = [],
-      nodeId;
-    if (!depth) {
-      depth = 0;
-    }
-    for (var i = 0; i < nodeCount; i++) {
-      nodeId = i;
-      if (parentNode) {
-        nodeId = parentNode.id + '_' + nodeId;
-      }
-      nodes[i] = createModelNode(nodeId, 'node ' + nodeId);
-      nodes[i].expanded = expanded;
-      if (depth > 0) {
-        nodes[i].childNodes = createModelNodesInternal(nodeCount, depth - 1, expanded, nodes[i]);
-      }
-    }
-    return nodes;
-  }
-
-  function createTree(model) {
-    var tree = new scout.Tree();
-    tree.init(model);
-    return tree;
-  }
-
-  function findAllNodes(tree) {
-    return tree.$container.find('.tree-node');
-  }
-
-  function createNodeExpandedEvent(model, nodeId, expanded) {
-    return {
-      target: model.id,
-      nodeId: nodeId,
-      expanded: expanded,
-      type: 'nodeExpanded'
-    };
-  }
-
-  function createNodesSelectedEvent(model, nodeIds) {
-    return {
-      target: model.id,
-      nodeIds: nodeIds,
-      type: 'nodesSelected'
-    };
-  }
-
-  function createNodesInsertedEvent(model, nodes, commonParentNodeId) {
-    return {
-      target: model.id,
-      commonParentNodeId: commonParentNodeId,
-      nodes: nodes,
-      type: 'nodesInserted'
-    };
-  }
-
-  function createNodesInsertedEventTopNode(model, nodes) {
-    return {
-      target: model.id,
-      nodes: nodes,
-      type: 'nodesInserted'
-    };
-  }
-
-  function createNodesDeletedEvent(model, nodeIds, commonParentNodeId) {
-    return {
-      target: model.id,
-      commonParentNodeId: commonParentNodeId,
-      nodeIds: nodeIds,
-      type: 'nodesDeleted'
-    };
-  }
-
-  function createAllChildNodesDeletedEvent(model, commonParentNodeId) {
-    return {
-      target: model.id,
-      commonParentNodeId: commonParentNodeId,
-      type: 'allChildNodesDeleted'
-    };
-  }
-
-  function createNodeChangedEvent(model, nodeId) {
-    return {
-      target: model.id,
-      nodeId: nodeId,
-      type: 'nodeChanged'
-    };
-  }
-
-  function createNodesUpdatedEvent(model, nodes) {
-    return {
-      target: model.id,
-      nodes: nodes,
-      type: 'nodesUpdated'
-    };
-  }
-
-  function createTreeEnabledEvent(model, enabled) {
-    return {
-      target: model.id,
-      type: 'property',
-      properties: {
-        enabled: enabled
-      }
-    };
-  }
-
   describe("creation", function() {
     it("adds nodes", function() {
 
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
-      expect(findAllNodes(tree).length).toBe(1);
+      expect(helper.findAllNodes(tree).length).toBe(1);
     });
 
     it("does not add notes if no nodes are provided", function() {
 
-      var model = createModelFixture();
-      var tree = createTree(model);
+      var model = helper.createModelFixture();
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
-      expect(findAllNodes(tree).length).toBe(0);
+      expect(helper.findAllNodes(tree).length).toBe(0);
     });
   });
 
@@ -195,8 +58,8 @@
     var node2;
 
     beforeEach(function() {
-      model = createModelFixture(3, 1, true);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 1, true);
+      tree = helper.createTree(model);
       node0 = tree.nodes[0];
       node1 = tree.nodes[1];
       node2 = tree.nodes[2];
@@ -205,7 +68,7 @@
     describe("inserting a child", function() {
 
       it("updates model", function() {
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 3);
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
         expect(tree.nodes.length).toBe(3);
         expect(Object.keys(tree.nodesMap).length).toBe(12);
 
@@ -217,35 +80,35 @@
 
       it("updates html document if parent is expanded", function() {
         tree.render(session.$entryPoint);
-
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 3);
-        expect(findAllNodes(tree).length).toBe(12);
+        tree.revalidateLayoutTree();
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        expect(helper.findAllNodes(tree).length).toBe(12);
 
         tree.insertNodes([newNode0Child3], node0);
-        expect(findAllNodes(tree).length).toBe(13);
+        expect(helper.findAllNodes(tree).length).toBe(13);
         expect(node0.childNodes[3].$node.text()).toBe(newNode0Child3.text);
       });
 
       it("updates html document on specific position", function() {
         tree.render(session.$entryPoint);
 
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 2);
-        var newNode0Child4 = createModelNode('0_4', 'newNode0Child4', 3);
-        expect(findAllNodes(tree).length).toBe(12);
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 2);
+        var newNode0Child4 = helper.createModelNode('0_4', 'newNode0Child4', 3);
+        expect(helper.findAllNodes(tree).length).toBe(12);
 
         tree.insertNodes([newNode0Child3, newNode0Child4], node0);
-        expect(findAllNodes(tree).length).toBe(14);
+        expect(helper.findAllNodes(tree).length).toBe(14);
         expect(node0.childNodes[2].$node.text()).toBe(newNode0Child3.text);
         expect(node0.childNodes[3].$node.text()).toBe(newNode0Child4.text);
         expect(node0.childNodes[3].$node.attr('data-level')).toBe('1');
         expect(node0.childNodes[3].$node.next().attr('data-level')).toBe('1');
         expect(node0.childNodes[3].$node.next().text()).toBe('node 0_2');
 
-        var newNode1Child3 = createModelNode('1_3', 'newNode1Child3', 1);
-        var newNode1Child4 = createModelNode('1_4', 'newNode1Child4', 2);
+        var newNode1Child3 = helper.createModelNode('1_3', 'newNode1Child3', 1);
+        var newNode1Child4 = helper.createModelNode('1_4', 'newNode1Child4', 2);
 
         tree.insertNodes([newNode1Child3, newNode1Child4]);
-        expect(findAllNodes(tree).length).toBe(16);
+        expect(helper.findAllNodes(tree).length).toBe(16);
         expect(tree.nodes[1].$node.prev().text()).toBe('node 0_2');
         expect(tree.nodes[1].$node.prev().attr('data-level')).toBe('1');
         expect(tree.nodes[1].$node.text()).toBe(newNode1Child3.text);
@@ -258,11 +121,11 @@
     });
 
     it("only updates the model if parent is collapsed", function() {
-      node0.expanded = false;
+      tree.setNodeExpanded(node0, false);
       tree.render(session.$entryPoint);
 
-      var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 3);
-      expect(findAllNodes(tree).length).toBe(9);
+      var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+      expect(helper.findAllNodes(tree).length).toBe(9);
 
       tree.insertNodes([newNode0Child3], node0);
       //Check that the model was updated correctly
@@ -271,27 +134,27 @@
       expect(Object.keys(tree.nodesMap).length).toBe(13);
 
       //Check that no dom manipulation happened
-      expect(findAllNodes(tree).length).toBe(9);
+      expect(helper.findAllNodes(tree).length).toBe(9);
       expect(node0.childNodes[3].$node).toBeUndefined();
     });
 
     it("expands the parent if parent.expanded = true and the new inserted nodes are the first child nodes", function() {
-      model = createModelFixture(3, 0, true);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 0, true);
+      tree = helper.createTree(model);
       node0 = model.nodes[0];
       node1 = model.nodes[1];
       node2 = model.nodes[2];
       tree.render(session.$entryPoint);
 
-      var newNode0Child3 = createModelNode('0_3', 'newNode0Child3');
+      var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3');
       var $node0 = node0.$node;
       // Even tough the nodes were created with expanded=true, the $node should not have
       // been rendered as expanded (because it has no children)
       expect($node0).not.toHaveClass('expanded');
-      expect(findAllNodes(tree).length).toBe(3);
+      expect(helper.findAllNodes(tree).length).toBe(3);
 
       tree.insertNodes([newNode0Child3], node0);
-      expect(findAllNodes(tree).length).toBe(4);
+      expect(helper.findAllNodes(tree).length).toBe(4);
       expect(node0.childNodes[0].$node.text()).toBe(newNode0Child3.text);
       expect($node0).toHaveClass('expanded');
     });
@@ -305,8 +168,8 @@
     var child0;
 
     beforeEach(function() {
-      model = createModelFixture(3, 3, false);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 3, false);
+      tree = helper.createTree(model);
       node0 = tree.nodes[0];
       child0 = node0.childNodes[0];
     });
@@ -351,13 +214,13 @@
 
         // Make sure child0 is not visible anymore
         tree.setNodeExpanded(node0, false);
-        expect(child0.$node).toBeFalsy();
+        expect(child0.attached).toBeFalsy();
 
         tree.updateNodes([child0Update]);
 
         // Mode state needs to be updated, $node is still node visible
         expect(child0.enabled).toBe(false);
-        expect(child0.$node).toBeFalsy();
+        expect(child0.attached).toBeFalsy();
 
         // Expand node -> node gets visible and needs to be disabled
         tree.setNodeExpanded(node0, true);
@@ -409,14 +272,14 @@
 
         // Make sure child0 is not visible anymore
         tree.setNodeExpanded(node0, false);
-        expect(child0.$node).toBeFalsy();
+        expect(child0.attached).toBeFalsy();
         expect(child0.enabled).toBe(true);
 
         tree.updateNodes([child0Update]);
 
         // Mode state needs to be updated, $node is still node visible
         expect(child0.enabled).toBe(false);
-        expect(child0.$node).toBeFalsy();
+        expect(child0.attached).toBeFalsy();
 
         // Expand node -> node gets visible and needs to be disabled
         tree.setNodeExpanded(node0, true);
@@ -434,8 +297,8 @@
 
     beforeEach(function() {
       // A large tree is used to properly test recursion
-      model = createModelFixture(3, 2, true);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 2, true);
+      tree = helper.createTree(model);
       node0 = tree.nodes[0];
       node1 = tree.nodes[1];
       node2 = tree.nodes[2];
@@ -457,15 +320,16 @@
       });
 
       it("updates html document", function() {
+        tree.setViewRangeSize(40);
         tree.render(session.$entryPoint);
 
         var node2Child0 = node2.childNodes[0];
 
-        expect(findAllNodes(tree).length).toBe(39);
+        expect(helper.findAllNodes(tree).length).toBe(39);
         expect(node2Child0.$node).toBeDefined();
 
         tree.deleteNodes([node2Child0], node2);
-        expect(findAllNodes(tree).length).toBe(35);
+        expect(helper.findAllNodes(tree).length).toBe(35);
         expect(node2Child0.$node).toBeUndefined();
 
         expect(node0.$node).toBeDefined();
@@ -474,6 +338,63 @@
         expect(node0.childNodes[2].$node).toBeDefined();
       });
 
+      it("considers view range (distinguishes between rendered and non rendered rows, adjusts viewRangeRendered)", function() {
+        //initial view range
+        model = helper.createModelFixture(6, 0, false);
+        tree = helper.createTree(model);
+        node0 = tree.nodes[0];
+        node1 = tree.nodes[1];
+        var lastNode = tree.nodes[5];
+
+        var spy = spyOn(tree, '_calculateCurrentViewRange').and.returnValue(new scout.Range(1, 4));
+        tree.render(session.$entryPoint);
+        expect(tree.viewRangeRendered).toEqual(new scout.Range(1, 4));
+        expect(tree.$nodes().length).toBe(3);
+        expect(tree.nodes.length).toBe(6);
+
+        // reset spy -> view range now starts from 0
+        spy.and.callThrough();
+        tree.viewRangeSize = 3;
+
+        // delete first (not rendered)
+        tree.deleteNodes([node0]);
+        expect(tree.viewRangeDirty).toBeTruthy();
+        tree._renderViewport();
+        expect(tree.viewRangeDirty).toBeFalsy();
+        expect(tree.viewRangeRendered).toEqual(new scout.Range(0, 3));
+        expect(tree.$nodes().length).toBe(3);
+        expect(tree.nodes.length).toBe(5);
+
+        // delete first rendered
+        tree.deleteNodes([node1]);
+        expect(tree.viewRangeDirty).toBeTruthy();
+        tree._renderViewport();
+        expect(tree.viewRangeDirty).toBeFalsy();
+        expect(tree.viewRangeRendered).toEqual(new scout.Range(0, 3));
+        expect(tree.$nodes().length).toBe(3);
+        expect(tree.nodes.length).toBe(4);
+
+        // delete last node not rendered
+        tree.deleteNodes([lastNode]);
+        expect(tree.viewRangeDirty).toBeTruthy();
+        tree._renderViewport();
+        expect(tree.viewRangeDirty).toBeFalsy();
+        expect(tree.viewRangeRendered).toEqual(new scout.Range(0, 3));
+        expect(tree.$nodes().length).toBe(3);
+        expect(tree.nodes.length).toBe(3);
+
+        // delete remaining (rendered) nodes
+        tree.deleteNodes([tree.nodes[0], tree.nodes[1], tree.nodes[2]]);
+        expect(tree.viewRangeDirty).toBeTruthy();
+        tree._renderViewport();
+        expect(tree.viewRangeDirty).toBeFalsy();
+        expect(tree.viewRangeRendered).toEqual(new scout.Range(0, 0));
+        expect(tree.$nodes().length).toBe(0);
+        expect(tree.nodes.length).toBe(0);
+        expect(tree.$fillBefore.height()).toBe(0);
+        expect(tree.$fillAfter.height()).toBe(0);
+      });
+
     });
 
     describe("deleting a root node", function() {
@@ -485,11 +406,13 @@
       });
 
       it("updates html document", function() {
+        tree.setViewRangeSize(30);
         tree.render(session.$entryPoint);
 
         tree.deleteNodes([node0]);
-        expect(findAllNodes(tree).length).toBe(26);
+        expect(tree.visibleNodesFlat.length).toBe(26);
         expect(node0.$node).toBeUndefined();
+        expect(tree.nodes.indexOf(node0)).toBe(-1);
         expect(node0.childNodes[0].$node).toBeUndefined();
         expect(node0.childNodes[1].$node).toBeUndefined();
         expect(node0.childNodes[2].$node).toBeUndefined();
@@ -497,6 +420,7 @@
 
       describe("deleting a collapsed root node", function() {
         it("updates model", function() {
+          tree.setNodeExpanded(node0, false);
           node0.expanded = false;
 
           tree.deleteNodes([node0]);
@@ -506,12 +430,14 @@
         });
 
         it("updates html document", function() {
-          node0.expanded = false;
+          tree.setViewRangeSize(30);
+          tree.setNodeExpanded(node0, false);
           tree.render(session.$entryPoint);
 
           tree.deleteNodes([node0]);
-          expect(findAllNodes(tree).length).toBe(26);
+          expect(helper.findAllNodes(tree).length).toBe(26);
           expect(node0.$node).toBeUndefined();
+          expect(tree.nodes.indexOf(node0)).toBe(-1);
           expect(node0.childNodes[0].$node).toBeUndefined();
           expect(node0.childNodes[1].$node).toBeUndefined();
           expect(node0.childNodes[2].$node).toBeUndefined();
@@ -530,7 +456,7 @@
         tree.render(session.$entryPoint);
 
         tree.deleteNodes([node0, node1, node2]);
-        expect(findAllNodes(tree).length).toBe(0);
+        expect(helper.findAllNodes(tree).length).toBe(0);
       });
     });
 
@@ -547,8 +473,8 @@
     var node1Child2;
 
     beforeEach(function() {
-      model = createModelFixture(3, 1, true);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 1, true);
+      tree = helper.createTree(model);
       node0 = model.nodes[0];
       node1 = model.nodes[1];
       node2 = model.nodes[2];
@@ -569,10 +495,10 @@
     it("deletes all nodes from html document", function() {
       tree.render(session.$entryPoint);
 
-      expect(findAllNodes(tree).length).toBe(12);
+      expect(helper.findAllNodes(tree).length).toBe(12);
 
       tree.deleteAllChildNodes();
-      expect(findAllNodes(tree).length).toBe(0);
+      expect(helper.findAllNodes(tree).length).toBe(0);
     });
 
     it("deletes all nodes from model for a given parent", function() {
@@ -587,10 +513,10 @@
     it("deletes all nodes from html document for a given parent", function() {
       tree.render(session.$entryPoint);
 
-      expect(findAllNodes(tree).length).toBe(12);
+      expect(helper.findAllNodes(tree).length).toBe(12);
 
       tree.deleteAllChildNodes(node1);
-      expect(findAllNodes(tree).length).toBe(9);
+      expect(helper.findAllNodes(tree).length).toBe(9);
 
       //Check that children are removed, parent must still exist
       expect(node1.$node).toBeDefined();
@@ -604,8 +530,8 @@
   describe("node click", function() {
 
     it("calls tree._onNodeMouseDown", function() {
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       spyOn(tree, '_onNodeMouseDown');
       tree.render(session.$entryPoint);
 
@@ -616,8 +542,8 @@
     });
 
     it("sends selection and click events in one call in this order", function() {
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $node = tree.$container.find('.tree-node:first');
@@ -631,8 +557,8 @@
     });
 
     it("sends selection, check and click events if tree is checkable and checkbox has been clicked", function() {
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       tree.checkable = true;
       tree.render(session.$entryPoint);
 
@@ -648,8 +574,8 @@
     });
 
     it("updates model (selection)", function() {
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       expect(tree.selectedNodes.length).toBe(0);
@@ -662,8 +588,8 @@
     });
 
     it("does not send click if mouse down happens on another node than mouseup", function() {
-      var model = createModelFixture(2);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(2);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $node0 = tree.nodes[0].$node;
@@ -684,14 +610,19 @@
     });
 
     it("does not send click if mouse down does not happen on a node", function() {
-      var model = createModelFixture(1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1);
+      var tree = helper.createTree(model);
       var $div = session.$entryPoint.makeDiv().cssHeight(10).cssWidth(10);
       tree.render(session.$entryPoint);
 
       var $node0 = tree.nodes[0].$node;
       $node0.triggerMouseDown();
-      $(window).triggerMouseUp({position: {left: 0, top:0}});
+      $(window).triggerMouseUp({
+        position: {
+          left: 0,
+          top: 0
+        }
+      });
 
       sendQueuedAjaxCalls();
       expect(jasmine.Ajax.requests.count()).toBe(1);
@@ -707,7 +638,12 @@
       jasmine.Ajax.uninstall();
       jasmine.Ajax.install();
 
-      $(window).triggerMouseDown({position: {left: 0, top:0}});
+      $(window).triggerMouseDown({
+        position: {
+          left: 0,
+          top: 0
+        }
+      });
       $node0.triggerMouseUp();
 
       sendQueuedAjaxCalls();
@@ -718,8 +654,8 @@
   describe("check nodes", function() {
 
     it("checks a subnode -> mark upper nodes ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
       tree.checkable = true;
 
@@ -744,8 +680,8 @@
     });
 
     it("checks a node -> mark upper nodes -> uncheck node and test if node keeps marked because children are checked", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
       tree.checkable = true;
       var node, nodeToCheck;
@@ -783,8 +719,8 @@
     });
 
     it("checks a subnode and its sibling->mark upper nodes -> uncheck one of the siblings", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
       tree.checkable = true;
       var nodeOne, nodeTwo;
@@ -827,8 +763,8 @@
     });
 
     it("try to check a disabled node ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
       tree.checkable = true;
       var node = tree.nodes[0];
@@ -842,8 +778,8 @@
     });
 
     it("try to check a node in disabled tree ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.enabled = false;
       tree.render(session.$entryPoint);
 
@@ -857,8 +793,8 @@
     });
 
     it("try to check two nodes in singlecheck tree ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.multiCheck = false;
       tree.checkable = true;
       tree.render(session.$entryPoint);
@@ -881,8 +817,8 @@
     });
 
     it("check a parent in autoCheckChildren tree ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.multiCheck = true;
       tree.checkable = true;
       tree.autoCheckChildren = true;
@@ -903,8 +839,8 @@
     });
 
     it("check a parent in autoCheckChildren = false tree ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.multiCheck = true;
       tree.checkable = true;
       tree.autoCheckChildren = false;
@@ -925,8 +861,8 @@
     });
 
     it("try to check nodes in uncheckable tree ", function() {
-      var model = createModelFixture(4, 4);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(4, 4);
+      var tree = helper.createTree(model);
       tree.multiCheck = false;
       tree.checkable = false;
       tree.render(session.$entryPoint);
@@ -961,8 +897,8 @@
     });
 
     it("expands/collapses the node", function() {
-      var model = createModelFixture(1, 1, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1, 1, false);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $node = tree.$container.find('.tree-node:first');
@@ -976,8 +912,8 @@
     });
 
     it("sends clicked, selection, action and expansion events", function() {
-      var model = createModelFixture(1, 1, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1, 1, false);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $node = tree.$container.find('.tree-node:first');
@@ -1002,8 +938,8 @@
     });
 
     it("does the same as control single click (does NOT expand and immediately collapse again)", function() {
-      var model = createModelFixture(1, 1, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1, 1, false);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $nodeControl = tree.$container.find('.tree-node-control:first');
@@ -1021,8 +957,8 @@
     });
 
     it("sends clicked, selection, action and expansion events", function() {
-      var model = createModelFixture(1, 1, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1, 1, false);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var $node = tree.$container.find('.tree-node:first');
@@ -1039,8 +975,8 @@
 
     it("collapses all nodes and updates model", function() {
       var i;
-      var model = createModelFixture(3, 2, true);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 2, true);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var allNodes = [];
@@ -1067,11 +1003,11 @@
   describe("deselectAll", function() {
 
     it("clears the selection", function() {
-      var model = createModelFixture(1, 1);
+      var model = helper.createModelFixture(1, 1);
       var node0 = model.nodes[0];
       model.selectedNodes = [node0.id];
 
-      var tree = createTree(model);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
       expect(tree.$selectedNodes().length).toBe(1);
 
@@ -1088,8 +1024,8 @@
   describe("selectNodes", function() {
 
     it("selects a node", function() {
-      var model = createModelFixture(3, 3, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
       var node0 = model.nodes[0];
 
       tree.render(session.$entryPoint);
@@ -1107,8 +1043,8 @@
     });
 
     it("expands the parents if a hidden node should be selected whose parents are collapsed (revealing the selection)", function() {
-      var model = createModelFixture(3, 3, false);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 3, false);
+      var tree = helper.createTree(model);
       var node0 = tree.nodes[0];
       var child0 = node0.childNodes[0];
       var grandchild0 = child0.childNodes[0];
@@ -1140,11 +1076,11 @@
     });
 
     it("also expands the node if bread crumb mode is enabled", function() {
-      var model = createModelFixture(1, 1);
+      var model = helper.createModelFixture(1, 1);
       var node0 = model.nodes[0];
 
-      var tree = createTree(model);
-      tree.breadcrumbEnabled = true;
+      var tree = helper.createTree(model);
+      tree.displayStyle = scout.Tree.DisplayStyle.BREADCRUMB;
       tree.render(session.$entryPoint);
 
       tree.selectNodes(node0);
@@ -1154,8 +1090,8 @@
     });
 
     it("sets css class ancestor-of-selected on every ancestor of the selected element", function() {
-      var model = createModelFixture(3, 3);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 3);
+      var tree = helper.createTree(model);
       var nodes = tree.nodes;
       var node1 = nodes[1];
       var child1 = node1.childNodes[1];
@@ -1167,15 +1103,18 @@
       expect($parents.length).toBe(0);
 
       tree.selectNodes(node1);
+      jasmine.clock().tick(1);
       $parents = tree.$data.find('.tree-node.ancestor-of-selected');
       expect($parents.length).toBe(0);
 
       tree.selectNodes(child1);
+      jasmine.clock().tick(1);
       $parents = tree.$data.find('.tree-node.ancestor-of-selected');
       expect($parents.length).toBe(1);
       expect($parents.eq(0)[0]).toBe(nodes[1].$node[0]);
 
       tree.selectNodes(grandchild1);
+      jasmine.clock().tick(1);
       $parents = tree.$data.find('.tree-node.ancestor-of-selected');
       expect($parents.length).toBe(2);
       expect($parents.eq(0)[0]).toBe(nodes[1].$node[0]);
@@ -1187,12 +1126,11 @@
     });
 
     it("sets css class child-of-selected on direct children of the selected element", function() {
-      var model = createModelFixture(3, 3, true);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 1, true);
+      var tree = helper.createTree(model);
       var nodes = tree.nodes;
       var node1 = nodes[1];
       var child1 = node1.childNodes[1];
-      var grandchild1 = child1.childNodes[1];
 
       tree.render(session.$entryPoint);
 
@@ -1222,8 +1160,8 @@
   describe("expandNode", function() {
 
     it("sets css class child-of-selected on direct children if the expanded node is selected", function() {
-      var model = createModelFixture(3, 3);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(3, 3);
+      var tree = helper.createTree(model);
       var nodes = tree.nodes;
       var node1 = nodes[1];
 
@@ -1250,11 +1188,11 @@
   describe("collapseNode", function() {
 
     it("prevents collapsing in bread crumb mode if node is selected", function() {
-      var model = createModelFixture(1, 1);
+      var model = helper.createModelFixture(1, 1);
       var node0 = model.nodes[0];
 
-      var tree = createTree(model);
-      tree.breadcrumbEnabled = true;
+      var tree = helper.createTree(model);
+      tree.displayStyle = scout.Tree.DisplayStyle.BREADCRUMB;
       tree.render(session.$entryPoint);
 
       tree.selectNodes(node0);
@@ -1273,8 +1211,8 @@
     var model, tree, node1, child1, grandchild1, nodes;
 
     beforeEach(function() {
-      model = createModelFixture(3, 3);
-      tree = createTree(model);
+      model = helper.createModelFixture(3, 3);
+      tree = helper.createTree(model);
       nodes = tree.nodes;
       node1 = nodes[1];
       child1 = node1.childNodes[1];
@@ -1288,22 +1226,26 @@
       };
 
       tree.selectNodes([]);
+      tree._renderViewport();
       var $groupNodes = tree.$data.find('.tree-node.group');
       expect($groupNodes.length).toBe(0);
 
       tree.selectNodes(node1);
+      tree._renderViewport();
       $groupNodes = tree.$data.find('.tree-node.group');
       expect($groupNodes.length).toBe(1);
       expect($groupNodes.eq(0)[0]).toBe(node1.$node[0]);
 
       node1.nodeType = 'groupingParent';
       tree.selectNodes(child1);
+      tree._renderViewport();
       $groupNodes = tree.$data.find('.tree-node.group');
       expect($groupNodes.length).toBe(1);
       expect($groupNodes.eq(0)[0]).toBe(child1.$node[0]);
 
       node1.nodeType = 'groupingParent';
       tree.selectNodes(grandchild1);
+      tree._renderViewport();
       $groupNodes = tree.$data.find('.tree-node.group');
       expect($groupNodes.length).toBe(4);
       expect($groupNodes.eq(0)[0]).toBe(child1.$node[0]);
@@ -1316,8 +1258,8 @@
   describe("tree filter", function() {
 
     it("filters nodes when filter() is called", function() {
-      var model = createModelFixture(1, 1, true);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(1, 1, true);
+      var tree = helper.createTree(model);
       tree.render(session.$entryPoint);
 
       var filter = {
@@ -1336,29 +1278,26 @@
       expect(tree.nodes[0].childNodes[0].filterAccepted).toBe(true);
     });
 
-    it("filters nodes when tree gets rendered", function() {
-      var model = createModelFixture(1, 1, true);
-      var tree = createTree(model);
+    it("filters nodes when filter is added and removed", function() {
+      var model = helper.createModelFixture(1, 1, true);
+      var tree = helper.createTree(model);
       var filter = {
         accept: function(node) {
           return node === tree.nodes[0];
         }
       };
       tree.addFilter(filter);
-      tree.render(session.$entryPoint);
-
       expect(tree.nodes[0].filterAccepted).toBe(true);
       expect(tree.nodes[0].childNodes[0].filterAccepted).toBe(false);
 
       tree.removeFilter(filter);
-      tree.filter();
       expect(tree.nodes[0].filterAccepted).toBe(true);
       expect(tree.nodes[0].childNodes[0].filterAccepted).toBe(true);
     });
 
     it("makes sure only filtered nodes are displayed when node gets expanded", function() {
-      var model = createModelFixture(2, 1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(2, 1);
+      var tree = helper.createTree(model);
       var filter = {
         accept: function(node) {
           return node === tree.nodes[0] || node === tree.nodes[0].childNodes[0];
@@ -1367,21 +1306,21 @@
       tree.addFilter(filter);
       tree.render(session.$entryPoint);
 
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[0].$node).toBeFalsy();
-      expect(tree.nodes[0].childNodes[1].$node).toBeFalsy();
+      expect(tree.nodes[0].rendered).toBe(true);
+      expect(tree.nodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[0].rendered).toBeFalsy();
+      expect(tree.nodes[0].childNodes[1].rendered).toBeFalsy();
 
       tree.expandNode(tree.nodes[0]);
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[0].childNodes[1].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].rendered).toBe(true);
+      expect(tree.nodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[0].rendered).toBe(true);
+      expect(tree.nodes[0].childNodes[1].rendered).toBe(false);
     });
 
     it("applies filter if a node gets changed", function() {
-      var model = createModelFixture(2, 1);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(2, 1);
+      var tree = helper.createTree(model);
       var filter = {
         accept: function(node) {
           return node.text === 'node 0';
@@ -1390,10 +1329,10 @@
       tree.addFilter(filter);
       tree.render(session.$entryPoint);
 
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].attached).toBe(true);
+      expect(tree.nodes[1].attached).toBe(false);
 
-      var event = createNodeChangedEvent(model, tree.nodes[0].id);
+      var event = helper.createNodeChangedEvent(model, tree.nodes[0].id);
       event.text = 'new Text';
       var message = {
         events: [event]
@@ -1402,13 +1341,13 @@
 
       expect(tree.nodes[0].text).toBe(event.text);
       // text has changed -> filter condition returns false -> must not be visible anymore
-      expect(tree.nodes[0].$node.isVisible()).toBe(false);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].attached).toBe(false);
+      expect(tree.nodes[1].attached).toBe(false);
     });
 
     it("applies filter if a node gets inserted", function() {
-      var model = createModelFixture(2, 1, true);
-      var tree = createTree(model);
+      var model = helper.createModelFixture(2, 1, true);
+      var tree = helper.createTree(model);
       var filter = {
         accept: function(node) {
           return node.text === 'node 0';
@@ -1418,31 +1357,31 @@
       tree.render(session.$entryPoint);
 
       expect(tree.nodes[0].childNodes.length).toBe(2);
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].rendered).toBe(true);
+      expect(tree.nodes[1].rendered).toBe(false);
 
-      var newNode = createModelNode('', 'newNode0Child1');
+      var newNode = helper.createModelNode('', 'newNode0Child1');
       tree.insertNodes([newNode], tree.nodes[0], 2);
 
       expect(tree.nodes[0].childNodes.length).toBe(3);
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[0].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[2].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].rendered).toBe(true);
+      expect(tree.nodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[0].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[2].rendered).toBe(false);
       expect(tree.nodes[0].childNodes[2].filterAccepted).toBe(false);
 
-      newNode = createModelNode('', 'node 0', 3);
+      newNode = helper.createModelNode('', 'node 0', 3);
       tree.insertNodes([newNode], tree.nodes[0]);
 
       expect(tree.nodes[0].childNodes.length).toBe(4);
-      expect(tree.nodes[0].$node.isVisible()).toBe(true);
-      expect(tree.nodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[0].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[1].$node.isVisible()).toBe(false);
-      expect(tree.nodes[0].childNodes[2].$node.isVisible()).toBe(false);
+      expect(tree.nodes[0].rendered).toBe(true);
+      expect(tree.nodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[0].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[1].rendered).toBe(false);
+      expect(tree.nodes[0].childNodes[2].rendered).toBe(false);
       expect(tree.nodes[0].childNodes[2].filterAccepted).toBe(false);
-      expect(tree.nodes[0].childNodes[3].$node.isVisible()).toBe(true);
+      expect(tree.nodes[0].childNodes[3].rendered).toBe(true);
       expect(tree.nodes[0].childNodes[3].filterAccepted).toBe(true);
     });
   });
@@ -1457,8 +1396,8 @@
       var node2;
 
       beforeEach(function() {
-        model = createModelFixture(3, 1, true);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 1, true);
+        tree = helper.createTree(model);
         node0 = model.nodes[0];
         node1 = model.nodes[1];
         node2 = model.nodes[2];
@@ -1467,8 +1406,8 @@
       it("calls insertNodes", function() {
         spyOn(tree, 'insertNodes');
 
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 3);
-        var event = createNodesInsertedEvent(model, [newNode0Child3], node0.id);
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        var event = helper.createNodesInsertedEvent(model, [newNode0Child3], node0.id);
         tree.onModelAction(event);
         expect(tree.insertNodes).toHaveBeenCalledWith([newNode0Child3], tree.nodes[0]);
       });
@@ -1484,8 +1423,8 @@
 
       beforeEach(function() {
         // A large tree is used to properly test recursion
-        model = createModelFixture(3, 2, true);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 2, true);
+        tree = helper.createTree(model);
         node0 = tree.nodes[0];
         node1 = tree.nodes[1];
         node2 = tree.nodes[2];
@@ -1495,8 +1434,8 @@
         spyOn(tree, 'deleteNodes');
 
         var node2Child0 = node2.childNodes[0];
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3', 3);
-        var event = createNodesDeletedEvent(model, [node2Child0.id], node2.id);
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        var event = helper.createNodesDeletedEvent(model, [node2Child0.id], node2.id);
         tree.onModelAction(event);
         expect(tree.deleteNodes).toHaveBeenCalledWith([node2Child0], node2);
       });
@@ -1514,8 +1453,8 @@
       var node1Child2;
 
       beforeEach(function() {
-        model = createModelFixture(3, 1, true);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 1, true);
+        tree = helper.createTree(model);
         node0 = model.nodes[0];
         node1 = model.nodes[1];
         node2 = model.nodes[2];
@@ -1527,7 +1466,7 @@
       it("calls deleteAllChildNodes", function() {
         spyOn(tree, 'deleteAllChildNodes');
 
-        var event = createAllChildNodesDeletedEvent(model);
+        var event = helper.createAllChildNodesDeletedEvent(model);
         tree.onModelAction(event);
         expect(tree.deleteAllChildNodes).toHaveBeenCalled();
       });
@@ -1542,8 +1481,8 @@
       var grandchild0;
 
       beforeEach(function() {
-        model = createModelFixture(3, 3, false);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 3, false);
+        tree = helper.createTree(model);
         node0 = model.nodes[0];
         child0 = node0.childNodes[0];
         grandchild0 = child0.childNodes[0];
@@ -1552,7 +1491,7 @@
       it("calls selectNodes", function() {
         spyOn(tree, 'selectNodes');
 
-        var event = createNodesSelectedEvent(model, [node0.id]);
+        var event = helper.createNodesSelectedEvent(model, [node0.id]);
         tree.onModelAction(event);
         expect(tree.selectNodes).toHaveBeenCalledWith([node0], false);
       });
@@ -1561,7 +1500,7 @@
         tree.render(session.$entryPoint);
 
         var message = {
-          events: [createNodesSelectedEvent(model, [node0.id])]
+          events: [helper.createNodesSelectedEvent(model, [node0.id])]
         };
         session._processSuccessResponse(message);
 
@@ -1574,8 +1513,8 @@
       var model, tree, nodes, node0, node1, child0, child1_1;
 
       beforeEach(function() {
-        model = createModelFixture(3, 3, false);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 3, false);
+        tree = helper.createTree(model);
         nodes = tree.nodes;
         node0 = nodes[0];
         node1 = nodes[1];
@@ -1584,7 +1523,7 @@
       });
 
       it("updates the text of the model node", function() {
-        var event = createNodeChangedEvent(model, node0.id);
+        var event = helper.createNodeChangedEvent(model, node0.id);
         event.text = 'new Text';
         var message = {
           events: [event]
@@ -1597,7 +1536,7 @@
       it("updates the text of the html node", function() {
         tree.render(session.$entryPoint);
 
-        var event = createNodeChangedEvent(model, node0.id);
+        var event = helper.createNodeChangedEvent(model, node0.id);
         event.text = 'new Text';
         var message = {
           events: [event]
@@ -1616,7 +1555,7 @@
         tree.selectedNodes = [node0];
         tree.render(session.$entryPoint);
 
-        var event = createNodeChangedEvent(model, node0.id);
+        var event = helper.createNodeChangedEvent(model, node0.id);
         event.cssClass = 'new-css-class';
         var message = {
           events: [event]
@@ -1634,7 +1573,7 @@
         expect($node0).toHaveClass('selected');
 
         // Check if removal works (event does not contain cssClass again)
-        event = createNodeChangedEvent(model, node0.id);
+        event = helper.createNodeChangedEvent(model, node0.id);
         message = {
           events: [event]
         };
@@ -1661,7 +1600,7 @@
         expect($children.eq(1)[0]).toBe(nodes[1].$node[0]);
         expect($children.eq(2)[0]).toBe(nodes[2].$node[0]);
 
-        var event = createNodeChangedEvent(model, node1.id);
+        var event = helper.createNodeChangedEvent(model, node1.id);
         event.text = 'new text';
         var message = {
           events: [event]
@@ -1679,7 +1618,7 @@
 
       it("preserves child-of-selected when child nodes get updated", function() {
         tree.selectedNodes = [node1];
-        node1.expanded = true;
+        tree.setNodeExpanded(node1, true);
         tree.render(session.$entryPoint);
 
         var $children = tree.$data.find('.tree-node.child-of-selected');
@@ -1688,7 +1627,7 @@
         expect($children.eq(1)[0]).toBe(node1.childNodes[1].$node[0]);
         expect($children.eq(2)[0]).toBe(node1.childNodes[2].$node[0]);
 
-        var event = createNodeChangedEvent(model, child1_1.id);
+        var event = helper.createNodeChangedEvent(model, child1_1.id);
         event.text = 'new text';
         var message = {
           events: [event]
@@ -1705,8 +1644,7 @@
       });
 
       it("preserves group css class when nodes get updated", function() {
-        tree.selectedNodes = [node1];
-        node1.expanded = false;
+        tree.selectNode(node1, false);
         tree.render(session.$entryPoint);
 
         tree._isGroupingEnd = function(node) {
@@ -1717,7 +1655,7 @@
         expect($groupNodes.length).toBe(1);
         expect($groupNodes.eq(0)[0]).toBe(node1.$node[0]);
 
-        var event = createNodeChangedEvent(model, node1.id);
+        var event = helper.createNodeChangedEvent(model, node1.id);
         event.text = 'new text';
         var message = {
           events: [event]
@@ -1740,8 +1678,8 @@
       var child0;
 
       beforeEach(function() {
-        model = createModelFixture(3, 3, false);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 3, false);
+        tree = helper.createTree(model);
         node0 = model.nodes[0];
         child0 = node0.childNodes[0];
       });
@@ -1753,7 +1691,7 @@
           id: child0.id,
           enabled: false
         };
-        var event = createNodesUpdatedEvent(model, [child0Update]);
+        var event = helper.createNodesUpdatedEvent(model, [child0Update]);
         tree.onModelAction(event);
         expect(tree.updateNodes).toHaveBeenCalledWith([child0Update]);
       });
@@ -1768,8 +1706,8 @@
       var node2;
 
       beforeEach(function() {
-        model = createModelFixture(3, 1, true);
-        tree = createTree(model);
+        model = helper.createModelFixture(3, 1, true);
+        tree = helper.createTree(model);
         node0 = model.nodes[0];
         node1 = model.nodes[1];
         node2 = model.nodes[2];
@@ -1780,25 +1718,25 @@
 
         //Delete child nodes from node0
         var message = {
-          events: [createAllChildNodesDeletedEvent(model, node0.id)]
+          events: [helper.createAllChildNodesDeletedEvent(model, node0.id)]
         };
         session._processSuccessResponse(message);
         expect(node0.childNodes.length).toBe(0);
-        expect(findAllNodes(tree).length).toBe(9);
+        expect(helper.findAllNodes(tree).length).toBe(9);
 
         //Collapse node0
         var $node0 = node0.$node;
         message = {
-          events: [createNodeExpandedEvent(model, node0.id, false)]
+          events: [helper.createNodeExpandedEvent(model, node0.id, false)]
         };
         session._processSuccessResponse(message);
         expect(node0.expanded).toBe(false);
         expect($node0).not.toHaveClass('expanded');
 
         //Insert new child node at node0
-        var newNode0Child3 = createModelNode('0_3', 'newNode0Child3');
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3');
         message = {
-          events: [createNodesInsertedEvent(model, [newNode0Child3], node0.id)]
+          events: [helper.createNodesInsertedEvent(model, [newNode0Child3], node0.id)]
         };
         session._processSuccessResponse(message);
 
@@ -1806,11 +1744,11 @@
         expect(node0.childNodes.length).toBe(1);
         expect(node0.childNodes[0].text).toBe(newNode0Child3.text);
         expect(Object.keys(tree.nodesMap).length).toBe(10);
-        expect(findAllNodes(tree).length).toBe(9); //Still 9 nodes
+        expect(helper.findAllNodes(tree).length).toBe(9); //Still 9 nodes
 
         //Expand again
         message = {
-          events: [createNodeExpandedEvent(model, node0.id, true)]
+          events: [helper.createNodeExpandedEvent(model, node0.id, true)]
         };
         session._processSuccessResponse(message);
 
@@ -1818,7 +1756,7 @@
         expect($node0).toHaveClass('expanded');
 
         //Html nodes should now be added
-        expect(findAllNodes(tree).length).toBe(10);
+        expect(helper.findAllNodes(tree).length).toBe(10);
         expect(node0.childNodes[0].$node).toBeDefined();
       });
     });
@@ -1833,11 +1771,11 @@
     var node2;
 
     beforeEach(function() {
-      model = createModelFixture(3, 1, true);
+      model = helper.createModelFixture(3, 1, true);
       model.checkable = true;
       model.nodes[2].enabled = false;
 
-      tree = createTree(model);
+      tree = helper.createTree(model);
       node0 = model.nodes[0];
       node1 = model.nodes[1];
       node2 = model.nodes[2];
@@ -1851,7 +1789,7 @@
 
       // Disable tree
       var message = {
-        events: [createTreeEnabledEvent(model, false)]
+        events: [helper.createTreeEnabledEvent(model, false)]
       };
       session._processSuccessResponse(message);
 
@@ -1860,7 +1798,7 @@
 
       // Re-enable tree
       message = {
-        events: [createTreeEnabledEvent(model, true)]
+        events: [helper.createTreeEnabledEvent(model, true)]
       };
       session._processSuccessResponse(message);
 
@@ -1869,4 +1807,314 @@
     });
   });
 
+  describe("test visible list and map", function() {
+
+    describe("with initial all expanded nodes", function() {
+      var model, tree;
+      beforeEach(function() {
+        model = helper.createModelFixture(3, 2, true);
+        tree = helper.createTree(model);
+      });
+
+      it("init with all expanded in correct order", function() {
+        var index = 0;
+        tree._visitNodes(tree.nodes, function(node) {
+          expect(tree.visibleNodesFlat.indexOf(node) === index).toBeTruthy();
+          expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          index++;
+        });
+      });
+
+      it("collapse a node -> all children have to be removed", function() {
+        var collapseNode = model.nodes[0];
+        tree.collapseNode(collapseNode);
+
+        tree.nodes.forEach(function(node) {
+          expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+          expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          if (node === collapseNode) {
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeFalsy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeFalsy();
+            });
+          } else {
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+            });
+          }
+        });
+      });
+
+      it("filter node -> filtered node and children has to be removed from visible", function() {
+        var filterNode = model.nodes[0];
+        var filter = {
+          accept: function(node) {
+            return node !== filterNode;
+          }
+        };
+        tree.addFilter(filter);
+
+        tree.nodes.forEach(function(node) {
+          if (node === filterNode) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeFalsy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeFalsy();
+            });
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+            });
+          }
+        });
+      });
+
+      it("update node -> node is filtered", function() {
+
+        var filter = {
+          accept: function(node) {
+            return node.enabled;
+          }
+        };
+        tree.addFilter(filter);
+
+        tree._visitNodes(tree.nodes, function(childNode) {
+          expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+          expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+        });
+        var nodeToChange = model.nodes[0];
+
+        var clone = {
+          checked: nodeToChange.checked,
+          childNodeIndex: nodeToChange.childNodeIndex,
+          childNodes: nodeToChange.childNodes,
+          enabled: false,
+          expanded: nodeToChange.expanded,
+          expandedLazy: nodeToChange.expandedLazy,
+          id: "0",
+          lazyExpandingEnabled: nodeToChange.lazyExpandingEnabled,
+          leaf: nodeToChange.leaf,
+          text: nodeToChange.text
+        };
+
+        tree.updateNodes([clone]);
+
+        tree.nodes.forEach(function(node) {
+          if (node === nodeToChange) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeFalsy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeFalsy();
+            });
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+            });
+          }
+        });
+      });
+
+      it("insert expanded node to expanded parent", function() {
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        newNode0Child3.expanded = true;
+        var event = helper.createNodesInsertedEvent(model, [newNode0Child3], model.nodes[0].id);
+        tree.onModelAction(event);
+        var newNode0Child3Child0 = helper.createModelNode('0_3_1', 'newNode0Child3Child0', 0);
+        event = helper.createNodesInsertedEvent(model, [newNode0Child3Child0], newNode0Child3.id);
+        tree.onModelAction(event);
+        expect(tree.visibleNodesFlat.indexOf(newNode0Child3) > -1).toBeTruthy();
+        expect(tree.visibleNodesMap[newNode0Child3.id]).toBeTruthy();
+        expect(tree.visibleNodesFlat.indexOf(newNode0Child3Child0) > -1).toBeTruthy();
+        expect(tree.visibleNodesMap[newNode0Child3Child0.id]).toBeTruthy();
+      });
+
+      it("insert child node in filtered parent", function() {
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        newNode0Child3.expanded = true;
+        var event = helper.createNodesInsertedEvent(model, [newNode0Child3], model.nodes[0].id);
+
+        var filter = {
+          accept: function(node) {
+            return model.nodes[0].id !== node.id;
+          }
+        };
+        tree.addFilter(filter);
+
+        tree.nodes.forEach(function(node) {
+          if (node === model.nodes[0]) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeFalsy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeFalsy();
+            });
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+            });
+          }
+        });
+        tree.onModelAction(event);
+        tree.nodes.forEach(function(node) {
+          if (node === model.nodes[0]) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeFalsy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeFalsy();
+            });
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+            tree._visitNodes(node.childNodes, function(childNode) {
+              expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+              expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+            });
+          }
+        });
+
+      });
+
+      it("insert child node which should be filtered", function() {
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        newNode0Child3.expanded = true;
+        var event = helper.createNodesInsertedEvent(model, [newNode0Child3], model.nodes[0].id);
+
+        var filter = {
+          accept: function(node) {
+            return newNode0Child3.id !== node.id;
+          }
+        };
+        tree.addFilter(filter);
+
+        tree._visitNodes(tree.nodes, function(childNode) {
+          expect(tree.visibleNodesFlat.indexOf(childNode) > -1).toBeTruthy();
+          expect(tree.visibleNodesMap[childNode.id]).toBeTruthy();
+        });
+        tree.onModelAction(event);
+        tree._visitNodes(tree.nodes, function(node) {
+          if (node === newNode0Child3) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          }
+        });
+      });
+    });
+
+    describe("with initial all closed nodes", function() {
+      var model, tree;
+      beforeEach(function() {
+        model = helper.createModelFixture(3, 2, false);
+        tree = helper.createTree(model);
+      });
+
+      it("init with all collapsed", function() {
+        tree._visitNodes(tree.nodes, function(node) {
+          if (tree.nodes.indexOf(node) > -1) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+          }
+        });
+      });
+
+      it("insert child node collapsed parent", function() {
+        var newNode0Child3 = helper.createModelNode('0_3', 'newNode0Child3', 3);
+        newNode0Child3.expanded = true;
+        var event = helper.createNodesInsertedEvent(model, [newNode0Child3], model.nodes[0].id);
+        tree.onModelAction(event);
+        var newNode0Child3Child0 = helper.createModelNode('0_3_1', 'newNode0Child3Child0', 0);
+        event = helper.createNodesInsertedEvent(model, [newNode0Child3Child0], newNode0Child3.id);
+        tree.onModelAction(event);
+        expect(tree.visibleNodesFlat.indexOf(newNode0Child3) > -1).toBeFalsy();
+        expect(tree.visibleNodesMap[newNode0Child3.id]).toBeFalsy();
+        expect(tree.visibleNodesFlat.indexOf(newNode0Child3Child0) > -1).toBeFalsy();
+        expect(tree.visibleNodesMap[newNode0Child3Child0.id]).toBeFalsy();
+      });
+
+      it("expand node", function() {
+        var node0 = model.nodes[0];
+        tree.expandNode(node0);
+        tree._visitNodes(tree.nodes, function(node) {
+          if (node.parentNode === node0) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else if (tree.nodes.indexOf(node) > -1) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+          }
+        });
+        //check order
+        for (var i = 0; i < tree.visibleNodesFlat.length; i++) {
+          var nodeInList = tree.visibleNodesFlat[i];
+          if (i === 0) {
+            expect(nodeInList.id === '0').toBeTruthy();
+          } else if (i < 4) {
+            expect(nodeInList.id === '0_' + (i - 1)).toBeTruthy();
+          } else {
+            expect(nodeInList.id === String(i - 3)).toBeTruthy();
+          }
+        }
+
+      });
+
+      it("expand child node", function() {
+        var node0 = model.nodes[0],
+          node0_0 = node0.childNodes[0];
+        tree.expandNode(node0);
+        tree.expandNode(node0_0);
+        tree._visitNodes(tree.nodes, function(node) {
+          if (node.parentNode === node0) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else if (node.parentNode && node.parentNode === node0_0 && node.parentNode.parentNode === node0) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else if (tree.nodes.indexOf(node) > -1) {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeTruthy();
+            expect(tree.visibleNodesMap[node.id]).toBeTruthy();
+          } else {
+            expect(tree.visibleNodesFlat.indexOf(node) > -1).toBeFalsy();
+            expect(tree.visibleNodesMap[node.id]).toBeFalsy();
+          }
+        });
+        for (var i = 0; i < tree.visibleNodesFlat.length; i++) {
+          var nodeInList = tree.visibleNodesFlat[i];
+          if (i === 0) {
+            expect(nodeInList.id === '0').toBeTruthy();
+          } else if (i < 7) {
+            if (i === 1) {
+              expect(nodeInList.id === '0_0').toBeTruthy();
+            } else if (i < 5) {
+              expect(nodeInList.id === '0_0_' + (i - 2)).toBeTruthy();
+            } else {
+              expect(nodeInList.id === '0_' + (i - 4)).toBeTruthy();
+            }
+          } else {
+            expect(nodeInList.id === String(i - 6)).toBeTruthy();
+          }
+        }
+      });
+    });
+  });
 });
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpecHelper.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpecHelper.js
new file mode 100644
index 0000000..b59c436
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/tree/TreeSpecHelper.js
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+var TreeSpecHelper = function(session) {
+  this.session = session;
+};
+
+TreeSpecHelper.prototype.createModel = function(nodes) {
+  var model = createSimpleModel('Tree', this.session);
+
+  if (nodes) {
+    model.nodes = nodes;
+  }
+  model.enabled = true;
+  return model;
+};
+
+TreeSpecHelper.prototype.createModelFixture = function(nodeCount, depth, expanded) {
+  return this.createModel(this.createModelNodes(nodeCount, depth, expanded));
+};
+
+TreeSpecHelper.prototype.createModelNode = function(id, text, position) {
+  return {
+    id: id + '' || scout.objectFactory.createUniqueId(),
+    text: text,
+    childNodeIndex: position ? position : 0,
+    enabled: true,
+    checked: false
+  };
+};
+
+TreeSpecHelper.prototype.createModelNodes = function(nodeCount, depth, expanded) {
+  return this.createModelNodesInternal(nodeCount, depth, expanded);
+};
+
+TreeSpecHelper.prototype.createModelNodesInternal = function(nodeCount, depth, expanded, parentNode) {
+  if (!nodeCount) {
+    return;
+  }
+
+  var nodes = [],
+    nodeId;
+  if (!depth) {
+    depth = 0;
+  }
+  for (var i = 0; i < nodeCount; i++) {
+    nodeId = i;
+    if (parentNode) {
+      nodeId = parentNode.id + '_' + nodeId;
+    }
+    nodes[i] = this.createModelNode(nodeId, 'node ' + nodeId);
+    nodes[i].expanded = expanded;
+    if (depth > 0) {
+      nodes[i].childNodes = this.createModelNodesInternal(nodeCount, depth - 1, expanded, nodes[i]);
+    }
+  }
+  return nodes;
+};
+
+TreeSpecHelper.prototype.createTree = function(model) {
+  var tree = new scout.Tree();
+  tree.init(model);
+  return tree;
+};
+
+TreeSpecHelper.prototype.createCompactTree = function(model) {
+  var tree = new scout.CompactTree();
+  tree.init(model);
+  return tree;
+};
+
+TreeSpecHelper.prototype.findAllNodes = function(tree) {
+  return tree.$container.find('.tree-node');
+};
+
+TreeSpecHelper.prototype.createNodeExpandedEvent = function(model, nodeId, expanded) {
+  return {
+    target: model.id,
+    nodeId: nodeId,
+    expanded: expanded,
+    type: 'nodeExpanded'
+  };
+};
+
+TreeSpecHelper.prototype.selectNodesAndAssert = function(tree, nodes) {
+  tree.selectNodes(nodes);
+  this.assertSelection(tree, nodes);
+};
+
+TreeSpecHelper.prototype.assertSelection = function(tree, nodes) {
+  var $selectedNodes = tree.$selectedNodes();
+  expect($selectedNodes.length).toBe(nodes.length);
+
+  var selectedNodes = [];
+  $selectedNodes.each(function() {
+    selectedNodes.push($(this).data('node'));
+  });
+
+  expect(scout.arrays.equalsIgnoreOrder(nodes, selectedNodes)).toBeTruthy();
+  expect(scout.arrays.equalsIgnoreOrder(nodes, tree.selectedNodes)).toBeTruthy();
+};
+
+TreeSpecHelper.prototype.createNodesSelectedEvent = function(model, nodeIds) {
+  return {
+    target: model.id,
+    nodeIds: nodeIds,
+    type: 'nodesSelected'
+  };
+};
+
+TreeSpecHelper.prototype.createNodesInsertedEvent = function(model, nodes, commonParentNodeId) {
+  return {
+    target: model.id,
+    commonParentNodeId: commonParentNodeId,
+    nodes: nodes,
+    type: 'nodesInserted'
+  };
+};
+
+TreeSpecHelper.prototype.createNodesInsertedEventTopNode = function(model, nodes) {
+  return {
+    target: model.id,
+    nodes: nodes,
+    type: 'nodesInserted'
+  };
+};
+
+TreeSpecHelper.prototype.createNodesDeletedEvent = function(model, nodeIds, commonParentNodeId) {
+  return {
+    target: model.id,
+    commonParentNodeId: commonParentNodeId,
+    nodeIds: nodeIds,
+    type: 'nodesDeleted'
+  };
+};
+
+TreeSpecHelper.prototype.createAllChildNodesDeletedEvent = function(model, commonParentNodeId) {
+  return {
+    target: model.id,
+    commonParentNodeId: commonParentNodeId,
+    type: 'allChildNodesDeleted'
+  };
+};
+
+TreeSpecHelper.prototype.createNodeChangedEvent = function(model, nodeId) {
+  return {
+    target: model.id,
+    nodeId: nodeId,
+    type: 'nodeChanged'
+  };
+};
+
+TreeSpecHelper.prototype.createNodesUpdatedEvent = function(model, nodes) {
+  return {
+    target: model.id,
+    nodes: nodes,
+    type: 'nodesUpdated'
+  };
+};
+
+TreeSpecHelper.prototype.createTreeEnabledEvent = function(model, enabled) {
+  return {
+    target: model.id,
+    type: 'property',
+    properties: {
+      enabled: enabled
+    }
+  };
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/DetachHelperSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/DetachHelperSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/DetachHelperSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/DetachHelperSpec.js
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/DeviceSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/DeviceSpec.js
new file mode 100644
index 0000000..28b5bea
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/DeviceSpec.js
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+describe('Device', function() {
+
+  function test(userAgent, expectedDevice) {
+    return verify(bootstrapDevice(userAgent), expectedDevice);
+  }
+
+  function verify(actual, expected) {
+    if (expected.system) {
+      expect(actual.system).toBe(expected.system);
+    }
+    if (expected.systemVersion >= 0) {
+      expect(actual.systemVersion).toBe(expected.systemVersion);
+    }
+    if (expected.type) {
+      expect(actual.type).toBe(expected.type);
+    }
+    if (expected.browser) {
+      expect(actual.browser).toBe(expected.browser);
+    }
+    if (expected.browserVersion >= 0) {
+      expect(actual.browserVersion).toBe(expected.browserVersion);
+    }
+  }
+
+  function bootstrapDevice(userAgent) {
+    var device = new scout.Device(userAgent);
+    device.bootstrap();
+    return device;
+  }
+
+  describe('scout.device', function() {
+
+    it('is initialized automatically', function() {
+      expect(scout.device).toBeDefined();
+      expect(scout.device.browser).toBeDefined();
+      expect(scout.device.unselectableAttribute).toBeDefined();
+    });
+
+  });
+
+  describe('isWindowsTablet', function() {
+
+    it('returns true when browser is Edge and scrollbarWidth is 0', function() {
+      scout.device.scrollbarWidth = 0;
+      scout.device.browser = scout.Device.Browser.EDGE;
+      expect(scout.device.isWindowsTablet()).toBe(true);
+    });
+
+  });
+
+  describe('user agent parsing', function() {
+
+    it('recognizes iOS devices', function() {
+      // iPhone 4S
+      test('Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25', {
+        system: scout.Device.System.IOS,
+        systemVersion: 6,
+        type: scout.Device.Type.MOBILE,
+        browser: scout.Device.Browser.SAFARI,
+        browserVersion: 6
+      });
+
+      // iPad 3
+      test('Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3', {
+        system: scout.Device.System.IOS,
+        systemVersion: 5.1,
+        type: scout.Device.Type.TABLET,
+        browser: scout.Device.Browser.SAFARI,
+        browserVersion: 5.1
+      });
+
+      // iPad 3 (home screen icon mode)
+      test('Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176', {
+        system: scout.Device.System.IOS,
+        systemVersion: 5.1,
+        type: scout.Device.Type.TABLET,
+        browser: scout.Device.Browser.UNKNOWN
+      });
+
+    });
+
+    it('recognizes Android devices', function() {
+      // Samsung Galaxy S4
+      test('Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.170 Mobile Safari/537.36', {
+        system: scout.Device.System.ANDROID,
+        type: scout.Device.Type.MOBILE,
+        browser: scout.Device.Browser.CHROME,
+        browserVersion: 33
+      });
+
+      // Google Nexus 10 Tablet
+      test('Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JWR66Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Safari/537.36', {
+        system: scout.Device.System.ANDROID,
+        type: scout.Device.Type.TABLET,
+        browser: scout.Device.Browser.CHROME,
+        browserVersion: 30
+      });
+    });
+
+    it('recognizes normal Windows PCs', function() {
+      // Windows with Firefox browser
+      test('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36', {
+        system: scout.Device.System.UNKNOWN,
+        type: scout.Device.Type.DESKTOP
+      });
+    });
+
+    // Note: cannot detect Surface tablet reliable with Jasmine test, since scrollbar width
+    // measurement depends on the browser that runs the spec.
+
+    it('recognizes supported browsers', function() {
+      var userAgent, device;
+
+      // Microsoft Edge 12
+      _test('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240',
+        scout.Device.Browser.EDGE, 12.10240);
+
+      // Internet Explorer 11
+      _test('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko',
+        scout.Device.Browser.INTERNET_EXPLORER, 11.0);
+      // Internet Explorer 11 - as used by Outlook - note the additional ; and text after the version-no (rv).
+      _test('Mozilla/5.0 (Windows NT 6.1; WOW65; Trident/7.0; rv:11.0; Microsoft Outlook 14.0.7155)',
+        scout.Device.Browser.INTERNET_EXPLORER, 11.0);
+
+      // Internet Explorer 8
+      _test('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.30729; .NET CLR 3.0.30729)',
+        scout.Device.Browser.INTERNET_EXPLORER, 8.0);
+
+      // Safari (6)
+      _test('Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25',
+        scout.Device.Browser.SAFARI, 6.0);
+
+      // Firefox (21) from v21 Firefox supports ECMA 5
+      _test('Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1',
+        scout.Device.Browser.FIREFOX, 21.0);
+
+      // Chrome (23) from v23 Chrome supports ECMA 5
+      _test('Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.6 Safari/537.11',
+        scout.Device.Browser.CHROME, 23.0);
+
+      function _test(userAgent, expectedBrowser, expectedVersion) {
+        var device = new scout.Device(userAgent);
+        expect(device.browser).toBe(expectedBrowser);
+        expect(device.browserVersion).toEqual(expectedVersion);
+      }
+    });
+
+  });
+
+});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/EventSupportSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/EventSupportSpec.js
similarity index 62%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/EventSupportSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/EventSupportSpec.js
index dc7fa7f..ee9b7e5 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/EventSupportSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/EventSupportSpec.js
@@ -62,7 +62,9 @@
       events.one('foo', function(event) {
         receivedEvent = event;
       });
-      events.trigger('foo', {theProp: 'bar'});
+      events.trigger('foo', {
+        theProp: 'bar'
+      });
       // expect the event has been passed to the registered func
       expect(receivedEvent.theProp).toBe('bar');
       // expect the type property is automatically set by EventSupport
@@ -78,4 +80,65 @@
 
   });
 
+  describe('off', function() {
+
+    function fooListener1() {
+      count++;
+    }
+
+    function fooListener2() {
+      count++;
+    }
+
+    function fooListener3() {
+      count++;
+    }
+
+    function fooListener4() {
+      count++;
+    }
+
+    function fooListener5() {
+      count++;
+    }
+
+    function fooListener6() {
+      count++;
+    }
+
+    function fooListener7() {
+      count++;
+    }
+
+    beforeEach(function() {
+      events = new scout.EventSupport();
+      count = 0;
+    });
+
+    it('remove all with same type', function() {
+      events.one('foo', fooListener);
+      events.one('foo', fooListener1);
+      events.one('asdf', fooListener2);
+      events.one('asdf', fooListener3);
+      events.one('asdf', fooListener4);
+      events.one('asdf', fooListener5);
+      events.one('asdf', fooListener6);
+      events.one('asdf', fooListener7);
+      events.off('foo');
+      expect(events._eventListeners.length).toBe(6);
+    });
+
+    it('remove specific listener', function() {
+      events.one('foo', fooListener);
+      events.one('foo', fooListener1);
+      events.one('asdf', fooListener2);
+      events.one('asdf', fooListener3);
+      events.one('asdf', fooListener4);
+      events.one('asdf', fooListener5);
+      events.one('asdf', fooListener6);
+      events.one('asdf', fooListener7);
+      events.off('foo', fooListener);
+      expect(events._eventListeners.length).toBe(7);
+    });
+  });
 });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/RangeSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/RangeSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/RangeSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/RangeSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/URLSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/URLSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/URLSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/URLSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/arraysSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/arraysSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/arraysSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/arraysSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/datesSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/datesSpec.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/datesSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/datesSpec.js
index bda7137..f97c726 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/datesSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/datesSpec.js
@@ -8,7 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-/* global LocaleSpecHelper */
 describe("scout.dates", function() {
 
   describe("shift", function() {
@@ -417,16 +416,16 @@
         scout.dates.format('gugus');
       }).toThrow();
 
-      var helper = new LocaleSpecHelper();
-      var locale = helper.createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+      var helper = new scout.LocaleSpecHelper();
+      var locale = helper.createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
 
       expect(scout.dates.format(null, locale)).toBe('');
       expect(scout.dates.format(scout.dates.create('2014-11-21'), locale)).toBe('21.11.2014');
     });
 
     it("can format valid dates", function() {
-      var helper = new LocaleSpecHelper();
-      var locale = helper.createLocale(LocaleSpecHelper.DEFAULT_LOCALE);
+      var helper = new scout.LocaleSpecHelper();
+      var locale = helper.createLocale(scout.LocaleSpecHelper.DEFAULT_LOCALE);
 
       expect(scout.dates.format(scout.dates.create('2014-11-21'), locale, 'yy')).toBe('14');
     });
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/defaultValuesSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/defaultValuesSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/defaultValuesSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/defaultValuesSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/iconsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/iconsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/iconsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/iconsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/numbersSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/numbersSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/numbersSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/numbersSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/objectsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/objectsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/objectsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/objectsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/stringsSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/stringsSpec.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/util/stringsSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/util/stringsSpec.js
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/widget/WidgetSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/widget/WidgetSpec.js
similarity index 68%
rename from org.eclipse.scout.rt.ui.html/src/test/js/scout/widget/WidgetSpec.js
rename to org.eclipse.scout.rt.ui.html.test/src/test/js/scout/widget/WidgetSpec.js
index 291e850..5598db5 100644
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/widget/WidgetSpec.js
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/widget/WidgetSpec.js
@@ -10,15 +10,38 @@
  ******************************************************************************/
 describe('Widget', function() {
 
-  var session,
-    widget = new scout.Widget(),
-    parent = new scout.Widget();
-
+  var session, widget, parent;
 
   beforeEach(function() {
     setFixtures(sandbox());
     session = sandboxSession();
     session.init();
+
+    widget = new scout.Widget(),
+    parent = new scout.Widget();
+  });
+
+  describe('rendering', function() {
+
+    it('should set rendering, rendered flags correctly', function() {
+      widget.init({session: session, parent: parent});
+      expect(widget.rendered).toBe(false);
+      expect(widget.rendering).toBe(false);
+      widget.render(session.$entryPoint);
+      expect(widget.rendered).toBe(true);
+      expect(widget.rendering).toBe(false);
+    });
+
+    it('should set rendering flag to true _while_ the component is rendering', function() {
+      var rendering;
+      widget._render = function($parent) {
+        rendering = this.rendering;
+      };
+      widget.init({session: session, parent: parent});
+      widget.render(session.$entryPoint);
+      expect(rendering).toBe(true);
+    });
+
   });
 
   describe('attach/detach', function() {
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_simple.json b/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_simple.json
index a6bf6bd..662164d 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_simple.json
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_simple.json
@@ -17,7 +17,6 @@
     },
     "Table": {
       "enabled": true,
-      "rowHeightHint": -1,
       "rows": []
     },
     "Cell": {
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_withComments.json b/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_withComments.json
index cccfeb3..6da9d14 100644
--- a/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_withComments.json
+++ b/org.eclipse.scout.rt.ui.html.test/src/test/resources/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterTest_defaults_withComments.json
@@ -15,7 +15,6 @@
     /* test
     "Table": {
       "enabled": true,
-      "rowHeightHint": -1,
       "rows": []
     },
     // nothing
diff --git a/org.eclipse.scout.rt.ui.html/.classpath b/org.eclipse.scout.rt.ui.html/.classpath
index 58e851c..0461494 100644
--- a/org.eclipse.scout.rt.ui.html/.classpath
+++ b/org.eclipse.scout.rt.ui.html/.classpath
@@ -22,11 +22,6 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry excluding="**" including="**/*.java" kind="src" output="target/test-classes" path="src/test/js">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
 		<attributes>
 			<attribute name="maven.pomderived" value="true"/>
diff --git a/org.eclipse.scout.rt.ui.html/.jshintrc b/org.eclipse.scout.rt.ui.html/.jshintrc
index 1016815..90c4d96 100644
--- a/org.eclipse.scout.rt.ui.html/.jshintrc
+++ b/org.eclipse.scout.rt.ui.html/.jshintrc
@@ -30,6 +30,7 @@
     "createPropertyChangeEvent": false,
     "createAdapterData": false,
     "createAdapter": false,
-    "createSimpleModel": false
+    "createSimpleModel": false,
+    "removePopups": false
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.core.resources.prefs b/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.core.resources.prefs
index 13d34f3..b1fe22a 100644
--- a/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.core.resources.prefs
+++ b/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.core.resources.prefs
@@ -10,7 +10,6 @@
 encoding//src/main/shared=UTF-8
 encoding//src/main/webapp=UTF-8
 encoding//src/test/java=UTF-8
-encoding//src/test/js=UTF-8
 encoding//src/test/resources=UTF-8
 encoding//target/generated-sources/annotations=UTF-8
 encoding//target/generated-sources/wsimport=UTF-8
diff --git a/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt.ui.html/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt.ui.html/pom.xml b/org.eclipse.scout.rt.ui.html/pom.xml
index 40b0f6e..7665d7b 100644
--- a/org.eclipse.scout.rt.ui.html/pom.xml
+++ b/org.eclipse.scout.rt.ui.html/pom.xml
@@ -17,7 +17,7 @@
   <parent>
     <groupId>org.eclipse.scout.rt</groupId>
     <artifactId>org.eclipse.scout.rt</artifactId>
-    <version>5.2.0-SNAPSHOT</version>
+    <version>6.0.0-SNAPSHOT</version>
     <relativePath>../org.eclipse.scout.rt/pom.xml</relativePath>
   </parent>
 
@@ -28,7 +28,6 @@
   <properties>
     <scout.script.version>5.0.0</scout.script.version>
     <sonar.sources>src/main,pom.xml</sonar.sources>
-    <sonar.tests>src/test</sonar.tests>
   </properties>
 
   <dependencies>
@@ -62,38 +61,6 @@
     </dependency>
   </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <!-- Loads phantomjs executable, necessary for jasmine plugin -->
-        <groupId>com.github.klieber</groupId>
-        <artifactId>phantomjs-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>install</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-
-      <!-- JS testing with Jasmine -->
-      <plugin>
-        <groupId>com.github.searls</groupId>
-        <artifactId>jasmine-maven-plugin</artifactId>
-        <configuration>
-          <jsSrcDir>${project.basedir}/../org.eclipse.scout.rt.ui.html/src/main/js</jsSrcDir>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>test</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 
   <!-- primarily for license header generation -->
   <inceptionYear>2014</inceptionYear>
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/JsonObjectFactory.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/JsonObjectFactory.java
index c9ba717..fdcbe45 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/JsonObjectFactory.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/JsonObjectFactory.java
@@ -31,6 +31,7 @@
 import org.eclipse.scout.rt.client.ui.basic.table.columns.INumberColumn;
 import org.eclipse.scout.rt.client.ui.basic.table.columns.IStringColumn;
 import org.eclipse.scout.rt.client.ui.basic.table.controls.IAggregateTableControl;
+import org.eclipse.scout.rt.client.ui.basic.table.controls.IFormTableControl;
 import org.eclipse.scout.rt.client.ui.basic.table.controls.ITableControl;
 import org.eclipse.scout.rt.client.ui.basic.table.userfilter.ColumnUserFilterState;
 import org.eclipse.scout.rt.client.ui.basic.table.userfilter.DateColumnUserFilterState;
@@ -39,13 +40,13 @@
 import org.eclipse.scout.rt.client.ui.basic.table.userfilter.TextColumnUserFilterState;
 import org.eclipse.scout.rt.client.ui.basic.tree.ITree;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutlineViewButton;
 import org.eclipse.scout.rt.client.ui.desktop.outline.ISearchOutline;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.IPage;
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.ISearchForm;
 import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 import org.eclipse.scout.rt.client.ui.form.fields.beanfield.IBeanField;
 import org.eclipse.scout.rt.client.ui.form.fields.booleanfield.IBooleanField;
 import org.eclipse.scout.rt.client.ui.form.fields.browserfield.IBrowserField;
@@ -93,13 +94,13 @@
 import org.eclipse.scout.rt.ui.html.json.calendar.JsonCalendar;
 import org.eclipse.scout.rt.ui.html.json.calendar.JsonCalendarComponent;
 import org.eclipse.scout.rt.ui.html.json.desktop.JsonDesktop;
-import org.eclipse.scout.rt.ui.html.json.desktop.JsonFormToolButton;
+import org.eclipse.scout.rt.ui.html.json.desktop.JsonFormMenu;
 import org.eclipse.scout.rt.ui.html.json.desktop.JsonOutline;
 import org.eclipse.scout.rt.ui.html.json.desktop.JsonOutlineViewButton;
+import org.eclipse.scout.rt.ui.html.json.desktop.JsonSearchForm;
 import org.eclipse.scout.rt.ui.html.json.desktop.JsonSearchOutline;
 import org.eclipse.scout.rt.ui.html.json.desktop.JsonViewButton;
 import org.eclipse.scout.rt.ui.html.json.form.JsonForm;
-import org.eclipse.scout.rt.ui.html.json.form.JsonSearchForm;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonDateField;
 import org.eclipse.scout.rt.ui.html.json.form.fields.beanfield.JsonBeanField;
 import org.eclipse.scout.rt.ui.html.json.form.fields.browserfield.JsonBrowserField;
@@ -145,6 +146,7 @@
 import org.eclipse.scout.rt.ui.html.json.table.JsonStringColumn;
 import org.eclipse.scout.rt.ui.html.json.table.JsonTable;
 import org.eclipse.scout.rt.ui.html.json.table.control.JsonAggregateTableControl;
+import org.eclipse.scout.rt.ui.html.json.table.control.JsonFormTableControl;
 import org.eclipse.scout.rt.ui.html.json.table.control.JsonTableControl;
 import org.eclipse.scout.rt.ui.html.json.table.userfilter.JsonColumnUserFilter;
 import org.eclipse.scout.rt.ui.html.json.table.userfilter.JsonDateColumnUserFilter;
@@ -270,8 +272,8 @@
     if (model instanceof IContextMenu) {
       return new JsonContextMenu<IContextMenu>((IContextMenu) model, session, id, parent);
     }
-    if (model instanceof IFormToolButton<?>) {
-      return new JsonFormToolButton((IFormToolButton<?>) model, session, id, parent);
+    if (model instanceof IFormMenu<?>) {
+      return new JsonFormMenu((IFormMenu<?>) model, session, id, parent);
     }
     if (model instanceof IMenu) {
       return new JsonMenu<IMenu>((IMenu) model, session, id, parent);
@@ -329,6 +331,9 @@
     if (model instanceof IAggregateTableControl) { // needs to be before ITableControl
       return new JsonAggregateTableControl<IAggregateTableControl>((IAggregateTableControl) model, session, id, parent);
     }
+    if (model instanceof IFormTableControl) { // needs to be before ITableControl
+      return new JsonFormTableControl<IFormTableControl>((IFormTableControl) model, session, id, parent);
+    }
     if (model instanceof ITableControl) {
       return new JsonTableControl<ITableControl>((ITableControl) model, session, id, parent);
     }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/SessionStore.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/SessionStore.java
index 181425f..71f6e00 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/SessionStore.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/SessionStore.java
@@ -379,8 +379,8 @@
   }
 
   /**
-   * Stops the given session if it is active. To stop it, {@link IDesktopUIFacade#fireDesktopClosingFromUI(boolean)} is
-   * called, which forces the desktop to close without opening any more forms (which could be the case when using
+   * Stops the given session if it is active. To stop it, {@link IDesktopUIFacade#closeFromUI(boolean)} is called, which
+   * forces the desktop to close without opening any more forms (which could be the case when using
    * {@link IClientSession#stop()}).
    * <p>
    * If the client session is still active after that, a warning is printed to the log.
@@ -396,7 +396,7 @@
     }
     else {
       LOG.debug("Forcing session with ID {} to shut down...", clientSession.getId());
-      desktop.getUIFacade().fireDesktopClosingFromUI(true); // true = force
+      desktop.getUIFacade().closeFromUI(true); // true = force
       if (clientSession.isActive()) {
         LOG.warn("Client session with ID {} is still {} after forcing it to shutdown!", clientSession.getId(), (clientSession.isStopping() ? "stopping" : "active"));
       }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/UiSession.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/UiSession.java
index 697824c..273ecd7 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/UiSession.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/UiSession.java
@@ -41,6 +41,7 @@
 import org.eclipse.scout.rt.client.job.ModelJobs;
 import org.eclipse.scout.rt.client.session.ClientSessionProvider;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
+import org.eclipse.scout.rt.client.ui.desktop.IDesktopUIFacade;
 import org.eclipse.scout.rt.platform.BEANS;
 import org.eclipse.scout.rt.platform.IPlatform;
 import org.eclipse.scout.rt.platform.Platform;
@@ -58,13 +59,13 @@
 import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
 import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedException;
 import org.eclipse.scout.rt.shared.TEXTS;
+import org.eclipse.scout.rt.shared.deeplink.DeepLinkUrlParameter;
 import org.eclipse.scout.rt.shared.job.filter.event.SessionJobEventFilter;
 import org.eclipse.scout.rt.shared.job.filter.future.SessionFutureFilter;
-import org.eclipse.scout.rt.shared.ui.IUiDeviceType;
-import org.eclipse.scout.rt.shared.ui.IUiLayer;
 import org.eclipse.scout.rt.shared.ui.UiDeviceType;
 import org.eclipse.scout.rt.shared.ui.UiLayer;
 import org.eclipse.scout.rt.shared.ui.UserAgent;
+import org.eclipse.scout.rt.shared.ui.UserAgents;
 import org.eclipse.scout.rt.ui.html.json.AbstractJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.JsonAdapterRegistry;
@@ -77,6 +78,7 @@
 import org.eclipse.scout.rt.ui.html.json.JsonResponse;
 import org.eclipse.scout.rt.ui.html.json.JsonStartupRequest;
 import org.eclipse.scout.rt.ui.html.json.MainJsonObjectFactory;
+import org.eclipse.scout.rt.ui.html.res.BrowserInfo;
 import org.eclipse.scout.rt.ui.html.res.IBinaryResourceConsumer;
 import org.json.JSONObject;
 import org.slf4j.Logger;
@@ -228,7 +230,7 @@
       JsonClientSession<?> jsonClientSessionAdapter = createClientSessionAdapter(m_clientSession);
 
       // Start desktop
-      startDesktop();
+      startDesktop(jsonStartupReq.getSessionStartupParams());
 
       // Fill startupData with everything that is needed to start the session on the UI
       putInitializationStartupData(jsonClientSessionAdapter.getId());
@@ -282,22 +284,32 @@
   }
 
   protected UserAgent createUserAgent(JsonStartupRequest jsonStartupReq) {
-    IUiLayer uiLayer = UiLayer.HTML;
-    IUiDeviceType uiDeviceType = UiDeviceType.DESKTOP;
     String browserId = currentHttpRequest().getHeader("User-Agent");
+    BrowserInfo browserInfo = BrowserInfo.createFrom(browserId);
+
+    UserAgents userAgentBuilder = UserAgents
+        .create()
+        .withUiLayer(UiLayer.HTML)
+        .withUiDeviceType(UiDeviceType.DESKTOP)
+        .withUiEngineType(browserInfo.getEngineType())
+        .withUiSystem(browserInfo.getSystem())
+        .withDeviceId(browserId);
+
     JSONObject userAgent = jsonStartupReq.getUserAgent();
     if (userAgent != null) {
-      // FIXME cgu: it would be great if UserAgent could be changed dynamically, to switch from mobile to tablet mode on the fly, should be done as event in JsonClientSession
+      // TODO [7.0] cgu: it would be great if UserAgent could be changed dynamically, to switch from mobile to tablet mode on the fly, should be done as event in JsonClientSession
       String uiDeviceTypeStr = userAgent.optString("deviceType", null);
       if (uiDeviceTypeStr != null) {
-        uiDeviceType = UiDeviceType.createByIdentifier(uiDeviceTypeStr);
+        userAgentBuilder.withUiDeviceType(UiDeviceType.createByIdentifier(uiDeviceTypeStr));
       }
       String uiLayerStr = userAgent.optString("uiLayer", null);
       if (uiLayerStr != null) {
-        uiLayer = UiLayer.createByIdentifier(uiLayerStr);
+        userAgentBuilder.withUiLayer(UiLayer.createByIdentifier(uiLayerStr));
       }
+      boolean touch = userAgent.optBoolean("touch", false);
+      userAgentBuilder.withTouch(touch);
     }
-    return UserAgent.create(uiLayer, uiDeviceType, browserId);
+    return userAgentBuilder.build();
   }
 
   protected IClientSession createAndStartClientSession(Locale locale, UserAgent userAgent, Map<String, String> sessionStartupParams) {
@@ -355,19 +367,18 @@
     return BEANS.get(UiJobs.class).awaitAndGet(future);
   }
 
-  protected void startDesktop() {
+  protected void startDesktop(Map<String, String> startupParams) {
+    final String deepLinkPath = startupParams.get(DeepLinkUrlParameter.DEEP_LINK);
     final IFuture<Void> future = ModelJobs.schedule(new IRunnable() {
 
       @Override
       public void run() throws Exception {
         IDesktop desktop = m_clientSession.getDesktop();
-
+        IDesktopUIFacade uiFacade = desktop.getUIFacade();
         if (!desktop.isOpened()) {
-          desktop.getUIFacade().fireDesktopOpenedFromUI();
+          uiFacade.openFromUI();
         }
-        if (!desktop.isGuiAvailable()) {
-          desktop.getUIFacade().fireGuiAttached();
-        }
+        uiFacade.fireGuiAttached(deepLinkPath);
       }
     }, ModelJobs.newInput(ClientRunContexts.copyCurrent()
         .withSession(m_clientSession, true))
@@ -450,6 +461,15 @@
 
   @Override
   public void dispose() {
+
+    // Inform the model the UI has been detached. There are different cases we handle here:
+    // 1. page reload (unload event) dispose method is called once
+    // 2. logout (Session.stop()) dispose methid is called _twice_, 1st call sets the disposing flag,
+    //    on the 2nd call, the desktop is already gone.
+    if (!m_disposing) {
+      getClientSession().getDesktop().getUIFacade().fireGuiDetached();
+    }
+
     if (isProcessingJsonRequest()) {
       // If there is a request in progress just mark the session as being disposed.
       // The actual disposing happens before returning to the client, see processJsonRequest().
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/csp/ContentSecurityPolicyReportHandler.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/csp/ContentSecurityPolicyReportHandler.java
index bb3dadf..1959549 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/csp/ContentSecurityPolicyReportHandler.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/csp/ContentSecurityPolicyReportHandler.java
@@ -11,6 +11,7 @@
 package org.eclipse.scout.rt.ui.html.csp;
 
 import java.io.IOException;
+import java.io.Reader;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -29,9 +30,13 @@
  * <p>
  * It is used to collect Content-Security-Policy violations.
  * <p>
+ * If you get a violation for content you need, make sure all your content is provided from the same origin. If this is
+ * not possible you can adjust the CSP rule to your own needs by replacing {@link HttpServletControl} and overriding
+ * {@link HttpServletControl#cspRule}.
+ * <p>
  * see {@link HttpServletControl}
  *
- * @since 5.s
+ * @since 5.2
  */
 public class ContentSecurityPolicyReportHandler extends AbstractUiServletRequestHandler {
   private static final Logger LOG = LoggerFactory.getLogger(ContentSecurityPolicyReportHandler.class);
@@ -44,7 +49,10 @@
     if (!CompareUtility.equals(HANDLER_PATH, req.getPathInfo())) {
       return false;
     }
-    final String jsonData = IOUtility.getContent(req.getReader());
+    final String jsonData;
+    try (Reader in = req.getReader()) {
+      jsonData = IOUtility.readString(in);
+    }
     LOG.warn("CSP-REPORT: {}", jsonData);
     return true;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/AbstractJsonPropertyObserver.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/AbstractJsonPropertyObserver.java
index 9c6df1d..3623e1b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/AbstractJsonPropertyObserver.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/AbstractJsonPropertyObserver.java
@@ -80,7 +80,11 @@
    * a property change event occurs with the same value, the event is not sent back to the client (=filtered).
    */
   protected void addPropertyEventFilterCondition(String propertyName, Object value) {
-    m_propertyEventFilter.addCondition(new PropertyChangeEventFilterCondition(propertyName, value));
+    addPropertyEventFilterCondition(new PropertyChangeEventFilterCondition(propertyName, value));
+  }
+
+  protected void addPropertyEventFilterCondition(IPropertyChangeEventFilterCondition condition) {
+    m_propertyEventFilter.addCondition(condition);
   }
 
   @Override
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterService.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterService.java
index af41993..77e4880 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterService.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/DefaultValuesFilterService.java
@@ -10,6 +10,7 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json;
 
+import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
@@ -123,7 +124,10 @@
         if (lastModified > newestModified) {
           newestModified = lastModified;
         }
-        String jsonData = IOUtility.getContentUtf8(conn.getInputStream());
+        String jsonData;
+        try (InputStream in = conn.getInputStream()) {
+          jsonData = IOUtility.readStringUTF8(in);
+        }
         jsonData = JsonUtility.stripCommentsFromJson(jsonData);
         JSONObject json = new JSONObject(jsonData);
         defaultValuesConfigurations.add(json);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/IPropertyChangeEventFilterCondition.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/IPropertyChangeEventFilterCondition.java
new file mode 100644
index 0000000..5575ff2
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/IPropertyChangeEventFilterCondition.java
@@ -0,0 +1,14 @@
+package org.eclipse.scout.rt.ui.html.json;
+
+import java.beans.PropertyChangeEvent;
+
+import org.eclipse.scout.rt.platform.filter.IFilter;
+
+/**
+ * Interface used to filter property change events.
+ */
+public interface IPropertyChangeEventFilterCondition extends IFilter<PropertyChangeEvent> {
+
+  String getPropertyName();
+
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonBean.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonBean.java
index fb85a61..afaf13c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonBean.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonBean.java
@@ -16,6 +16,7 @@
 import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.Map;
+import java.util.TreeMap;
 
 import org.eclipse.scout.rt.platform.annotations.IgnoreProperty;
 import org.eclipse.scout.rt.platform.annotations.IgnoreProperty.Context;
@@ -97,7 +98,7 @@
       throw new IllegalArgumentException("Cannot convert " + type + " to json object");
     }
     try {
-      JSONObject jbean = new JSONObject();
+      TreeMap<String, Object> properties = new TreeMap<>();
       for (Field f : type.getFields()) {
         if (Modifier.isStatic(f.getModifiers())) {
           continue;
@@ -105,7 +106,7 @@
         String key = f.getName();
         Object val = f.get(m_bean);
         IJsonObject jsonObject = m_objectFactory.createJsonObject(val);
-        jbean.put(key, jsonObject.toJson());
+        properties.put(key, jsonObject.toJson());
       }
       FastBeanInfo beanInfo = new FastBeanInfo(type, Object.class);
       for (FastPropertyDescriptor desc : beanInfo.getPropertyDescriptors()) {
@@ -121,7 +122,11 @@
         String key = desc.getName();
         Object val = m.invoke(m_bean);
         IJsonObject jsonObject = m_objectFactory.createJsonObject(val);
-        jbean.put(key, jsonObject.toJson());
+        properties.put(key, jsonObject.toJson());
+      }
+      JSONObject jbean = new JSONObject();
+      for (Map.Entry<String, Object> e : properties.entrySet()) {
+        jbean.put(e.getKey(), e.getValue());
       }
       return jbean;
     }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonEventProcessor.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonEventProcessor.java
index 09aeae9..093df70 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonEventProcessor.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonEventProcessor.java
@@ -41,7 +41,6 @@
   protected void processEvent(JsonEvent event, JsonResponse response) {
     final IJsonAdapter jsonAdapter = m_uiSession.getJsonAdapter(event.getTarget());
     if (jsonAdapter == null) {
-      // FIXME awe: (json-layer) schauen ob wir eine warning ans UI zurückgeben sollen
       LOG.warn("No adapter found for ID {}", event.getTarget());
       return;
     }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonProperty.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonProperty.java
index 5e95062..984c2d6 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonProperty.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonProperty.java
@@ -88,14 +88,6 @@
     return true;
   }
 
-  public boolean shouldAddEvent() {
-    return hasModelValue() && accept() && !isValueSent();
-  }
-
-  protected boolean hasModelValue() {
-    return modelValue() != null;
-  }
-
   /**
    * Returns the <i>raw</i> model value.
    * <p>
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonRequestHelper.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonRequestHelper.java
index ec255c9..d552549 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonRequestHelper.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/JsonRequestHelper.java
@@ -12,6 +12,7 @@
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.io.Reader;
 import java.nio.charset.StandardCharsets;
 
 import javax.servlet.ServletRequest;
@@ -146,8 +147,8 @@
    * Reads the content of {@link ServletRequest} into a {@link JSONObject}.
    */
   public JSONObject readJsonRequest(final ServletRequest servletRequest) {
-    try {
-      final String jsonData = IOUtility.getContent(servletRequest.getReader());
+    try (Reader in = servletRequest.getReader()) {
+      final String jsonData = IOUtility.readString(in);
       LOG.debug("Received: {}", jsonData);
       return (jsonData == null ? new JSONObject() : new JSONObject(jsonData));
     }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyChangeEventFilterCondition.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyChangeEventFilterCondition.java
index e2021ed..addfa79 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyChangeEventFilterCondition.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyChangeEventFilterCondition.java
@@ -10,7 +10,10 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json;
 
-public class PropertyChangeEventFilterCondition {
+import java.beans.PropertyChangeEvent;
+
+public class PropertyChangeEventFilterCondition implements IPropertyChangeEventFilterCondition {
+
   private String m_propertyName;
   private Object m_value;
 
@@ -19,18 +22,28 @@
     m_value = value;
   }
 
+  @Override
   public String getPropertyName() {
     return m_propertyName;
   }
 
-  public Object getValue() {
-    return m_value;
-  }
+  @Override
+  public boolean accept(PropertyChangeEvent event) {
+    Object newValue = event.getNewValue();
 
-  /**
-   * Used to update the filtered value of this condition.
-   */
-  public void updateValue(Object value) {
-    m_value = value;
+    // Ignore if null == null
+    if (m_value == null) {
+      if (newValue == null) {
+        return false;
+      }
+    }
+    // Ignore if value is the same
+    else if (m_value.equals(newValue)) {
+      return false;
+    }
+
+    // When value is not ignored, we update the value to filter
+    m_value = newValue;
+    return true;
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyEventFilter.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyEventFilter.java
index 7bc3627..c05ea7e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyEventFilter.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/PropertyEventFilter.java
@@ -12,30 +12,18 @@
 
 import java.beans.PropertyChangeEvent;
 
-public class PropertyEventFilter extends AbstractEventFilter<PropertyChangeEvent, PropertyChangeEventFilterCondition> {
-
-  public PropertyEventFilter() {
-  }
+public class PropertyEventFilter extends AbstractEventFilter<PropertyChangeEvent, IPropertyChangeEventFilterCondition> {
 
   /**
    * Ignores the event if new value is the same.
    */
   @Override
   public PropertyChangeEvent filter(PropertyChangeEvent event) {
-    for (PropertyChangeEventFilterCondition condition : getConditions()) {
+    for (IPropertyChangeEventFilterCondition condition : getConditions()) {
       if (condition.getPropertyName().equals(event.getPropertyName())) {
-        // Ignore if null == null
-        if (condition.getValue() == null) {
-          if (event.getNewValue() == null) {
-            return null;
-          }
-        }
-        // Ignore if value is the same
-        else if (condition.getValue().equals(event.getNewValue())) {
+        if (!condition.accept(event)) {
           return null;
         }
-        // When value is not ignored, we update the value to filter
-        condition.updateValue(event.getNewValue());
       }
     }
     return event;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/UploadRequestHandler.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/UploadRequestHandler.java
index 3cb8978..649e2d1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/UploadRequestHandler.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/UploadRequestHandler.java
@@ -178,8 +178,10 @@
         String[] parts = StringUtility.split(filename, "[/\\\\]");
         filename = parts[parts.length - 1];
       }
-      InputStream stream = item.openStream();
-      byte[] content = IOUtility.getContent(stream);
+      byte[] content;
+      try (InputStream in = item.openStream()) {
+        content = IOUtility.readBytes(in);
+      }
       String contentType = item.getContentType();
       BinaryResource res = BinaryResources.create()
           .withFilename(filename)
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/action/JsonAction.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/action/JsonAction.java
index f3e3bb0..612a112 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/action/JsonAction.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/action/JsonAction.java
@@ -136,6 +136,9 @@
     else if (IAction.PROP_SELECTED.equals(event.getType())) {
       handleUiSelected(event);
     }
+    else {
+      super.handleUiEvent(event);
+    }
   }
 
   protected void handleUiDoAction(JsonEvent event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/BooleanPropertyChangeFilter.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/BooleanPropertyChangeFilter.java
new file mode 100644
index 0000000..ed1fa52
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/BooleanPropertyChangeFilter.java
@@ -0,0 +1,31 @@
+package org.eclipse.scout.rt.ui.html.json.desktop;
+
+import java.beans.PropertyChangeEvent;
+
+import org.eclipse.scout.rt.ui.html.json.IPropertyChangeEventFilterCondition;
+
+/**
+ * This simple boolean filter is used to allow or suppress a property change event depending on an external condition.
+ */
+public class BooleanPropertyChangeFilter implements IPropertyChangeEventFilterCondition {
+
+  private final String m_propertyName;
+
+  private final boolean m_acceptEvent;
+
+  public BooleanPropertyChangeFilter(String propertyName, boolean acceptEvent) {
+    m_propertyName = propertyName;
+    m_acceptEvent = acceptEvent;
+  }
+
+  @Override
+  public boolean accept(PropertyChangeEvent event) {
+    return m_acceptEvent;
+  }
+
+  @Override
+  public String getPropertyName() {
+    return m_propertyName;
+  }
+
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonBrowserHistoryEntry.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonBrowserHistoryEntry.java
new file mode 100644
index 0000000..f98d837
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonBrowserHistoryEntry.java
@@ -0,0 +1,31 @@
+package org.eclipse.scout.rt.ui.html.json.desktop;
+
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
+import org.eclipse.scout.rt.ui.html.json.IJsonObject;
+import org.json.JSONObject;
+
+public class JsonBrowserHistoryEntry implements IJsonObject {
+
+  private BrowserHistoryEntry m_browserHistoryEntry;
+
+  public JsonBrowserHistoryEntry(BrowserHistoryEntry browserHistoryEntry) {
+    m_browserHistoryEntry = browserHistoryEntry;
+  }
+
+  @Override
+  public Object toJson() {
+    JSONObject json = new JSONObject();
+    json.put("path", m_browserHistoryEntry.getPath());
+    json.put("title", m_browserHistoryEntry.getTitle());
+    json.put("deepLinkPath", m_browserHistoryEntry.getDeepLinkPath());
+    return json;
+  }
+
+  public static Object toJson(BrowserHistoryEntry browserHistoryEntry) {
+    if (browserHistoryEntry == null) {
+      return null;
+    }
+    return new JsonBrowserHistoryEntry(browserHistoryEntry).toJson();
+  }
+
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktop.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktop.java
index 9a7bd27..adef0af 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktop.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonDesktop.java
@@ -10,27 +10,24 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json.desktop;
 
-import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.eclipse.scout.rt.client.ui.IDisplayParent;
-import org.eclipse.scout.rt.client.ui.action.IAction;
 import org.eclipse.scout.rt.client.ui.action.keystroke.IKeyStroke;
+import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.action.view.IViewButton;
 import org.eclipse.scout.rt.client.ui.basic.filechooser.IFileChooser;
+import org.eclipse.scout.rt.client.ui.desktop.BrowserHistoryEntry;
 import org.eclipse.scout.rt.client.ui.desktop.DesktopEvent;
 import org.eclipse.scout.rt.client.ui.desktop.DesktopListener;
 import org.eclipse.scout.rt.client.ui.desktop.IDesktop;
-import org.eclipse.scout.rt.client.ui.desktop.IDesktop.DesktopStyle;
 import org.eclipse.scout.rt.client.ui.desktop.IOpenUriAction;
 import org.eclipse.scout.rt.client.ui.desktop.notification.IDesktopNotification;
 import org.eclipse.scout.rt.client.ui.desktop.outline.IOutline;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 import org.eclipse.scout.rt.client.ui.messagebox.IMessageBox;
 import org.eclipse.scout.rt.platform.BEANS;
-import org.eclipse.scout.rt.platform.Order;
 import org.eclipse.scout.rt.platform.resource.BinaryResource;
-import org.eclipse.scout.rt.platform.util.collection.OrderedCollection;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.AbstractJsonPropertyObserver;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
@@ -51,6 +48,7 @@
   private static final String EVENT_OUTLINE_CHANGED = "outlineChanged";
   private static final String EVENT_OUTLINE_CONTENT_ACTIVATE = "outlineContentActivate";
   private static final String EVENT_FORM_ACTIVATED = "formActivated";
+  private static final String EVENT_HISTORY_ENTRY_ACTIVATED = "historyEntryActivated";
 
   public static final String PROP_OUTLINE = "outline";
   public static final String PROP_DISPLAY_PARENT = "displayParent";
@@ -65,6 +63,7 @@
   private final DownloadHandlerStorage m_downloads;
   private DesktopListener m_desktopListener;
   private DesktopEventFilter m_desktopEventFilter;
+  private BooleanPropertyChangeFilter m_browserHistoryFilter = new BooleanPropertyChangeFilter(IDesktop.PROP_BROWSER_HISTORY_ENTRY, false);
 
   public JsonDesktop(DESKTOP desktop, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
     super(desktop, uiSession, id, parent);
@@ -84,17 +83,11 @@
     attachGlobalAdapters(getModel().getDialogs(getModel(), false));
     attachGlobalAdapters(getModel().getMessageBoxes(getModel()));
     attachGlobalAdapters(getModel().getFileChoosers(getModel()));
-    attachAdapters(filterModelActions(), new DisplayableActionFilter<IAction>());
+    attachAdapters(getModel().getMenus(), new DisplayableActionFilter<IMenu>());
     attachAdapters(getModel().getAddOns());
     attachAdapters(getModel().getKeyStrokes(), new DisplayableActionFilter<IKeyStroke>());
-    if (hasDefaultStyle()) {
-      attachAdapters(getModel().getViewButtons(), new DisplayableActionFilter<IViewButton>());
-      attachGlobalAdapter(getModel().getOutline(), new DisplayableOutlineFilter<IOutline>());
-    }
-  }
-
-  protected boolean hasDefaultStyle() {
-    return DesktopStyle.DEFAULT == getModel().getDesktopStyle();
+    attachAdapters(getModel().getViewButtons(), new DisplayableActionFilter<IViewButton>());
+    attachGlobalAdapter(getModel().getOutline(), new DisplayableOutlineFilter<IOutline>());
   }
 
   @Override
@@ -102,11 +95,39 @@
     if (EVENT_FORM_ACTIVATED.equals(event.getType())) {
       handleUiFormActivated(event);
     }
+    else if (EVENT_HISTORY_ENTRY_ACTIVATED.equals(event.getType())) {
+      handleUiHistoryEntryActivated(event);
+    }
     else {
       super.handleUiEvent(event);
     }
   }
 
+  protected void handleUiHistoryEntryActivated(JsonEvent event) {
+    addPropertyEventFilterCondition(m_browserHistoryFilter);
+    String deepLinkPath = event.getData().optString("deepLinkPath");
+    getModel().getUIFacade().historyEntryActivatedFromUI(deepLinkPath);
+  }
+
+  @Override
+  protected void handleUiPropertyChange(String propertyName, JSONObject data) {
+    if (IDesktop.PROP_NAVIGATION_VISIBLE.equals(propertyName)) {
+      boolean visible = data.getBoolean(propertyName);
+      addPropertyEventFilterCondition(IDesktop.PROP_NAVIGATION_VISIBLE, visible);
+      getModel().getUIFacade().setNavigationVisibleFromUI(visible);
+    }
+    else if (IDesktop.PROP_BENCH_VISIBLE.equals(propertyName)) {
+      boolean visible = data.getBoolean(propertyName);
+      addPropertyEventFilterCondition(IDesktop.PROP_BENCH_VISIBLE, visible);
+      getModel().getUIFacade().setBenchVisibleFromUI(visible);
+    }
+    else if (IDesktop.PROP_HEADER_VISIBLE.equals(propertyName)) {
+      boolean visible = data.getBoolean(propertyName);
+      addPropertyEventFilterCondition(IDesktop.PROP_HEADER_VISIBLE, visible);
+      getModel().getUIFacade().setHeaderVisibleFromUI(visible);
+    }
+  }
+
   protected void handleUiFormActivated(JsonEvent event) {
     String formId = event.getData().optString("formId", null);
     if (formId == null) {
@@ -137,22 +158,6 @@
     m_desktopEventFilter.removeAllConditions();
   }
 
-  /**
-   * Returns all filtered list of all {@link IAction}s provided by the desktop. The list does <b>not</b> include
-   * {@link IKeyStroke}s and {@link IViewButton}s, because those action types are handled separately. The returned list
-   * is ordered according to the actions {@link Order} annotation.
-   */
-  protected List<IAction> filterModelActions() {
-    OrderedCollection<IAction> result = new OrderedCollection<>();
-    for (IAction action : getModel().getActions()) {
-      if (action instanceof IKeyStroke || action instanceof IViewButton) {
-        continue; // skip
-      }
-      result.addOrdered(action);
-    }
-    return result.getOrderedList();
-  }
-
   @Override
   protected void attachModel() {
     super.attachModel();
@@ -200,25 +205,73 @@
         return getModel().isCacheSplitterPosition();
       }
     });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_BROWSER_HISTORY_ENTRY, model) {
+      @Override
+      protected BrowserHistoryEntry modelValue() {
+        return getModel().getBrowserHistoryEntry();
+      }
+
+      @Override
+      public Object prepareValueForToJson(Object value) {
+        return JsonBrowserHistoryEntry.toJson((BrowserHistoryEntry) value);
+      }
+    });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_LOGO_ID, model) {
+      @Override
+      protected Object modelValue() {
+        return getModel().getLogoId();
+      }
+
+      @Override
+      public Object prepareValueForToJson(Object value) {
+        return BinaryResourceUrlUtility.createIconUrl((String) value);
+      }
+
+      @Override
+      public String jsonPropertyName() {
+        return "logoUrl";
+      }
+    });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_NAVIGATION_VISIBLE, model) {
+      @Override
+      protected Object modelValue() {
+        return getModel().isNavigationVisible();
+      }
+    });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_NAVIGATION_HANDLE_VISIBLE, model) {
+      @Override
+      protected Object modelValue() {
+        return getModel().isNavigationHandleVisible();
+      }
+    });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_BENCH_VISIBLE, model) {
+      @Override
+      protected Object modelValue() {
+        return getModel().isBenchVisible();
+      }
+    });
+    putJsonProperty(new JsonProperty<DESKTOP>(IDesktop.PROP_HEADER_VISIBLE, model) {
+      @Override
+      protected Object modelValue() {
+        return getModel().isHeaderVisible();
+      }
+    });
   }
 
   @Override
   public JSONObject toJson() {
     JSONObject json = super.toJson();
-    json.put(IDesktop.PROP_DESKTOP_STYLE, getModel().getDesktopStyle());
+    json.put(IDesktop.PROP_DISPLAY_STYLE, getModel().getDisplayStyle());
     putAdapterIdProperty(json, IDesktop.PROP_ACTIVE_FORM, getModel().getActiveForm());
     putAdapterIdsProperty(json, "views", getModel().getViews(getModel()));
     putAdapterIdsProperty(json, "dialogs", getModel().getDialogs(getModel(), false));
     putAdapterIdsProperty(json, "messageBoxes", getModel().getMessageBoxes(getModel()));
     putAdapterIdsProperty(json, "fileChoosers", getModel().getFileChoosers(getModel()));
-    putAdapterIdsProperty(json, "actions", filterModelActions(), new DisplayableActionFilter<IAction>());
+    putAdapterIdsProperty(json, "menus", getModel().getMenus(), new DisplayableActionFilter<IMenu>());
     putAdapterIdsProperty(json, "addOns", getModel().getAddOns());
     putAdapterIdsProperty(json, "keyStrokes", getModel().getKeyStrokes(), new DisplayableActionFilter<IKeyStroke>());
-    if (hasDefaultStyle()) {
-      // FIXME cgu: view and tool buttons should be removed from desktop by device transformer
-      putAdapterIdsProperty(json, "viewButtons", getModel().getViewButtons(), new DisplayableActionFilter<IViewButton>());
-      putAdapterIdProperty(json, "outline", getModel().getOutline(), new DisplayableOutlineFilter<IOutline>());
-    }
+    putAdapterIdsProperty(json, "viewButtons", getModel().getViewButtons(), new DisplayableActionFilter<IViewButton>());
+    putAdapterIdProperty(json, "outline", getModel().getOutline(), new DisplayableOutlineFilter<IOutline>());
     return json;
   }
 
@@ -325,17 +378,15 @@
   }
 
   protected void handleModelOutlineChanged(IOutline outline) {
-    if (!hasDefaultStyle()) {
-      return;
+    String jsonOutlineId = null;
+    if (outline != null) {
+      IJsonAdapter<?> jsonOutline = attachGlobalAdapter(outline);
+      jsonOutlineId = jsonOutline.getId();
     }
-    IJsonAdapter<?> jsonAdapter = attachGlobalAdapter(outline);
-    addActionEvent(EVENT_OUTLINE_CHANGED, new JSONObject().put(PROP_OUTLINE, jsonAdapter.getId()));
+    addActionEvent(EVENT_OUTLINE_CHANGED, new JSONObject().put(PROP_OUTLINE, jsonOutlineId));
   }
 
   protected void handleModelOutlineContentActivate() {
-    if (!hasDefaultStyle()) {
-      return;
-    }
     addActionEvent(EVENT_OUTLINE_CONTENT_ACTIVATE);
   }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormMenu.java
similarity index 74%
rename from org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java
rename to org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormMenu.java
index dca1c42..35cfa4c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormMenu.java
@@ -10,8 +10,8 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json.desktop;
 
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
 import org.eclipse.scout.rt.client.ui.form.IForm;
+import org.eclipse.scout.rt.client.ui.form.IFormMenu;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
@@ -19,22 +19,22 @@
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfigBuilder;
 import org.eclipse.scout.rt.ui.html.json.menu.JsonMenu;
 
-public class JsonFormToolButton<FORM_TOOL_BUTTON extends IFormToolButton<IForm>> extends JsonMenu<FORM_TOOL_BUTTON> {
+public class JsonFormMenu<FORM_MENU extends IFormMenu<IForm>> extends JsonMenu<FORM_MENU> {
 
-  public JsonFormToolButton(FORM_TOOL_BUTTON model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
+  public JsonFormMenu(FORM_MENU model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
     super(model, uiSession, id, parent);
   }
 
   @Override
   public String getObjectType() {
-    return "FormToolButton";
+    return "FormMenu";
   }
 
   @Override
-  protected void initJsonProperties(FORM_TOOL_BUTTON model) {
+  protected void initJsonProperties(FORM_MENU model) {
     super.initJsonProperties(model);
 
-    putJsonProperty(new JsonAdapterProperty<IFormToolButton<IForm>>(IFormToolButton.PROP_FORM, model, getUiSession()) {
+    putJsonProperty(new JsonAdapterProperty<IFormMenu<IForm>>(IFormMenu.PROP_FORM, model, getUiSession()) {
       @Override
       protected IForm modelValue() {
         return getModel().getForm();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonOutline.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonOutline.java
index 6e53b83..2b1d46b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonOutline.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonOutline.java
@@ -33,7 +33,6 @@
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.InspectorInfo;
-import org.eclipse.scout.rt.ui.html.json.JsonEvent;
 import org.eclipse.scout.rt.ui.html.json.JsonProperty;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfig;
@@ -66,10 +65,10 @@
   @Override
   protected void initJsonProperties(OUTLINE model) {
     super.initJsonProperties(model);
-    putJsonProperty(new JsonProperty<OUTLINE>(IOutline.PROP_BREADCRUMB_ENABLED, model) {
+    putJsonProperty(new JsonProperty<OUTLINE>(IOutline.PROP_NAVIGATE_BUTTONS_VISIBLE, model) {
       @Override
       protected Boolean modelValue() {
-        return getModel().isBreadcrumbEnabled();
+        return getModel().isNavigateButtonsVisible();
       }
     });
     putJsonProperty(new JsonAdapterProperty<OUTLINE>(IOutline.PROP_DEFAULT_DETAIL_FORM, model, getUiSession()) {
@@ -140,21 +139,6 @@
   }
 
   @Override
-  public void handleUiEvent(JsonEvent event) {
-    super.handleUiEvent(event);
-    if ("breadcrumbEnabled".equals(event.getType())) {
-      handleUiBreadcrumbEnabled(event);
-    }
-    else {
-      super.handleUiEvent(event);
-    }
-  }
-
-  protected void handleUiBreadcrumbEnabled(JsonEvent event) {
-    getModel().setBreadcrumbEnabled(event.getData().getBoolean("breadcrumbEnabled"));
-  }
-
-  @Override
   protected void handleModelTreeEvent(TreeEvent event) {
     super.handleModelTreeEvent(event);
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/JsonSearchForm.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonSearchForm.java
similarity index 91%
rename from org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/JsonSearchForm.java
rename to org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonSearchForm.java
index b7d9d2d..2a12978 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/JsonSearchForm.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonSearchForm.java
@@ -8,11 +8,12 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.ui.html.json.form;
+package org.eclipse.scout.rt.ui.html.json.desktop;
 
 import org.eclipse.scout.rt.client.ui.desktop.outline.pages.ISearchForm;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
+import org.eclipse.scout.rt.ui.html.json.form.JsonForm;
 import org.json.JSONObject;
 
 public class JsonSearchForm<SEARCH_FORM extends ISearchForm> extends JsonForm<SEARCH_FORM> {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonDateField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonDateField.java
index d95a559..24172cd 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonDateField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonDateField.java
@@ -12,30 +12,22 @@
 
 import java.beans.PropertyChangeEvent;
 import java.util.Date;
+import java.util.List;
 
-import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 import org.eclipse.scout.rt.client.ui.form.fields.IValueField;
-import org.eclipse.scout.rt.client.ui.form.fields.ParsingFailedStatus;
 import org.eclipse.scout.rt.client.ui.form.fields.datefield.IDateField;
-import org.eclipse.scout.rt.platform.status.IMultiStatus;
-import org.eclipse.scout.rt.platform.status.IStatus;
-import org.eclipse.scout.rt.platform.util.StringUtility;
 import org.eclipse.scout.rt.platform.util.date.DateUtility;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.JsonDate;
 import org.eclipse.scout.rt.ui.html.json.JsonEvent;
 import org.eclipse.scout.rt.ui.html.json.JsonProperty;
-import org.eclipse.scout.rt.ui.html.json.JsonStatus;
-import org.json.JSONObject;
+import org.json.JSONArray;
 
 public class JsonDateField<T extends IDateField> extends JsonValueField<T> {
 
   private static final String PROP_TIMESTAMP = "timestamp";
   private static final String PROP_AUTO_TIMESTAMP = "autoTimestamp";
-  private static final String PROP_INVALID_DISPLAY_TEXT = "invalidDisplayText";
-  private static final String PROP_INVALID_DATE_TEXT = "invalidDateText";
-  private static final String PROP_INVALID_TIME_TEXT = "invalidTimeText";
   // UI events
   private static final String EVENT_TIMESTAMP_CHANGED = "timestampChanged";
   private static final String EVENT_PARSING_ERROR = "parsingError";
@@ -52,38 +44,6 @@
   @Override
   protected void initJsonProperties(T model) {
     super.initJsonProperties(model);
-
-    // Don't send the displayText to the UI. Formatting and parsing is done completely on the UI,
-    // the JSON layer only needs to send the format and the time stamp.
-    removeJsonProperty(IValueField.PROP_DISPLAY_TEXT);
-
-    putJsonProperty(new JsonProperty<T>(IFormField.PROP_ERROR_STATUS, model) {
-      @Override
-      protected IStatus modelValue() {
-        return getModel().getErrorStatus();
-      }
-
-      @Override
-      public Object prepareValueForToJson(Object value) {
-        JSONObject jsonStatus = JsonStatus.toJson((IStatus) value);
-        // Override default from JsonFormField: Send invalid input texts back to the UI.
-        if (jsonStatus != null && value instanceof IMultiStatus) {
-          IMultiStatus multiStatus = (IMultiStatus) value;
-          for (IStatus status : multiStatus.getChildren()) {
-            if (status instanceof ParsingFailedStatus) {
-              ParsingFailedStatus parsingFailedStatus = (ParsingFailedStatus) status;
-              String parseInputString = StringUtility.nvl(parsingFailedStatus.getParseInputString(), "");
-              String[] texts = parseInputString.split("\n", -1); // -1 preserves trailing empty strings
-              if (texts.length == 2) {
-                jsonStatus.put(PROP_INVALID_DATE_TEXT, texts[0]);
-                jsonStatus.put(PROP_INVALID_TIME_TEXT, texts[1]);
-              }
-            }
-          }
-        }
-        return jsonStatus;
-      }
-    });
     putJsonProperty(new JsonProperty<T>(PROP_TIMESTAMP, model) {
       @Override
       protected Date modelValue() {
@@ -130,6 +90,26 @@
         return getModel().getTimeFormatPattern();
       }
     });
+    putJsonProperty(new JsonProperty<T>(IDateField.PROP_ALLOWED_DATES, model) {
+      @Override
+      protected List<Date> modelValue() {
+        return getModel().getAllowedDates();
+      }
+
+      @Override
+      @SuppressWarnings("unchecked")
+      public Object prepareValueForToJson(Object value) {
+        List<Date> allowedDates = (List<Date>) value;
+        if (allowedDates == null || allowedDates.isEmpty()) {
+          return null;
+        }
+        JSONArray dateArray = new JSONArray();
+        for (Date date : allowedDates) {
+          dateArray.put(dateToJson(date));
+        }
+        return dateArray;
+      }
+    });
   }
 
   protected String dateToJson(Date date) {
@@ -156,14 +136,6 @@
         addPropertyChangeEvent(PROP_AUTO_TIMESTAMP, dateToJson((Date) event.getNewValue()));
       }
     }
-    else if (IDateField.PROP_ERROR_STATUS.equals(propertyName)) {
-      //if error occured thru wrong input and model is resetting value to null it has to be submitted to client.
-      // -> only displayText is changed on model so there will be no event for value changed
-      if (getModel().getValue() == null && getModel().getDisplayText() == "" && event.getNewValue() == null) {
-        addPropertyChangeEvent(PROP_TIMESTAMP, dateToJson((Date) event.getNewValue()));
-      }
-      super.handleModelPropertyChange(event);
-    }
     else {
       super.handleModelPropertyChange(event);
     }
@@ -197,20 +169,17 @@
   }
 
   protected void handleUiParsingError(JsonEvent event) {
-    String invalidDisplayText = event.getData().optString(PROP_INVALID_DISPLAY_TEXT, null);
-    String invalidDateText = event.getData().optString(PROP_INVALID_DATE_TEXT, null);
-    String invalidTimeText = event.getData().optString(PROP_INVALID_TIME_TEXT, null);
     getModel().getUIFacade().removeParseErrorFromUI();
-    getModel().getUIFacade().setParseErrorFromUI(invalidDisplayText, invalidDateText, invalidTimeText);
+    getModel().getUIFacade().setParseErrorFromUI();
   }
 
   @Override
   protected void handleUiDisplayTextChangedWhileTyping(String displayText) {
-    throw new IllegalStateException("DisplayText may not be set manually");
+    throw new IllegalStateException("While typing is not supported by the date field.");
   }
 
   @Override
   protected void handleUiDisplayTextChangedAfterTyping(String displayText) {
-    throw new IllegalStateException("DisplayText may not be set manually");
+    getModel().getUIFacade().setDisplayTextFromUI(displayText);
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonFormField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonFormField.java
index 213ee97..96deb64 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonFormField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/JsonFormField.java
@@ -90,6 +90,12 @@
         return getModel().isStatusVisible();
       }
     });
+    putJsonProperty(new JsonProperty<FORM_FIELD>(IFormField.PROP_STATUS_POSITION, model) {
+      @Override
+      protected String modelValue() {
+        return getModel().getStatusPosition();
+      }
+    });
     putJsonProperty(new JsonProperty<FORM_FIELD>(IFormField.PROP_CSS_CLASS, model) {
       @Override
       protected String modelValue() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
index 29e3f09..65bf7d8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/browserfield/JsonBrowserField.java
@@ -45,7 +45,7 @@
   @Override
   protected void initJsonProperties(BROWSER_FIELD model) {
     super.initJsonProperties(model);
-    putJsonProperty(new JsonProperty<IBrowserField>(IBrowserField.PROP_SCROLLBARS_ENABLED, model) {
+    putJsonProperty(new JsonProperty<IBrowserField>(IBrowserField.PROP_SCROLL_BAR_ENABLED, model) {
       @Override
       protected Boolean modelValue() {
         return getModel().isScrollBarEnabled();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlField.java
index faf2c52..e604128 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/htmlfield/JsonHtmlField.java
@@ -60,19 +60,19 @@
       }
     });
 
-    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLLBARS_ENABLED, model) {
+    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLL_BAR_ENABLED, model) {
       @Override
       protected Boolean modelValue() {
         return getModel().isScrollBarEnabled();
       }
     });
-    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLLBAR_SCROLL_TO_END, model) {
+    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLL_TO_END, model) {
       @Override
       protected Object modelValue() {
         return null; // This property is not really a property, but an event, therefore it does not have a value
       }
     });
-    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLLBAR_SCROLL_TO_ANCHOR, model) {
+    putJsonProperty(new JsonProperty<IHtmlField>(IHtmlField.PROP_SCROLL_TO_ANCHOR, model) {
       @Override
       protected String modelValue() {
         return getModel().getScrollToAnchor();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonProposalChooser.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonProposalChooser.java
index 216ce09..8fb11a4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonProposalChooser.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonProposalChooser.java
@@ -20,6 +20,7 @@
 import org.eclipse.scout.rt.ui.html.json.JsonProperty;
 import org.eclipse.scout.rt.ui.html.json.JsonStatus;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
+import org.json.JSONArray;
 import org.json.JSONObject;
 
 public class JsonProposalChooser<PROPOSAL_CHOOSER extends IProposalChooser> extends AbstractJsonPropertyObserver<PROPOSAL_CHOOSER> {
@@ -90,7 +91,9 @@
     JSONObject json = super.toJson();
     if (getModel().isActiveFilterEnabled()) {
       putProperty(json, "activeFilter", getModel().getActiveFilter().name());
+      putProperty(json, "activeFilterLabels", new JSONArray(getModel().getActiveFilterLabels()));
     }
     return json;
   }
+
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonSmartField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonSmartField.java
index 9b6ec58..9ab6b57 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonSmartField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/smartfield/JsonSmartField.java
@@ -60,7 +60,7 @@
 
   @Override
   public void handleUiEvent(JsonEvent event) {
-    // NOTE: it's important we always set the submitted 'searchText' as display text
+    // NOTE: it's important we always set the submitted 'displayText' as display text
     // on the model field instance. Otherwise the java client will be out of sync
     // with the browser, which will cause a variety of bugs in the UI. This happens
     // in the UI facade impl.
@@ -85,7 +85,7 @@
   }
 
   protected void handleUiProposalTyped(JsonEvent event) {
-    String text = getSearchTextAndAddFilter(event);
+    String text = getDisplayTextAndAddFilter(event);
     getModel().getUIFacade().proposalTypedFromUI(text);
   }
 
@@ -94,16 +94,8 @@
   }
 
   protected void handleUiAcceptProposal(JsonEvent event) {
-    String text = getSearchTextAndAddFilter(event);
+    String text = getDisplayTextAndAddFilter(event);
     boolean chooser = event.getData().getBoolean("chooser");
-
-    // >>> [to be removed]
-    if (chooser && getModel().getProposalChooser() == null) {
-      // FIXME awe: ensure this state not to happen in UI; happens, once a focused smartfield looses focuses by a mouse click (e.g. by clicking into another field), and is based due to 2 'acceptInput' events (mouseclick and blur)
-      return;
-    }
-    // <<< [to be removed]
-
     boolean forceClose = event.getData().getBoolean("forceClose");
     getModel().getUIFacade().acceptProposalFromUI(text, chooser, forceClose);
   }
@@ -114,20 +106,20 @@
 
   protected void handleUiOpenProposal(JsonEvent event) {
     boolean browseAll = event.getData().optBoolean("browseAll");
-    String searchText = event.getData().optString("searchText", null);
+    String displayText = event.getData().optString("displayText", null);
     if (browseAll) {
       if (getModel().getErrorStatus() == null || (getModel().getErrorStatus() != null && !checkStatusContainsCode(getModel().getErrorStatus(), AbstractMixedSmartField.NOT_UNIQUE_ERROR_CODE))) {
-        searchText = "*";
+        displayText = "*";
       }
     }
-    addPropertyEventFilterCondition(IValueField.PROP_DISPLAY_TEXT, searchText);
+    addPropertyEventFilterCondition(IValueField.PROP_DISPLAY_TEXT, displayText);
     boolean selectCurrentValue = event.getData().optBoolean("selectCurrentValue");
-    LOG.debug("handle openProposal -> openProposalFromUI. searchText={} selectCurrentValue={}", searchText, selectCurrentValue);
-    getModel().getUIFacade().openProposalChooserFromUI(searchText, selectCurrentValue);
+    LOG.debug("handle openProposal -> openProposalFromUI. displayText={} selectCurrentValue={}", displayText, selectCurrentValue);
+    getModel().getUIFacade().openProposalChooserFromUI(displayText, selectCurrentValue);
   }
 
-  private String getSearchTextAndAddFilter(JsonEvent event) {
-    String text = event.getData().optString("searchText", null);
+  private String getDisplayTextAndAddFilter(JsonEvent event) {
+    String text = event.getData().optString("displayText", null);
     addPropertyEventFilterCondition(IValueField.PROP_DISPLAY_TEXT, text);
     return text;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/splitbox/JsonSplitBox.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/splitbox/JsonSplitBox.java
index 3a4b2f1..4fe65e8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/splitbox/JsonSplitBox.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/splitbox/JsonSplitBox.java
@@ -34,19 +34,22 @@
   public JsonSplitBox(SPLIT_BOX model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
     super(model, uiSession, id, parent);
     List<IFormField> fields = model.getFields();
+    int numFields = fields.size();
     IFormField firstField = null;
     IFormField secondField = null;
-    if (fields.size() > 0) {
+
+    if (numFields >= 1) {
       firstField = fields.get(0);
-      if (fields.size() > 1) {
-        secondField = fields.get(1);
-        if (fields.size() > 2) {
-          LOG.warn("Split box only supports two fields. {} surplus fields are ignored in {}.", (fields.size() - 2), model);
-        }
-      }
     }
-    m_firstField = (firstField != null && firstField.isVisibleGranted()) ? firstField : null;
-    m_secondField = (secondField != null && secondField.isVisibleGranted()) ? secondField : null;
+    if (numFields >= 2) {
+      secondField = fields.get(1);
+    }
+    if (numFields > 2) {
+      LOG.warn("Split box only supports two fields. {} surplus fields are ignored in {}.", (numFields - 2), model);
+    }
+
+    m_firstField = getFieldIfVisibleGranted(firstField);
+    m_secondField = getFieldIfVisibleGranted(secondField);
   }
 
   @Override
@@ -54,6 +57,10 @@
     return "SplitBox";
   }
 
+  protected static IFormField getFieldIfVisibleGranted(IFormField field) {
+    return field != null && field.isVisibleGranted() ? field : null;
+  }
+
   @Override
   protected void initJsonProperties(SPLIT_BOX model) {
     super.initJsonProperties(model);
@@ -75,6 +82,35 @@
         return getModel().isSplitterEnabled();
       }
     });
+    putJsonProperty(new JsonProperty<ISplitBox>(ISplitBox.PROP_COLLAPSIBLE_FIELD, model) {
+      @Override
+      protected IFormField modelValue() {
+        return getModel().getCollapsibleField();
+      }
+
+      @Override
+      public Object prepareValueForToJson(Object value) {
+        // Deals with the case the field is configured as collapsible, but it is not visible (granted)
+        // in that case it has never been attached.
+        IFormField field = getFieldIfVisibleGranted((IFormField) value);
+        if (field == null) {
+          return null;
+        }
+        return getAdapter(field).getId();
+      }
+    });
+    putJsonProperty(new JsonProperty<ISplitBox>(ISplitBox.PROP_FIELD_COLLAPSED, model) {
+      @Override
+      protected Boolean modelValue() {
+        return getModel().isFieldCollapsed();
+      }
+    });
+    putJsonProperty(new JsonProperty<ISplitBox>(ISplitBox.PROP_COLLAPSE_KEY_STROKE, model) {
+      @Override
+      protected String modelValue() {
+        return getModel().getCollapseKeyStroke();
+      }
+    });
   }
 
   @Override
@@ -111,6 +147,15 @@
     }
   }
 
+  @Override
+  protected void handleUiPropertyChange(String propertyName, JSONObject data) {
+    if (ISplitBox.PROP_FIELD_COLLAPSED.equals(propertyName)) {
+      boolean fieldCollapsed = data.getBoolean("fieldCollapsed");
+      addPropertyEventFilterCondition(ISplitBox.PROP_FIELD_COLLAPSED, fieldCollapsed);
+      getModel().setFieldCollapsed(fieldCollapsed);
+    }
+  }
+
   protected void handleUiSetSplitterPosition(JsonEvent event) {
     double splitterPosition = event.getData().optDouble("splitterPosition");
     addPropertyEventFilterCondition(ISplitBox.PROP_SPLITTER_POSITION, splitterPosition);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/wrappedform/JsonWrappedFormField.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/wrappedform/JsonWrappedFormField.java
index 2b46046..22e8c0f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/wrappedform/JsonWrappedFormField.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/form/fields/wrappedform/JsonWrappedFormField.java
@@ -14,6 +14,7 @@
 import org.eclipse.scout.rt.client.ui.form.fields.wrappedform.IWrappedFormField;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
+import org.eclipse.scout.rt.ui.html.json.JsonProperty;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfig;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfigBuilder;
@@ -44,5 +45,11 @@
         return getModel().getInnerForm();
       }
     });
+    putJsonProperty(new JsonProperty<WRAPPED_FORM_FIELD>(IWrappedFormField.PROP_INITIAL_FOCUS_ENABLED, model) {
+      @Override
+      protected Boolean modelValue() {
+        return getModel().isInitialFocusEnabled();
+      }
+    });
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/menu/JsonMenu.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/menu/JsonMenu.java
index c1e5903..3645f5a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/menu/JsonMenu.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/menu/JsonMenu.java
@@ -15,10 +15,12 @@
 
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.action.menu.IMenuType;
+import org.eclipse.scout.rt.client.ui.desktop.outline.OutlineMenuWrapper;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.JsonProperty;
 import org.eclipse.scout.rt.ui.html.json.action.JsonAction;
+import org.json.JSONArray;
 
 public class JsonMenu<MENU extends IMenu> extends JsonAction<MENU> {
 
@@ -45,6 +47,13 @@
       }
     });
 
+    putJsonProperty(new JsonProperty<MENU>("outlineMenuWrapper", model) {
+      @Override
+      protected Boolean modelValue() {
+        return getModel() instanceof OutlineMenuWrapper;
+      }
+    });
+
     putJsonProperty(new JsonProperty<MENU>(IMenu.PROP_MENU_TYPES, model) {
       @Override
       protected Set<IMenuType> modelValue() {
@@ -58,7 +67,7 @@
           String prefix = type.getClass().getSimpleName().replace("MenuType", "");
           menuTypes.add(prefix + "." + type.toString());
         }
-        return menuTypes;
+        return new JSONArray(menuTypes);
       }
     });
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/messagebox/JsonMessageBox.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/messagebox/JsonMessageBox.java
index a8bb5aa..b457431 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/messagebox/JsonMessageBox.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/messagebox/JsonMessageBox.java
@@ -71,7 +71,7 @@
     putJsonProperty(new JsonProperty<IMessageBox>("html", model) {
       @Override
       protected String modelValue() {
-        return getModel().getHtml() == null ? null : getModel().getHtml().toEncodedHtml();
+        return getModel().getHtml() == null ? null : getModel().getHtml().toHtml();
       }
     });
     putJsonProperty(new JsonProperty<IMessageBox>("hiddenText", model) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/JsonTable.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/JsonTable.java
index fbcc637..6081965 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/JsonTable.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/JsonTable.java
@@ -174,12 +174,6 @@
         return getModel().isMultilineText();
       }
     });
-    putJsonProperty(new JsonProperty<ITable>(ITable.PROP_ROW_HEIGHT_HINT, model) {
-      @Override
-      protected Integer modelValue() {
-        return getModel().getRowHeightHint();
-      }
-    });
     putJsonProperty(new JsonProperty<ITable>(ITable.PROP_CHECKABLE, model) {
       @Override
       protected Boolean modelValue() {
@@ -911,7 +905,7 @@
     return jsonColumnIds;
   }
 
-  protected IColumn optColumn(String columnId) {
+  public IColumn optColumn(String columnId) {
     return m_columns.get(columnId);
   }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControl.java
similarity index 62%
copy from org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java
copy to org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControl.java
index dca1c42..9abc0bc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/desktop/JsonFormToolButton.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonFormTableControl.java
@@ -8,42 +8,48 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-package org.eclipse.scout.rt.ui.html.json.desktop;
+package org.eclipse.scout.rt.ui.html.json.table.control;
 
-import org.eclipse.scout.rt.client.ui.desktop.outline.IFormToolButton;
+import org.eclipse.scout.rt.client.ui.action.IAction;
+import org.eclipse.scout.rt.client.ui.basic.table.controls.IFormTableControl;
 import org.eclipse.scout.rt.client.ui.form.IForm;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfig;
 import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfigBuilder;
-import org.eclipse.scout.rt.ui.html.json.menu.JsonMenu;
 
-public class JsonFormToolButton<FORM_TOOL_BUTTON extends IFormToolButton<IForm>> extends JsonMenu<FORM_TOOL_BUTTON> {
+public class JsonFormTableControl<TABLE_CONTROL extends IFormTableControl> extends JsonTableControl<TABLE_CONTROL> {
 
-  public JsonFormToolButton(FORM_TOOL_BUTTON model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
+  public JsonFormTableControl(TABLE_CONTROL model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
     super(model, uiSession, id, parent);
   }
 
   @Override
-  public String getObjectType() {
-    return "FormToolButton";
-  }
-
-  @Override
-  protected void initJsonProperties(FORM_TOOL_BUTTON model) {
+  protected void initJsonProperties(TABLE_CONTROL model) {
     super.initJsonProperties(model);
+    putJsonProperty(new JsonAdapterProperty<TABLE_CONTROL>(TABLE_CONTROL.PROP_FORM, model, getUiSession()) {
+      @Override
+      protected JsonAdapterPropertyConfig createConfig() {
+        return JsonAdapterPropertyConfigBuilder.globalConfig();
+      }
 
-    putJsonProperty(new JsonAdapterProperty<IFormToolButton<IForm>>(IFormToolButton.PROP_FORM, model, getUiSession()) {
       @Override
       protected IForm modelValue() {
         return getModel().getForm();
       }
 
       @Override
-      protected JsonAdapterPropertyConfig createConfig() {
-        return JsonAdapterPropertyConfigBuilder.globalConfig();
+      public boolean accept() {
+        return getModel().isSelected();
       }
     });
+    getJsonProperty(IAction.PROP_SELECTED).addLazyProperty(getJsonProperty(TABLE_CONTROL.PROP_FORM));
   }
+
+  @Override
+  public String getObjectType() {
+    return "FormTableControl";
+  }
+
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControl.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControl.java
index e1b1e11..b60e4a8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControl.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/table/control/JsonTableControl.java
@@ -10,63 +10,20 @@
  ******************************************************************************/
 package org.eclipse.scout.rt.ui.html.json.table.control;
 
-import org.eclipse.scout.rt.client.ui.action.IAction;
 import org.eclipse.scout.rt.client.ui.basic.table.controls.ITableControl;
-import org.eclipse.scout.rt.client.ui.form.IForm;
 import org.eclipse.scout.rt.ui.html.IUiSession;
 import org.eclipse.scout.rt.ui.html.json.IJsonAdapter;
-import org.eclipse.scout.rt.ui.html.json.JsonEvent;
 import org.eclipse.scout.rt.ui.html.json.action.JsonAction;
-import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterProperty;
-import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfig;
-import org.eclipse.scout.rt.ui.html.json.form.fields.JsonAdapterPropertyConfigBuilder;
 
 public class JsonTableControl<TABLE_CONTROL extends ITableControl> extends JsonAction<TABLE_CONTROL> {
-  protected boolean m_contentLoaded = false;
 
   public JsonTableControl(TABLE_CONTROL model, IUiSession uiSession, String id, IJsonAdapter<?> parent) {
     super(model, uiSession, id, parent);
   }
 
   @Override
-  protected void initJsonProperties(TABLE_CONTROL model) {
-    super.initJsonProperties(model);
-    putJsonProperty(new JsonAdapterProperty<ITableControl>(ITableControl.PROP_FORM, model, getUiSession()) {
-      @Override
-      protected JsonAdapterPropertyConfig createConfig() {
-        return JsonAdapterPropertyConfigBuilder.globalConfig();
-      }
-
-      @Override
-      protected IForm modelValue() {
-        return getModel().getForm();
-      }
-
-      @Override
-      public boolean accept() {
-        return getModel().isSelected();
-      }
-    });
-    getJsonProperty(IAction.PROP_SELECTED).addLazyProperty(getJsonProperty(ITableControl.PROP_FORM));
-  }
-
-  @Override
   public String getObjectType() {
     return "TableControl";
   }
 
-  @Override
-  protected void handleUiSelected(JsonEvent event) {
-    super.handleUiSelected(event);
-
-    // Lazy loading content on selection (temporary used for subclasses until subclasses are finally implemented)
-    if (getModel().isSelected() && !m_contentLoaded) {
-      handleUiLoadContent();
-      m_contentLoaded = true;
-    }
-  }
-
-  protected void handleUiLoadContent() {
-  }
-
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/tree/JsonTree.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/tree/JsonTree.java
index 410bb66..065b659 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/tree/JsonTree.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/json/tree/JsonTree.java
@@ -24,7 +24,6 @@
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.action.menu.root.IContextMenu;
 import org.eclipse.scout.rt.client.ui.basic.cell.ICell;
-import org.eclipse.scout.rt.client.ui.basic.table.ITable;
 import org.eclipse.scout.rt.client.ui.basic.tree.ITree;
 import org.eclipse.scout.rt.client.ui.basic.tree.ITreeNode;
 import org.eclipse.scout.rt.client.ui.basic.tree.IVirtualTreeNode;
@@ -141,6 +140,12 @@
         return getModel().isEnabled();
       }
     });
+    putJsonProperty(new JsonProperty<TREE>(ITree.PROP_LAZY_EXPANDING_ENABLED, model) {
+      @Override
+      protected Boolean modelValue() {
+        return getModel().isLazyExpandingEnabled();
+      }
+    });
     putJsonProperty(new JsonProperty<TREE>(ITree.PROP_AUTO_CHECK_CHILDREN, model) {
       @Override
       protected Boolean modelValue() {
@@ -165,7 +170,7 @@
         return getModel().getDropMaximumSize();
       }
     });
-    putJsonProperty(new JsonAdapterProperty<ITree>(ITable.PROP_KEY_STROKES, model, getUiSession()) {
+    putJsonProperty(new JsonAdapterProperty<ITree>(ITree.PROP_KEY_STROKES, model, getUiSession()) {
       @Override
       protected JsonAdapterPropertyConfig createConfig() {
         return new JsonAdapterPropertyConfigBuilder().filter(new DisplayableActionFilter<IAction>()).build();
@@ -176,6 +181,18 @@
         return getModel().getKeyStrokes();
       }
     });
+    putJsonProperty(new JsonProperty<TREE>(ITree.PROP_DISPLAY_STYLE, model) {
+      @Override
+      protected String modelValue() {
+        return getModel().getDisplayStyle();
+      }
+    });
+    putJsonProperty(new JsonProperty<TREE>(ITree.PROP_AUTO_TOGGLE_BREADCRUMB_STYLE, model) {
+      @Override
+      protected Boolean modelValue() {
+        return getModel().isAutoToggleBreadcrumbStyle();
+      }
+    });
   }
 
   @Override
@@ -891,6 +908,15 @@
     getModel().getUIFacade().setNodeExpandedFromUI(node, expanded, lazy);
   }
 
+  @Override
+  protected void handleUiPropertyChange(String propertyName, JSONObject data) {
+    if (ITree.PROP_DISPLAY_STYLE.equals(propertyName)) {
+      String displayStyle = data.getString(ITree.PROP_DISPLAY_STYLE);
+      addPropertyEventFilterCondition(ITree.PROP_DISPLAY_STYLE, displayStyle);
+      getModel().getUIFacade().setDisplayStyleFromUI(displayStyle);
+    }
+  }
+
   /**
    * Ignore deleted or filtered nodes, because for the UI, they don't exist
    */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BinaryResourceUrlUtility.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BinaryResourceUrlUtility.java
index 32942cd..297cbf8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BinaryResourceUrlUtility.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BinaryResourceUrlUtility.java
@@ -57,10 +57,6 @@
    */
   public static final Pattern PATTERN_DYNAMIC_ADAPTER_RESOURCE_PATH = Pattern.compile("^/dynamic/([^/]*)/([^/]*)/(.*)$");
 
-  // FIXME awe: (font icons) extend syntax for icon-ID so a font-name can be configured
-  // font:[char] --> uses default scoutIcons.ttf (CSS class .font-icon)
-  // font.crm:[char] --> uses crmIcons.ttf (CSS class .crm-font-icon)
-
   /**
    * @return a relative URL for a configured logical icon-name or a font-based icon. For instance:
    *         <ul>
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BrowserInfo.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BrowserInfo.java
index cea0a43..915c0d8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BrowserInfo.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/BrowserInfo.java
@@ -11,13 +11,14 @@
 package org.eclipse.scout.rt.ui.html.res;
 
 import java.util.Enumeration;
-import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.servlet.http.HttpServletRequest;
 
 import org.eclipse.scout.rt.platform.util.StringUtility;
+import org.eclipse.scout.rt.shared.ui.UiEngineType;
+import org.eclipse.scout.rt.shared.ui.UiSystem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -29,14 +30,6 @@
 public class BrowserInfo {
   private static final Logger LOG = LoggerFactory.getLogger(BrowserInfo.class);
 
-  public static enum EngineType {
-    ANDROID, CHROME, SAFARI, FIREFOX, IE, OPERA, KONQUEROR, UNKNOWN
-  }
-
-  public static enum System {
-    WINDOWS, UNIX, OSX, IOS, ANDROID, UNKNOWN
-  }
-
   public static class BrowserVersion implements Comparable<BrowserVersion> {
 
     private final int m_major;
@@ -125,9 +118,8 @@
   }
 
   private final String m_userAgent;
-  private final Locale m_locale;
 
-  private EngineType m_engineType = EngineType.UNKNOWN;
+  private UiEngineType m_engineType = UiEngineType.UNKNOWN;
   private BrowserVersion m_engineVersion;
   // Basic engine types
   private boolean m_isWebkit = false;
@@ -135,7 +127,7 @@
   private boolean m_isMshtml = false;
   private boolean m_isOpera = false;
 
-  private System m_system = System.UNKNOWN;
+  private UiSystem m_system = UiSystem.UNKNOWN;
   private BrowserVersion m_systemVersion;
 
   // Flags
@@ -143,9 +135,8 @@
   private boolean m_isTablet = false;
   private boolean m_isStandalone = false;
 
-  public BrowserInfo(String userAgent, Locale locale) {
+  public BrowserInfo(String userAgent) {
     m_userAgent = (userAgent == null ? "" : userAgent);
-    m_locale = locale;
 
     initInfos();
   }
@@ -161,7 +152,7 @@
     boolean isOpera = StringUtility.contains(m_userAgent, regex);
     if (isOpera) {
       setOpera(true);
-      setEngineType(EngineType.OPERA);
+      setEngineType(UiEngineType.OPERA);
       setEngineVersion(extractVersion(m_userAgent, regex));
       return;
     }
@@ -171,7 +162,7 @@
     boolean isKonqueror = StringUtility.contains(m_userAgent, regex);
     if (isKonqueror) {
       setWebkit(true);
-      setEngineType(EngineType.KONQUEROR);
+      setEngineType(UiEngineType.KONQUEROR);
       setEngineVersion(extractVersion(m_userAgent, regex));
       return;
     }
@@ -182,19 +173,19 @@
     if (isWebkit) {
       setWebkit(true);
       if (m_userAgent.indexOf("Chrome") != -1) {
-        setEngineType(EngineType.CHROME);
+        setEngineType(UiEngineType.CHROME);
       }
       else if (m_userAgent.indexOf("Safari") != -1) {
         if (m_userAgent.indexOf("Android") != -1) {
-          setEngineType(EngineType.ANDROID);
+          setEngineType(UiEngineType.ANDROID);
         }
         else {
-          setEngineType(EngineType.SAFARI);
+          setEngineType(UiEngineType.SAFARI);
         }
       }
       else if (m_userAgent.indexOf("Mobile") != -1) {
         // iPad reports this in fullscreen mode
-        setEngineType(EngineType.SAFARI);
+        setEngineType(UiEngineType.SAFARI);
         setStandalone(true);
       }
       setEngineVersion(extractVersion(m_userAgent, regex));
@@ -206,7 +197,7 @@
     boolean isMshtml = StringUtility.contains(m_userAgent, regex);
     if (isMshtml) {
       setMshtml(true);
-      setEngineType(EngineType.IE);
+      setEngineType(UiEngineType.IE);
       setEngineVersion(extractVersion(m_userAgent, regex));
       return;
     }
@@ -217,7 +208,7 @@
     if (isGecko) {
       setGecko(true);
       if (m_userAgent.indexOf("Firefox") != -1) {
-        setEngineType(EngineType.FIREFOX);
+        setEngineType(UiEngineType.FIREFOX);
       }
       setEngineVersion(extractVersion(m_userAgent, regex));
       return;
@@ -226,7 +217,7 @@
 
   protected void initSystemInfo() {
     if (m_userAgent.indexOf("Windows") != -1 || m_userAgent.indexOf("Win32") != -1 || m_userAgent.indexOf("Win64") != -1 || m_userAgent.indexOf("Win95") != -1) {
-      setSystem(System.WINDOWS);
+      setSystem(UiSystem.WINDOWS);
       if (m_userAgent.indexOf("Windows Phone") != -1 || m_userAgent.indexOf("IEMobile") != -1) {
         setSystemVersion(parseWindowsPhoneVersion(m_userAgent));
         setMobile(true);
@@ -236,10 +227,10 @@
       }
     }
     else if (m_userAgent.indexOf("Macintosh") != -1 || m_userAgent.indexOf("MacPPC") != -1 || m_userAgent.indexOf("MacIntel") != -1 || m_userAgent.indexOf("Mac_PowerPC") != -1) {
-      setSystem(System.OSX);
+      setSystem(UiSystem.OSX);
     }
     else if (m_userAgent.indexOf("Android") != -1) {
-      setSystem(System.ANDROID);
+      setSystem(UiSystem.ANDROID);
       setSystemVersion(parseAndroidVersion(m_userAgent));
 
       // Update mobile/tablet flags based on android version
@@ -260,15 +251,15 @@
       }
     }
     else if (m_userAgent.indexOf("X11") != -1 || m_userAgent.indexOf("Linux") != -1 || m_userAgent.indexOf("BSD") != -1 || m_userAgent.indexOf("SunOS") != -1 || m_userAgent.indexOf("DragonFly") != -1) {
-      setSystem(System.UNIX);
+      setSystem(UiSystem.UNIX);
     }
     else if (m_userAgent.indexOf("iPad") != -1) {
-      setSystem(System.IOS);
+      setSystem(UiSystem.IOS);
       setSystemVersion(parseIosVersion(m_userAgent));
       setTablet(true);
     }
     else if (m_userAgent.indexOf("iPhone") != -1 || m_userAgent.indexOf("iPod") != -1) {
-      setSystem(System.IOS);
+      setSystem(UiSystem.IOS);
       setSystemVersion(parseIosVersion(m_userAgent));
       setMobile(true);
     }
@@ -278,10 +269,6 @@
     return m_userAgent;
   }
 
-  public Locale getLocale() {
-    return m_locale;
-  }
-
   public boolean isWebkit() {
     return m_isWebkit;
   }
@@ -341,19 +328,19 @@
     m_isStandalone = isStandalone;
   }
 
-  public EngineType getEngineType() {
+  public UiEngineType getEngineType() {
     return m_engineType;
   }
 
-  protected void setEngineType(EngineType engineType) {
+  protected void setEngineType(UiEngineType engineType) {
     m_engineType = engineType;
   }
 
-  public System getSystem() {
+  public UiSystem getSystem() {
     return m_system;
   }
 
-  protected void setSystem(System system) {
+  protected void setSystem(UiSystem system) {
     m_system = system;
   }
 
@@ -388,7 +375,6 @@
     result = prime * result + (m_isStandalone ? 1231 : 1237);
     result = prime * result + (m_isTablet ? 1231 : 1237);
     result = prime * result + (m_isWebkit ? 1231 : 1237);
-    result = prime * result + ((m_locale == null) ? 0 : m_locale.hashCode());
     result = prime * result + ((m_system == null) ? 0 : m_system.hashCode());
     result = prime * result + ((m_systemVersion == null) ? 0 : m_systemVersion.hashCode());
     result = prime * result + ((m_engineType == null) ? 0 : m_engineType.hashCode());
@@ -430,14 +416,6 @@
     if (m_isWebkit != other.m_isWebkit) {
       return false;
     }
-    if (m_locale == null) {
-      if (other.m_locale != null) {
-        return false;
-      }
-    }
-    else if (!m_locale.equals(other.m_locale)) {
-      return false;
-    }
     if (m_system != other.m_system) {
       return false;
     }
@@ -473,7 +451,7 @@
 
   @Override
   public String toString() {
-    StringBuffer sb = new StringBuffer("System: ").append(getSystem());
+    StringBuilder sb = new StringBuilder("System: ").append(getSystem());
     sb.append(" / SystemVersion: ").append(getSystemVersion());
     if (isWebkit()) {
       sb.append(" / isWebkit");
@@ -508,12 +486,11 @@
     }
 
     String userAgent = request.getHeader("User-Agent");
-    BrowserInfo info = createFrom(userAgent, request.getLocale());
-    return info;
+    return createFrom(userAgent);
   }
 
-  public static BrowserInfo createFrom(String userAgent, Locale locale) {
-    BrowserInfo info = new BrowserInfo(userAgent, locale);
+  public static BrowserInfo createFrom(String userAgent) {
+    BrowserInfo info = new BrowserInfo(userAgent);
 
     if (LOG.isTraceEnabled()) {
       LOG.trace(info.toString());
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/ResourceRequestHandler.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/ResourceRequestHandler.java
index 50ada9f..e26fb5b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/ResourceRequestHandler.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/ResourceRequestHandler.java
@@ -131,6 +131,10 @@
     return m_httpCacheControl;
   }
 
+  /**
+   * @return index.html for requests on root (empty or /) and also for deep-link requests, for all other requests the
+   *         pathInfo from the given request
+   */
   protected String resolvePathInfoEx(HttpServletRequest req) {
     String pathInfo = req.getPathInfo();
     if (pathInfo == null) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/DynamicResourceLoader.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/DynamicResourceLoader.java
index 4d787aa..9fb99e7 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/DynamicResourceLoader.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/DynamicResourceLoader.java
@@ -119,7 +119,7 @@
     String isoFilename = originalFilename;
     CharsetEncoder iso8859Encoder = StandardCharsets.ISO_8859_1.newEncoder();
     if (!iso8859Encoder.canEncode(originalFilename)) {
-      StringBuffer sb = new StringBuffer();
+      StringBuilder sb = new StringBuilder();
       for (char c : originalFilename.toCharArray()) {
         if (iso8859Encoder.canEncode(String.valueOf(c))) {
           sb.append(c);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParser.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParser.java
index ff0d42e..4a581a7 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParser.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParser.java
@@ -40,6 +40,7 @@
   private static final Pattern PATTERN_MESSAGE_TAG = Pattern.compile("<scout\\:message(.*)/>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
   private static final Pattern PATTERN_STYLESHEET_TAG = Pattern.compile("<scout\\:stylesheet src=\"(.*?)\"(.*)/>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
   private static final Pattern PATTERN_SCRIPT_TAG = Pattern.compile("<scout\\:script src=\"(.*?)\"(.*)/>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
+  private static final String PATTERN_BASE_TAG = "<scout\\:base\\s*/>";
 
   private final HtmlDocumentParserParameters m_params;
   private String m_workingContent;
@@ -52,6 +53,7 @@
     // the order of calls is important: first we must resolve all includes
     m_workingContent = new String(document, StandardCharsets.UTF_8.name());
     replaceIncludeTags();
+    replaceBaseTags();
     replaceMessageTags();
     replaceStylesheetTags();
     replaceScriptTags();
@@ -129,6 +131,20 @@
     replaceScriptTags(PATTERN_SCRIPT_TAG, "<script src=\"", "\"></script>");
   }
 
+  protected void replaceBaseTags() {
+    // <scout:base />
+    String contextPath = m_params.getContextPath();
+    if (StringUtility.isNullOrEmpty(contextPath)) {
+      contextPath = "/";
+    }
+    else if (contextPath.lastIndexOf('/') != contextPath.length() - 1) {
+      // add / at end of string (unless it already has a slash at the end)
+      contextPath += "/";
+    }
+    String baseTag = "<base href=\"" + contextPath + "\">";
+    m_workingContent = m_workingContent.replaceAll(PATTERN_BASE_TAG, baseTag);
+  }
+
   protected void replaceIncludeTags() throws IOException {
     // <scout:include template="no-script.html" />
     Matcher m = PATTERN_INCLUDE_TAG.matcher(m_workingContent);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParserParameters.java b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParserParameters.java
index aa5d140..96bcd27 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParserParameters.java
+++ b/org.eclipse.scout.rt.ui.html/src/main/java/org/eclipse/scout/rt/ui/html/res/loader/HtmlDocumentParserParameters.java
@@ -56,6 +56,10 @@
     return m_cacheKey.getResourcePath();
   }
 
+  public String getContextPath() {
+    return m_req.getServletContext().getContextPath();
+  }
+
   public HttpCacheObject loadScriptFile(String resourcePath) throws IOException {
     ScriptFileLoader scriptLoader = new ScriptFileLoader(m_req);
     HttpCacheKey cacheKey = scriptLoader.createCacheKey(resourcePath);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
index ff120e0..1835714 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/jquery/jquery-scout.js
@@ -12,1139 +12,1183 @@
  * JQuery plugin with scout extensions
  */
 
-/*global console: false */
-(function($) {
+// === internal methods ===
 
-  // === internal methods ===
-
-  /**
-   * Returns false when the component display is 'none' or visibility is 'hidden', otherwise true.
-   * Note: this gives other results than $.is(':visible'), since that method will also return false
-   * when a component has absolute positioning and no width and height is defined (well, you cannot
-   * see a component with a style like this, but technically it is not set to 'not visible').
-   */
-  function elemVisible(elem) {
-    // Check if element itself is hidden by its own style attribute
-    if (isHidden(elem.style)) {
-      return false;
-    }
-    // Must use correct window for element / computedStyle
-    var myWindow = elem.ownerDocument.defaultView;
-    // Check if element itself is hidden by external style-sheet
-    if (isHidden(myWindow.getComputedStyle(elem))) {
-      return false;
-    }
-    // Else visible
-    return true;
-
-    // ----- Helper functions -----
-
-    function isHidden(style) {
-      return style.display === 'none' || style.visibility === 'hidden';
-    }
-  }
-
-  function explodeShorthandProperties(properties) {
-    var newProperties = [];
-    properties.forEach(function(prop) {
-      // shorthand css properties may not be copied directly (at least not in firefox) -> copy the actual properties
-      if (prop === 'margin' || prop === 'padding') {
-        newProperties.push(prop + '-top');
-        newProperties.push(prop + '-right');
-        newProperties.push(prop + '-bottom');
-        newProperties.push(prop + '-left');
-      } else if (prop === 'border') {
-        newProperties.push('border-top-style');
-        newProperties.push('border-right-style');
-        newProperties.push('border-bottom-style');
-        newProperties.push('border-left-style');
-
-        newProperties.push('border-top-color');
-        newProperties.push('border-right-color');
-        newProperties.push('border-bottom-color');
-        newProperties.push('border-left-color');
-
-        newProperties.push('border-top-width');
-        newProperties.push('border-right-width');
-        newProperties.push('border-bottom-width');
-        newProperties.push('border-left-width');
-      } else {
-        newProperties.push(prop);
-      }
-    });
-    return newProperties;
-  }
-
-  // === $ extensions ===
-
-  // used by some animate functions
-  $.removeThis = function() {
-    $(this).remove();
-  };
-
-  /**
-   * Convenience function that can be used as an jQuery event handler, when this
-   * event should be "swallowed". Technically, this function calls preventDefault(),
-   * stopPropagation() and stopImmediatePropagation() on the event.
-   *
-   * Note: "return false" is equal to preventDefault() and stopPropagation(), but
-   * not stopImmediatePropagation().
-   */
-  $.suppressEvent = function(event) {
-    if (event) {
-      event.preventDefault();
-      event.stopPropagation();
-      event.stopImmediatePropagation();
-    }
-  };
-
-  /**
-   * If the event target is disabled (according to $.fn.isEnabled()), the event is suppressed
-   * and the method returns true. Otherwise, false is returned.
-   */
-  $.suppressEventIfDisabled = function(event, $target) {
-    $target = $target || $(event.target);
-    if (!$target.isEnabled()) {
-      $.suppressEvent(event);
-      return true;
-    }
+/**
+ * Returns false when the component display is 'none' or visibility is 'hidden', otherwise true.
+ * Note: this gives other results than $.is(':visible'), since that method will also return false
+ * when a component has absolute positioning and no width and height is defined (well, you cannot
+ * see a component with a style like this, but technically it is not set to 'not visible').
+ */
+function elemVisible(elem) {
+  // Check if element itself is hidden by its own style attribute
+  if (isHidden(elem.style)) {
     return false;
-  };
+  }
+  // Must use correct window for element / computedStyle
+  var myWindow = elem.ownerDocument.defaultView;
+  // Check if element itself is hidden by external style-sheet
+  if (isHidden(myWindow.getComputedStyle(elem))) {
+    return false;
+  }
+  // Else visible
+  return true;
 
-  /**
-   * Implements the 'debounce' pattern. The given function fx is executed after a certain delay
-   * (in milliseconds), but if the same function is called a second time within the waiting time,
-   * the timer is reset. The default value for 'delay' is 250 ms.
-   */
-  $.debounce = function(fx, delay) {
-    delay = (delay !== undefined) ? delay : 250;
-    var timeoutId = null;
-    return function() {
-      var that = this,
-        args = arguments;
+  // ----- Helper functions -----
+
+  function isHidden(style) {
+    return style.display === 'none' || style.visibility === 'hidden';
+  }
+}
+
+function explodeShorthandProperties(properties) {
+  var newProperties = [];
+  properties.forEach(function(prop) {
+    // shorthand css properties may not be copied directly (at least not in firefox) -> copy the actual properties
+    if (prop === 'margin' || prop === 'padding') {
+      newProperties.push(prop + '-top');
+      newProperties.push(prop + '-right');
+      newProperties.push(prop + '-bottom');
+      newProperties.push(prop + '-left');
+    } else if (prop === 'border') {
+      newProperties.push('border-top-style');
+      newProperties.push('border-right-style');
+      newProperties.push('border-bottom-style');
+      newProperties.push('border-left-style');
+
+      newProperties.push('border-top-color');
+      newProperties.push('border-right-color');
+      newProperties.push('border-bottom-color');
+      newProperties.push('border-left-color');
+
+      newProperties.push('border-top-width');
+      newProperties.push('border-right-width');
+      newProperties.push('border-bottom-width');
+      newProperties.push('border-left-width');
+    } else {
+      newProperties.push(prop);
+    }
+  });
+  return newProperties;
+}
+
+// === $ extensions ===
+
+// used by some animate functions
+$.removeThis = function() {
+  $(this).remove();
+};
+
+/**
+ * Convenience function that can be used as an jQuery event handler, when this
+ * event should be "swallowed". Technically, this function calls preventDefault(),
+ * stopPropagation() and stopImmediatePropagation() on the event.
+ *
+ * Note: "return false" is equal to preventDefault() and stopPropagation(), but
+ * not stopImmediatePropagation().
+ */
+$.suppressEvent = function(event) {
+  if (event) {
+    event.preventDefault();
+    event.stopPropagation();
+    event.stopImmediatePropagation();
+  }
+};
+
+/**
+ * If the event target is disabled (according to $.fn.isEnabled()), the event is suppressed
+ * and the method returns true. Otherwise, false is returned.
+ */
+$.suppressEventIfDisabled = function(event, $target) {
+  $target = $target || $(event.target);
+  if (!$target.isEnabled()) {
+    $.suppressEvent(event);
+    return true;
+  }
+  return false;
+};
+
+/**
+ * Implements the 'debounce' pattern. The given function fx is executed after a certain delay
+ * (in milliseconds), but if the same function is called a second time within the waiting time,
+ * the timer is reset. The default value for 'delay' is 250 ms.
+ */
+$.debounce = function(fx, delay) {
+  delay = (delay !== undefined) ? delay : 250;
+  var timeoutId = null;
+  return function() {
+    var that = this,
+      args = arguments;
+    clearTimeout(timeoutId);
+    timeoutId = setTimeout(function() {
+      fx.apply(that, args);
+    }, delay);
+  };
+};
+
+/**
+ * Executes the given function. Further calls to the same function are delayed by the given delay
+ * (default 250ms). This is similar to $.debounce() but ensures that function is called at least
+ * every 'delay' milliseconds. Can be useful to prevent too many function calls, e.g. from UI events.
+ */
+$.throttle = function(fx, delay) {
+  delay = (delay !== undefined) ? delay : 250;
+  var timeoutId = null;
+  var lastExecution;
+  return function() {
+    var that = this,
+      args = arguments,
+      now = new Date().getTime(),
+      callFx = function() {
+        lastExecution = now;
+        fx.apply(that, args);
+      };
+    if (lastExecution && lastExecution + delay > now) {
       clearTimeout(timeoutId);
       timeoutId = setTimeout(function() {
-        fx.apply(that, args);
-      }, delay);
-    };
-  };
-
-  /**
-   * Executes the given function. Further calls to the same function are delayed by the given delay
-   * (default 250ms). This is similar to $.debounce() but ensures that function is called at least
-   * every 'delay' milliseconds. Can be useful to prevent too many function calls, e.g. from UI events.
-   */
-  $.throttle = function(fx, delay) {
-    delay = (delay !== undefined) ? delay : 250;
-    var timeoutId = null;
-    var lastExecution;
-    return function() {
-      var that = this,
-        args = arguments,
-        now = new Date().getTime(),
-        callFx = function() {
-          lastExecution = now;
-          fx.apply(that, args);
-        };
-      if (lastExecution && lastExecution + delay > now) {
-        clearTimeout(timeoutId);
-        timeoutId = setTimeout(function() {
-          callFx();
-        }, delay);
-      } else {
         callFx();
-      }
-    };
-  };
-
-  /**
-   * Returns a function which negates the return value of the given function when called.
-   */
-  $.negate = function(fx) {
-    return function() {
-      return !fx.apply(this, arguments);
-    };
-  };
-
-  /**
-   * color calculation
-   */
-  $.colorOpacity = function(hex, opacity) {
-    // validate hex string
-    hex = String(hex).replace(/[^0-9a-f]/gi, '');
-    if (hex.length < 6) {
-      hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
-    }
-    opacity = opacity || 0;
-
-    // convert to decimal and change luminosity
-    var rgb = '#';
-    for (var i = 0; i < 3; i++) {
-      var c = parseInt(hex.substr(i * 2, 2), 16);
-      c = Math.round(Math.min(Math.max(0, 255 - (255 - c) * opacity), 255)).toString(16);
-      rgb += ('00' + c).substr(c.length);
-    }
-
-    return rgb;
-  };
-
-  /**
-   * from http://api.jquery.com/jquery.getscript/
-   */
-  $.getCachedScript = function(url, options) {
-    options = $.extend(options || {}, {
-      dataType: 'script',
-      cache: true,
-      url: url
-    });
-    return jQuery.ajax(options);
-  };
-
-  $.pxToNumber = function(pixel) {
-    if (!pixel) {
-      // parseFloat would return NaN if pixel is '' or undefined
-      return 0;
-    }
-    // parseFloat ignores 'px' and just extracts the number
-    return parseFloat(pixel, 10);
-  };
-
-  // === $.prototype extensions ===
-
-  /**
-   * @param element string. Example = &lt;input&gt;
-   * @param cssClass (optional) class attribute
-   * @param text (optional) adds a child text-node with given text (no HTML content)
-   */
-  $.fn.makeElement = function(element, cssClass, text) {
-    var myDocument = this.document(true);
-    if (myDocument === undefined || element === undefined) {
-      return new Error('missing arguments: document, element');
-    }
-    var $element = $(element, myDocument);
-    if (cssClass) {
-      $element.addClass(cssClass);
-    }
-    if (text) {
-      $element.text(text);
-    }
-    return $element;
-  };
-
-  /**
-   * Creates a DIV element in the current document. The function adds an unselectable attribute,
-   * if this is required by the current device (@see Device.js). When you don't want the (un-)
-   * selectable behavior use <code>makeElement('&lt;div&gt;')</code>.
-   *
-   * @param cssClass (optional) string added to the 'class' attribute
-   * @param text (optional) string used as inner text
-   */
-  $.fn.makeDiv = function(cssClass, text) {
-    var unselectable = scout.device.unselectableAttribute,
-      $div = this.makeElement('<div>', cssClass, text);
-
-    if (unselectable.key) {
-      $div.attr(unselectable.key, unselectable.value);
-    }
-    return $div;
-  };
-
-  $.fn.makeSpan = function(cssClass, text) {
-    return this.makeElement('<span>', cssClass, text);
-  };
-
-  /**
-   * @return HTML document reference (ownerDocument) of the HTML element.
-   * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
-   */
-  $.fn.document = function(domElement) {
-    var myDocument = this.length ? this[0].ownerDocument : null;
-    return domElement ? myDocument : $(myDocument);
-  };
-
-  /**
-   * @return HTML window reference (defaultView) of the HTML element
-   * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
-   */
-  $.fn.window = function(domElement) {
-    var myDocument = this.document(true),
-      myWindow = myDocument ? myDocument.defaultView : null;
-    return domElement ? myWindow : $(myWindow);
-  };
-
-  /**
-   * @return HTML document reference (ownerDocument) of the HTML element.
-   * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
-   */
-  $.fn.activeElement = function(domElement) {
-    var myDocument = this.document(true),
-      activeElement = myDocument ? myDocument.activeElement : null;
-    return domElement ? activeElement : $(activeElement);
-  };
-
-  /**
-   * @return the BODY element of the HTML document in which the current HTML element is placed.
-   */
-  $.fn.body = function() {
-    return $('body', this.document(true));
-  };
-
-  /**
-   * @return the closest DOM element that has the 'scout' class.
-   * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
-   */
-  $.fn.entryPoint = function(domElement) {
-    var $element = this.closest('.scout');
-    return domElement ? $element[0] : $element;
-  };
-
-  // prepend - and return new div for chaining
-  $.fn.prependDiv = function(cssClass, text) {
-    return this.makeDiv(cssClass, text).prependTo(this);
-  };
-
-  // append - and return new div for chaining
-  $.fn.appendDiv = function(cssClass, text) {
-    return this.makeDiv(cssClass, text).appendTo(this);
-  };
-
-  $.fn.prependElement = function(element, cssClass, text) {
-    return this.makeElement(element, cssClass, text).prependTo(this);
-  };
-
-  $.fn.appendElement = function(element, cssClass, text) {
-    return this.makeElement(element, cssClass, text).appendTo(this);
-  };
-
-  // insert after - and return new div for chaining
-  $.fn.afterDiv = function(cssClass, text) {
-    return this.makeDiv(cssClass, text).insertAfter(this);
-  };
-
-  // insert before - and return new div for chaining
-  $.fn.beforeDiv = function(cssClass, text) {
-    return this.makeDiv(cssClass, text).insertBefore(this);
-  };
-
-  $.fn.appendSpan = function(cssClass, text) {
-    return this.makeSpan(cssClass, text).appendTo(this);
-  };
-
-  $.fn.appendBr = function(cssClass) {
-    return this.makeElement('<br>', cssClass).appendTo(this);
-  };
-
-  $.fn.appendTextNode = function(text) {
-    return $(this.document(true).createTextNode(text)).appendTo(this);
-  };
-
-  $.fn.makeSVG = function(type, cssClass, text, id) {
-    var myDocument = this.document(true);
-    if (myDocument === undefined || type === undefined) {
-      return new Error('missing arguments: document, type');
-    }
-    var $svg = $(myDocument.createElementNS('http://www.w3.org/2000/svg', type));
-    if (cssClass) {
-      $svg.attrSVG('class', cssClass);
-    }
-    if (text) {
-      $svg.text(text);
-    }
-    if (id !== undefined) {
-      $svg.attrSVG('id', id);
-    }
-    return $svg;
-  };
-
-  // append SVG
-  $.fn.appendSVG = function(type, cssClass, text, id) {
-    return this.makeSVG(type, cssClass, text, id).appendTo(this);
-  };
-
-  // attr and class handling for svg
-  $.fn.attrSVG = function(attributeName, value) {
-    if (this.length === 0) { // shortcut for empty collections
-      return this;
-    }
-    if (this.length === 1) { // shortcut for single element collections
-      this[0].setAttribute(attributeName, value);
-      return this;
-    }
-    return this.each(function() {
-      this.setAttribute(attributeName, value);
-    });
-  };
-
-  $.fn.removeAttrSVG = function(attributeName) {
-    if (this.length === 0) { // shortcut for empty collections
-      return this;
-    }
-    if (this.length === 1) { // shortcut for single element collections
-      this[0].removeAttribute(attributeName);
-      return this;
-    }
-    return this.each(function() {
-      this.removeAttribute(attributeName);
-    });
-  };
-
-  $.fn.attrXLINK = function(attributeName, value) {
-    if (this.length === 0) { // shortcut for empty collections
-      return this;
-    }
-    if (this.length === 1) { // shortcut for single element collections
-      this[0].setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:' + attributeName, value);
-      return this;
-    }
-    return this.each(function() {
-      this.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:' + attributeName, value);
-    });
-  };
-
-  $.fn.addClassSVG = function(cssClass) {
-    var old;
-    if (this.length === 0) { // shortcut for empty collections
-      return this;
-    }
-    if (this.length === 1) { // shortcut for single element collections
-      if (!this.hasClassSVG(cssClass)) {
-        old = this[0].getAttribute('class');
-        this[0].setAttribute('class', scout.strings.join(' ', old, cssClass).trim());
-      }
-      return this;
-    }
-    return this.each(function() {
-      if (!$(this).hasClassSVG(cssClass)) {
-        old = this.getAttribute('class');
-        this.setAttribute('class', scout.strings.join(' ', old, cssClass).trim());
-      }
-    });
-  };
-
-  $.fn.removeClassSVG = function(cssClass) {
-    var old;
-    if (this.length === 0) { // shortcut for empty collections
-      return this;
-    }
-    if (this.length === 1) { // shortcut for single element collections
-      old = ' ' + this[0].getAttribute('class') + ' ';
-      this[0].setAttribute('class', old.replace(' ' + cssClass + ' ', ' ').trim());
-      return this;
-    }
-    return this.each(function() {
-      var old = ' ' + this.getAttribute('class') + ' ';
-      this.setAttribute('class', old.replace(' ' + cssClass + ' ', ' ').trim());
-    });
-  };
-
-  $.fn.hasClassSVG = function(cssClass) {
-    var old = ' ' + this[0].getAttribute('class') + ' ';
-    return old.indexOf(' ' + cssClass + ' ') !== -1;
-  };
-
-  // select one and deselect siblings
-  $.fn.selectOne = function() {
-    this.siblings().removeClass('selected');
-    this.addClass('selected');
-    return this;
-  };
-
-  $.fn.select = function(selected) {
-    return this.toggleClass('selected', !!selected);
-  };
-
-  $.fn.isSelected = function() {
-    return this.hasClass('selected');
-  };
-
-  $.fn.setEnabled = function(enabled) {
-    enabled = !!enabled;
-    this.toggleClass('disabled', !enabled);
-    // Toggle disabled attribute for elements that support it (see http://www.w3.org/TR/html5/disabled-elements.html)
-    if (this.is('button, input, select, textarea, optgroup, option, fieldset')) {
-      this.toggleAttr('disabled', !enabled);
-    }
-    return this;
-  };
-
-  $.fn.isEnabled = function() {
-    return !this.hasClass('disabled');
-  };
-
-  $.fn.setVisible = function(visible) {
-    var i, elem;
-    for (i = 0; i < this.length; i++) {
-      elem = this[i];
-      if (elemVisible(elem) != visible) {
-        if (visible) {
-          this.show();
-        } else {
-          this.hide();
-        }
-      }
-    }
-    return this;
-  };
-
-  $.fn.isDisplayNone = function() {
-    return this.css('display') === 'none';
-  };
-
-  $.fn.setTabbable = function(tabbable) {
-    return this.attr('tabIndex', tabbable ? 0 : null);
-  };
-
-  $.fn.icon = function(iconId) {
-    var icon, $icon = this.data('$icon');
-    if (iconId) {
-      icon = scout.icons.parseIconId(iconId);
-      if (icon.isFontIcon()) {
-        getOrCreateIconElement.call(this, $icon, '<span>')
-          .addClass(icon.appendCssClass('font-icon'))
-          .addClass('icon')
-          .text(icon.iconCharacter);
-      } else {
-        getOrCreateIconElement.call(this, $icon, '<img>')
-          .attr('src', icon.iconUrl)
-          .addClass('icon');
-      }
+      }, delay);
     } else {
+      callFx();
+    }
+  };
+};
+
+/**
+ * Returns a function which negates the return value of the given function when called.
+ */
+$.negate = function(fx) {
+  return function() {
+    return !fx.apply(this, arguments);
+  };
+};
+
+/**
+ * color calculation
+ */
+$.colorOpacity = function(hex, opacity) {
+  // validate hex string
+  hex = String(hex).replace(/[^0-9a-f]/gi, '');
+  if (hex.length < 6) {
+    hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
+  }
+  opacity = opacity || 0;
+
+  // convert to decimal and change luminosity
+  var rgb = '#';
+  for (var i = 0; i < 3; i++) {
+    var c = parseInt(hex.substr(i * 2, 2), 16);
+    c = Math.round(Math.min(Math.max(0, 255 - (255 - c) * opacity), 255)).toString(16);
+    rgb += ('00' + c).substr(c.length);
+  }
+
+  return rgb;
+};
+
+/**
+ * from http://api.jquery.com/jquery.getscript/
+ */
+$.getCachedScript = function(url, options) {
+  options = $.extend(options || {}, {
+    dataType: 'script',
+    cache: true,
+    url: url
+  });
+  return $.ajax(options);
+};
+
+$.pxToNumber = function(pixel) {
+  if (!pixel) {
+    // parseFloat would return NaN if pixel is '' or undefined
+    return 0;
+  }
+  // parseFloat ignores 'px' and just extracts the number
+  return parseFloat(pixel, 10);
+};
+
+// === $.prototype extensions ===
+
+/**
+ * @param element string. Example = &lt;input&gt;
+ * @param cssClass (optional) class attribute
+ * @param text (optional) adds a child text-node with given text (no HTML content)
+ */
+$.fn.makeElement = function(element, cssClass, text) {
+  var myDocument = this.document(true);
+  if (myDocument === undefined || element === undefined) {
+    return new Error('missing arguments: document, element');
+  }
+  var $element = $(element, myDocument);
+  if (cssClass) {
+    $element.addClass(cssClass);
+  }
+  if (text) {
+    $element.text(text);
+  }
+  return $element;
+};
+
+/**
+ * Creates a DIV element in the current document. The function adds an unselectable attribute,
+ * if this is required by the current device (@see Device.js). When you don't want the (un-)
+ * selectable behavior use <code>makeElement('&lt;div&gt;')</code>.
+ *
+ * @param cssClass (optional) string added to the 'class' attribute
+ * @param text (optional) string used as inner text
+ */
+$.fn.makeDiv = function(cssClass, text) {
+  var unselectable = scout.device.unselectableAttribute,
+    $div = this.makeElement('<div>', cssClass, text);
+
+  if (unselectable.key) {
+    $div.attr(unselectable.key, unselectable.value);
+  }
+  return $div;
+};
+
+$.fn.makeSpan = function(cssClass, text) {
+  return this.makeElement('<span>', cssClass, text);
+};
+
+/**
+ * @return HTML document reference (ownerDocument) of the HTML element.
+ * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
+ */
+$.fn.document = function(domElement) {
+  var myDocument = this.length ? this[0].ownerDocument : null;
+  return domElement ? myDocument : $(myDocument);
+};
+
+/**
+ * @return HTML window reference (defaultView) of the HTML element
+ * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
+ */
+$.fn.window = function(domElement) {
+  var myDocument = this.document(true),
+    myWindow = myDocument ? myDocument.defaultView : null;
+  return domElement ? myWindow : $(myWindow);
+};
+
+/**
+ * @return HTML document reference (ownerDocument) of the HTML element.
+ * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
+ */
+$.fn.activeElement = function(domElement) {
+  var myDocument = this.document(true),
+    activeElement = myDocument ? myDocument.activeElement : null;
+  return domElement ? activeElement : $(activeElement);
+};
+
+/**
+ * @return the BODY element of the HTML document in which the current HTML element is placed.
+ */
+$.fn.body = function() {
+  return $('body', this.document(true));
+};
+
+/**
+ * @return the closest DOM element that has the 'scout' class.
+ * @param domElement (optional) if true this function returns a JQuery object, otherwise only the DOM element is returned
+ */
+$.fn.entryPoint = function(domElement) {
+  var $element = this.closest('.scout');
+  return domElement ? $element[0] : $element;
+};
+
+// prepend - and return new div for chaining
+$.fn.prependDiv = function(cssClass, text) {
+  return this.makeDiv(cssClass, text).prependTo(this);
+};
+
+// append - and return new div for chaining
+$.fn.appendDiv = function(cssClass, text) {
+  return this.makeDiv(cssClass, text).appendTo(this);
+};
+
+$.fn.prependElement = function(element, cssClass, text) {
+  return this.makeElement(element, cssClass, text).prependTo(this);
+};
+
+$.fn.appendElement = function(element, cssClass, text) {
+  return this.makeElement(element, cssClass, text).appendTo(this);
+};
+
+// insert after - and return new div for chaining
+$.fn.afterDiv = function(cssClass, text) {
+  return this.makeDiv(cssClass, text).insertAfter(this);
+};
+
+// insert before - and return new div for chaining
+$.fn.beforeDiv = function(cssClass, text) {
+  return this.makeDiv(cssClass, text).insertBefore(this);
+};
+
+$.fn.appendSpan = function(cssClass, text) {
+  return this.makeSpan(cssClass, text).appendTo(this);
+};
+
+$.fn.appendBr = function(cssClass) {
+  return this.makeElement('<br>', cssClass).appendTo(this);
+};
+
+$.fn.appendTextNode = function(text) {
+  return $(this.document(true).createTextNode(text)).appendTo(this);
+};
+
+$.fn.makeSVG = function(type, cssClass, text, id) {
+  var myDocument = this.document(true);
+  if (myDocument === undefined || type === undefined) {
+    return new Error('missing arguments: document, type');
+  }
+  var $svg = $(myDocument.createElementNS('http://www.w3.org/2000/svg', type));
+  if (cssClass) {
+    $svg.attrSVG('class', cssClass);
+  }
+  if (text) {
+    $svg.text(text);
+  }
+  if (id !== undefined) {
+    $svg.attrSVG('id', id);
+  }
+  return $svg;
+};
+
+// append SVG
+$.fn.appendSVG = function(type, cssClass, text, id) {
+  return this.makeSVG(type, cssClass, text, id).appendTo(this);
+};
+
+// attr and class handling for svg
+$.fn.attrSVG = function(attributeName, value) {
+  if (this.length === 0) { // shortcut for empty collections
+    return this;
+  }
+  if (this.length === 1) { // shortcut for single element collections
+    this[0].setAttribute(attributeName, value);
+    return this;
+  }
+  return this.each(function() {
+    this.setAttribute(attributeName, value);
+  });
+};
+
+$.fn.removeAttrSVG = function(attributeName) {
+  if (this.length === 0) { // shortcut for empty collections
+    return this;
+  }
+  if (this.length === 1) { // shortcut for single element collections
+    this[0].removeAttribute(attributeName);
+    return this;
+  }
+  return this.each(function() {
+    this.removeAttribute(attributeName);
+  });
+};
+
+$.fn.attrXLINK = function(attributeName, value) {
+  if (this.length === 0) { // shortcut for empty collections
+    return this;
+  }
+  if (this.length === 1) { // shortcut for single element collections
+    this[0].setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:' + attributeName, value);
+    return this;
+  }
+  return this.each(function() {
+    this.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:' + attributeName, value);
+  });
+};
+
+$.fn.addClassSVG = function(cssClass) {
+  var old;
+  if (this.length === 0) { // shortcut for empty collections
+    return this;
+  }
+  if (this.length === 1) { // shortcut for single element collections
+    if (!this.hasClassSVG(cssClass)) {
+      old = this[0].getAttribute('class');
+      this[0].setAttribute('class', scout.strings.join(' ', old, cssClass).trim());
+    }
+    return this;
+  }
+  return this.each(function() {
+    if (!$(this).hasClassSVG(cssClass)) {
+      old = this.getAttribute('class');
+      this.setAttribute('class', scout.strings.join(' ', old, cssClass).trim());
+    }
+  });
+};
+
+$.fn.removeClassSVG = function(cssClass) {
+  var old;
+  if (this.length === 0) { // shortcut for empty collections
+    return this;
+  }
+  if (this.length === 1) { // shortcut for single element collections
+    old = ' ' + this[0].getAttribute('class') + ' ';
+    this[0].setAttribute('class', old.replace(' ' + cssClass + ' ', ' ').trim());
+    return this;
+  }
+  return this.each(function() {
+    var old = ' ' + this.getAttribute('class') + ' ';
+    this.setAttribute('class', old.replace(' ' + cssClass + ' ', ' ').trim());
+  });
+};
+
+$.fn.hasClassSVG = function(cssClass) {
+  var old = ' ' + this[0].getAttribute('class') + ' ';
+  return old.indexOf(' ' + cssClass + ' ') !== -1;
+};
+
+// select one and deselect siblings
+$.fn.selectOne = function() {
+  this.siblings().removeClass('selected');
+  this.addClass('selected');
+  return this;
+};
+
+$.fn.select = function(selected) {
+  return this.toggleClass('selected', !!selected);
+};
+
+$.fn.isSelected = function() {
+  return this.hasClass('selected');
+};
+
+$.fn.setEnabled = function(enabled) {
+  enabled = !!enabled;
+  this.toggleClass('disabled', !enabled);
+  // Toggle disabled attribute for elements that support it (see http://www.w3.org/TR/html5/disabled-elements.html)
+  if (this.is('button, input, select, textarea, optgroup, option, fieldset')) {
+    this.toggleAttr('disabled', !enabled);
+  }
+  return this;
+};
+
+$.fn.isEnabled = function() {
+  return !this.hasClass('disabled');
+};
+
+$.fn.setVisible = function(visible) {
+  var i, elem;
+  for (i = 0; i < this.length; i++) {
+    elem = this[i];
+    if (elemVisible(elem) != visible) {
+      if (visible) {
+        this.show();
+      } else {
+        this.hide();
+      }
+    }
+  }
+  return this;
+};
+
+$.fn.isDisplayNone = function() {
+  return this.css('display') === 'none';
+};
+
+$.fn.setTabbable = function(tabbable) {
+  return this.attr('tabIndex', tabbable ? 0 : null);
+};
+
+$.fn.icon = function(iconId) {
+  var icon, $icon = this.data('$icon');
+  if (iconId) {
+    icon = scout.icons.parseIconId(iconId);
+    if (icon.isFontIcon()) {
+      getOrCreateIconElement.call(this, $icon, '<span>')
+        .addClass(icon.appendCssClass('font-icon'))
+        .addClass('icon')
+        .text(icon.iconCharacter);
+    } else {
+      getOrCreateIconElement.call(this, $icon, '<img>')
+        .attr('src', icon.iconUrl)
+        .addClass('icon');
+    }
+  } else {
+    removeIconElement.call(this, $icon);
+  }
+  return this;
+
+  // ----- Helper functions -----
+
+  function getOrCreateIconElement($icon, newElement) {
+    // If element type does not match existing element, remove the existing element (e.g. when changing from font-icon to picture icon)
+    if ($icon && !$icon.is(newElement.replace(/[<>]/g, ''))) {
       removeIconElement.call(this, $icon);
+      $icon = null;
     }
-    return this;
-
-    // ----- Helper functions -----
-
-    function getOrCreateIconElement($icon, newElement) {
-      // If element type does not match existing element, remove the existing element (e.g. when changing from font-icon to picture icon)
-      if ($icon && !$icon.is(newElement.replace(/[<>]/g, ''))) {
-        removeIconElement.call(this, $icon);
-        $icon = null;
-      }
-      // Create new element if necessary
-      if (!$icon) {
-        $icon = $(newElement);
-        this.data('$icon', $icon);
-        this.prepend($icon);
-      }
-      return $icon;
+    // Create new element if necessary
+    if (!$icon) {
+      $icon = $(newElement);
+      this.data('$icon', $icon);
+      this.prepend($icon);
     }
+    return $icon;
+  }
 
-    function removeIconElement($icon) {
-      if ($icon) {
-        $icon.remove();
-      }
-      this.removeData('$icon');
+  function removeIconElement($icon) {
+    if ($icon) {
+      $icon.remove();
     }
-  };
+    this.removeData('$icon');
+  }
+};
 
-  $.fn.placeholder = function(placeholder) {
-    return this.toggleAttr('placeholder', !!placeholder, placeholder);
-  };
+$.fn.placeholder = function(placeholder) {
+  return this.toggleAttr('placeholder', !!placeholder, placeholder);
+};
 
-  $.fn.isVisible = function() {
-    return elemVisible(this[0]);
-  };
+$.fn.isVisible = function() {
+  return elemVisible(this[0]);
+};
 
-  $.fn.isEveryParentVisible = function() {
-    var everyParentVisible = true;
-    this.parents().each(function() {
-      if (!$(this).isVisible()) {
-        everyParentVisible = false;
-        return false;
-      }
-    });
-    return everyParentVisible;
-  };
-
-  /**
-   * @return true if the element is attached (= is in the dom tree), false if not
-   */
-  $.fn.isAttached = function() {
-    return $.contains(this.document(true).documentElement, this[0]);
-  };
-
-  /**
-   * Returns the first parent which is scrollable
-   */
-  $.fn.scrollParent = function() {
-    var $elem = this;
-    while ($elem.length > 0) {
-      if ($elem.data('scrollable')) {
-        return $elem;
-      }
-      $elem = $elem.parent();
+$.fn.isEveryParentVisible = function() {
+  var everyParentVisible = true;
+  this.parents().each(function() {
+    if (!$(this).isVisible()) {
+      everyParentVisible = false;
+      return false;
     }
-    return $();
-  };
+  });
+  return everyParentVisible;
+};
 
-  /**
-   * Returns every parent which is scrollable
-   */
-  $.fn.scrollParents = function() {
-    var $scrollParents = $(),
-      $elem = this;
+/**
+ * @return true if the element is attached (= is in the dom tree), false if not
+ */
+$.fn.isAttached = function() {
+  return $.contains(this.document(true).documentElement, this[0]);
+};
 
-    while ($elem.length > 0) {
-      if ($elem.data('scrollable')) {
-        $scrollParents.push($elem);
-      }
-      $elem = $elem.parent();
+/**
+ * Returns the first parent which is scrollable
+ */
+$.fn.scrollParent = function() {
+  var $elem = this;
+  while ($elem.length > 0) {
+    if ($elem.data('scrollable')) {
+      return $elem;
     }
-    return $scrollParents;
-  };
+    $elem = $elem.parent();
+  }
+  return $();
+};
 
-  // most used animate
-  $.fn.animateAVCSD = function(attr, value, complete, step, duration) {
-    var properties = {};
-    var options = {};
+/**
+ * Returns every parent which is scrollable
+ */
+$.fn.scrollParents = function() {
+  var $scrollParents = $(),
+    $elem = this;
 
-    properties[attr] = value;
-    if (complete) {
-      options.complete = complete;
+  while ($elem.length > 0) {
+    if ($elem.data('scrollable')) {
+      $scrollParents.push($elem);
     }
-    if (step) {
-      options.step = step;
-    }
-    if (duration) {
-      options.duration = duration;
-    }
-    options.queue = false;
+    $elem = $elem.parent();
+  }
+  return $scrollParents;
+};
 
-    this.animate(properties, options);
-    return this;
-  };
+// most used animate
+$.fn.animateAVCSD = function(attr, value, complete, step, duration) {
+  var properties = {};
+  var options = {};
 
-  // SVG animate, array contains attr, endValue + startValue
-  $.fn.animateSVG = function(attr, endValue, duration, complete, withoutTabIndex) {
-    return this.each(function() {
-      var startValue = parseFloat($(this).attr(attr));
-      if (withoutTabIndex) {
-        var oldComplete = complete;
-        complete = function() {
-          if (oldComplete) {
-            oldComplete.call(this);
-          }
-          $(this).removeAttr('tabindex');
-        };
-      }
-      $(this).animate({
-        tabIndex: 0
-      }, {
-        step: function(now, fx) {
-          this.setAttribute(attr, startValue + (endValue - startValue) * fx.pos);
-        },
-        duration: duration,
-        complete: complete,
-        queue: false
-      });
-    });
-  };
+  properties[attr] = value;
+  if (complete) {
+    options.complete = complete;
+  }
+  if (step) {
+    options.step = step;
+  }
+  if (duration) {
+    options.duration = duration;
+  }
+  options.queue = false;
 
-  $.fn.addClassForAnimation = function(className, options) {
-    var defaultOptions = {
-      delay: 1000,
-      classesToRemove: className
-    };
-    options = $.extend({}, defaultOptions, options);
-    this.addClass(className);
-    setTimeout(function() {
-      // remove class, otherwise animation will be executed each time the element changes it's visibility (attach/rerender),
-      // and even each time when the css classes change
-      this.removeClass(options.classesToRemove);
-      // delay must be greater than css animation duration
-    }.bind(this), options.delay);
-  };
+  this.animate(properties, options);
+  return this;
+};
 
-  /**
-   * Animates from old to new width
-   */
-  $.fn.cssWidthAnimated = function(oldWidth, newWidth, opts) {
-    opts = opts || {};
-    opts.duration = scout.nvl(opts.duration, 300);
-
-    // Reset to old width first
-    this.cssWidth(oldWidth);
-
-    // Then animate to new width
-    this.animate({
-      width: newWidth
-    }, opts);
-
-    return this;
-  };
-
-  $.fn.cssHeightAnimated = function(oldHeight, newHeight, opts) {
-    opts = opts || {};
-    opts.duration = scout.nvl(opts.duration, 300);
-
-    // Reset to old height first
-    this.cssHeight(oldHeight);
-
-    // Then animate to new height
-    this.animate({
-      height: newHeight
-    }, opts);
-
-    return this;
-  };
-
-  $.fn.cssLeftAnimated = function(from, to, opts) {
-    opts = opts || {};
-    opts.duration = scout.nvl(opts.duration, 300);
-
-    // Reset to from first
-    this.cssLeft(from);
-
-    // Then animate to new width
-    this.animate({
-      left: to
-    }, opts);
-
-    return this;
-  };
-
-  $.fn.cssTopAnimated = function(from, to, opts) {
-    opts = opts || {};
-    opts.duration = scout.nvl(opts.duration, 300);
-
-    // Reset to from first
-    this.cssTop(from);
-
-    // Then animate to new pos
-    this.animate({
-      top: to
-    }, opts);
-
-    return this;
-  };
-
-  $.fn.cssAnimated = function(fromVals, toVals, opts) {
-    opts = opts || {};
-    opts.duration = scout.nvl(opts.duration, 300);
-
-    // Reset to from first
-    this.css(fromVals);
-
-    // Then animate to new pos
-    this.animate(toVals, opts);
-    return this;
-  };
-
-  // over engineered animate
-  $.fn.widthToContent = function(opts) {
-    var oldW = this.outerWidth(),
-      newW = this.css('width', 'auto').outerWidth();
-
-    this.cssWidthAnimated(oldW, newW, opts);
-    return this;
-  };
-
-  $.fn.cssLeft = function(position) {
-    return this.cssPxValue('left', position);
-  };
-
-  $.fn.cssTop = function(position) {
-    return this.cssPxValue('top', position);
-  };
-
-  $.fn.cssBottom = function(position) {
-    return this.cssPxValue('bottom', position);
-  };
-
-  $.fn.cssRight = function(position) {
-    return this.cssPxValue('right', position);
-  };
-
-  $.fn.cssWidth = function(width) {
-    return this.cssPxValue('width', width);
-  };
-
-  $.fn.cssHeight = function(height) {
-    return this.cssPxValue('height', height);
-  };
-
-  $.fn.cssLineHeight = function(height) {
-    return this.cssPxValue('line-height', height);
-  };
-
-  $.fn.cssPxValue = function(prop, value) {
-    if (value === undefined) {
-      return $.pxToNumber(this.css(prop));
-    }
-    return this.css(prop, value + 'px');
-  };
-
-  $.fn.cssMarginLeft = function(value) {
-    return this.cssPxValue('margin-left', value);
-  };
-
-  $.fn.cssMarginBottom = function(value) {
-    return this.cssPxValue('margin-bottom', value);
-  };
-
-  $.fn.cssMarginRight = function(value) {
-    return this.cssPxValue('margin-right', value);
-  };
-
-  $.fn.cssMarginTop = function(value) {
-    return this.cssPxValue('margin-top', value);
-  };
-
-  $.fn.cssMarginX = function(value) {
-    if (value === undefined) {
-      return this.cssMarginLeft() + this.cssMarginRight();
-    }
-    this.cssMarginLeft(value);
-    this.cssMarginRight(value);
-  };
-
-  $.fn.cssMarginY = function(value) {
-    if (value === undefined) {
-      return this.cssMarginTop() + this.cssMarginBottom();
-    }
-    this.cssMarginTop(value);
-    this.cssMarginBottom(value);
-  };
-
-  $.fn.cssBorderBottomWidth = function(value) {
-    return this.cssPxValue('border-bottom-width', value);
-  };
-
-  $.fn.cssBorderLeftWidth = function(value) {
-    return this.cssPxValue('border-left-width', value);
-  };
-
-  $.fn.cssBorderRightWidth = function(value) {
-    return this.cssPxValue('border-right-width', value);
-  };
-
-  $.fn.cssBorderTopWidth = function(value) {
-    return this.cssPxValue('border-top-width', value);
-  };
-
-  $.fn.cssBorderWidthY = function(value) {
-    if (value === undefined) {
-      return this.cssBorderTopWidth() + this.cssBorderBottomWidth();
-    }
-    this.cssBorderTopWidth(value);
-    this.cssBorderBottomWidth(value);
-  };
-
-  $.fn.cssBorderWidthX = function(value) {
-    if (value === undefined) {
-      return this.cssBorderLeftWidth() + this.cssBorderRightWidth();
-    }
-    this.cssBorderLeftWidth(value);
-    this.cssBorderRightWidth(value);
-  };
-
-  /**
-   * Bottom of a html element without margin and border relative to offset parent. Expects border-box model.
-   */
-  $.fn.innerBottom = function() {
-    return this.position().top + this.outerHeight(true) - this.cssMarginBottom() - this.cssBorderBottomWidth();
-  };
-
-  /**
-   * Right of a html element without margin and border relative to offset parent. Expects border-box model.
-   */
-  $.fn.innerRight = function() {
-    return this.position().left + this.outerWidth(true) - this.cssMarginRight() - this.cssBorderRightWidth();
-  };
-
-  $.fn.copyCss = function($origin, props) {
-    var properties = props.split(' ');
-    var $this = this;
-    properties = explodeShorthandProperties(properties);
-    properties.forEach(function(prop) {
-      $this.css(prop, $origin.css(prop));
-    });
-    return $this;
-  };
-
-  $.fn.copyCssIfGreater = function($origin, props) {
-    var properties = props.split(' ');
-    var $this = this;
-    properties = explodeShorthandProperties(properties);
-    properties.forEach(function(prop) {
-      var originValue = $.pxToNumber($origin.css(prop));
-      var thisValue = $.pxToNumber($this.css(prop));
-      if (originValue > thisValue) {
-        $this.css(prop, originValue + 'px');
-      }
-    });
-    return $this;
-  };
-
-  $.fn.copyCssClasses = function($other, classString) {
-    var classes = classString.split(' ');
-    var $this = this;
-    classes.forEach(function(cssClass) {
-      if ($other.hasClass(cssClass)) {
-        $this.addClass(cssClass);
-      }
-    });
-    return $this;
-  };
-
-  $.fn.disableSpellcheck = function() {
-    return this.attr('spellcheck', false);
-  };
-
-  /**
-   * Returns whether the current element is the given element or has a child which is the given element.
-   */
-  $.fn.isOrHas = function(elem) {
-    return this[0] === elem || this.has(elem).length > 0;
-  };
-
-  /**
-   * Makes any element movable with the mouse. If the argument '$handle' is missing, the entire
-   * element can be used as a handle.
-   *
-   * A callback function can be passed as second argument (optional). The function is called for
-   * every change of the draggable's position with an object as argument:
-   * { top: (top pixels), left: (left pixels) }
-   */
-  $.fn.makeDraggable = function($handle, callback) {
-    var $draggable = this;
-    $handle = $handle || $draggable;
-    return $handle.on('mousedown.draggable', function(event) {
-      var orig_offset = $draggable.offset();
-      var orig_event = event;
-      var handleWidth = $handle.width();
-      var windowWidth = $handle.window().width();
-      var windowHeight = $handle.window().height();
-      $handle.parents()
-        .on('mousemove.dragging', function(event) {
-          var top = orig_offset.top + (event.pageY - orig_event.pageY);
-          var left = orig_offset.left + (event.pageX - orig_event.pageX);
-          // do not drop outside of viewport (and leave a margin of 100 pixels)
-          left = Math.max(100 - handleWidth, left);
-          left = Math.min(windowWidth - 100, left);
-          top = Math.max(0, top); // must not be dragged outside of top, otherwise dragging back is impossible
-          top = Math.min(windowHeight - 100, top);
-          var newOffset = {
-            top: top,
-            left: left
-          };
-          $draggable.offset(newOffset);
-          callback && callback(newOffset);
-        })
-        .on('mouseup.dragging', function(e) {
-          $handle.parents().off('.dragging');
-        });
-      event.preventDefault();
-    });
-  };
-
-  /**
-   * Calls jQuery.fadeOut() and then removes the element from the DOM.
-   * Default fade-out duration is 150 ms.
-   */
-  $.fn.fadeOutAndRemove = function(duration, callback) {
-    if (callback === undefined && typeof duration === 'function') {
-      callback = duration;
-      duration = undefined;
-    }
-    duration = scout.nvl(duration, 150);
-    this.stop(true).fadeOut(duration, function() {
-      $(this).remove();
-      if (callback) {
-        callback.call(this);
-      }
-    });
-  };
-
-  var _oldhide = $.fn.hide;
-  $.fn.hide = function() {
-    this.trigger('hide');
-    var returnValue = _oldhide.apply(this, arguments);
-    return returnValue;
-  };
-
-  /**
-   * Compared to the regular hide it does not remember the current display state, it just sets display to none.
-   * This is a lot faster (1.8sec faster when applying hide to 500 nodes).
-   * It has the drawback that show cannot revert the display style, so you have to know the style.<p>
-   * See also showFast.
-   */
-  $.fn.hideFast = function() {
-    //TODO [5.2] cgu: change to use css class (this.addClass('hidden');). Replace jquery hide and show -> should be a lot faster because it is not necessary to remember any state.
-    this[0].style.display = 'none';
-    return this;
-  };
-
-  /**
-   * Just sets display to block. See hideFast for details.
-   */
-  $.fn.showFast = function() {
-    this[0].style.display = 'block';
-    return this;
-  };
-
-  /**
-   * Sets the given 'text' as text to the jQuery element, using the text() function (i.e. HTML is encoded automatically).
-   * If the text does not contain any non-space characters, the text '&nbsp;' is set instead (using the html() function).
-   * If an 'emptyCssClass' is provided, this CSS class is removed in the former and added in the later case.
-   */
-  $.fn.textOrNbsp = function(text, emptyCssClass) {
-    if (scout.strings.hasText(text)) {
-      this.text(text);
-      if (emptyCssClass) {
-        this.removeClass(emptyCssClass);
-      }
-    } else {
-      this.html('&nbsp;');
-      if (emptyCssClass) {
-        this.addClass(emptyCssClass);
-      }
-    }
-    return this;
-  };
-
-  /**
-   * Same as "textOrNbsp", but with html (caller is responsible for encoding).
-   */
-  $.fn.htmlOrNbsp = function(html, emptyCssClass) {
-    if (scout.strings.hasText(html)) {
-      this.html(html);
-      if (emptyCssClass) {
-        this.removeClass(emptyCssClass);
-      }
-    } else {
-      this.html('&nbsp;');
-      if (emptyCssClass) {
-        this.addClass(emptyCssClass);
-      }
-    }
-    return this;
-  };
-
-  /**
-   * Like toggleClass(), this toggles a HTML attribute on a set of jquery elements.
-   *
-   * @param attr
-   *          Name of the attribute to toggle.
-   * @param state
-   *          Specifies if the attribute should be added or removed (based on whether the argument is truthy or falsy).
-   *          If this argument is not defined, the attribute is added when it exists, and vice-versa. If this behavior
-   *          is not desired, explicitly cast the argument to a boolean using "!!".
-   * @param value
-   *          Value to use when adding the attribute.
-   *          If this argument is not specified, 'attr' is used as value.
-   */
-  $.fn.toggleAttr = function(attr, state, value) {
-    if (!attr) {
-      return this;
-    }
-    if (value === undefined) {
-      value = attr;
-    }
-    return this.each(function() {
-      var $element = $(this);
-      if (state === undefined) {
-        // set state according to the current value
-        state = ($element.attr(attr) === undefined);
-      }
-      if (state) {
-        // set attr
-        $element.attr(attr, value);
-      } else {
-        // remove attr
-        $element.removeAttr(attr);
-      }
-    });
-  };
-
-  $.fn.backupSelection = function() {
-    var field = this[0];
-    if (field && field === this.activeElement(true)) {
-      return {
-        selectionStart: field.selectionStart,
-        selectionEnd: field.selectionEnd,
-        selectionDirection: field.selectionDirection
+// SVG animate, array contains attr, endValue + startValue
+$.fn.animateSVG = function(attr, endValue, duration, complete, withoutTabIndex) {
+  return this.each(function() {
+    var startValue = parseFloat($(this).attr(attr));
+    if (withoutTabIndex) {
+      var oldComplete = complete;
+      complete = function() {
+        if (oldComplete) {
+          oldComplete.call(this);
+        }
+        $(this).removeAttr('tabindex');
       };
     }
-    return null;
-  };
+    $(this).animate({
+      tabIndex: 0
+    }, {
+      step: function(now, fx) {
+        this.setAttribute(attr, startValue + (endValue - startValue) * fx.pos);
+      },
+      duration: duration,
+      complete: complete,
+      queue: false
+    });
+  });
+};
 
-  $.fn.restoreSelection = function(selection) {
-    var field = this[0];
-    if (field && field === this.activeElement(true) && selection) {
-      field.setSelectionRange(selection.selectionStart, selection.selectionEnd, selection.selectionDirection);
+$.fn.addClassForAnimation = function(className, options) {
+  var defaultOptions = {
+    classesToRemove: className
+  };
+  options = $.extend({}, defaultOptions, options);
+  this.addClass(className);
+  this.oneAnimationEnd(function() {
+    // remove class, otherwise animation will be executed each time the element changes it's visibility (attach/rerender),
+    // and even each time when the css classes change
+    this.removeClass(options.classesToRemove);
+    // delay must be greater than css animation duration
+  }.bind(this));
+};
+
+$.fn.oneAnimationEnd = function(selector, data, handler) {
+  this.one('animationend webkitAnimationEnd', selector, data, handler);
+};
+
+/**
+ * Animates from old to new width
+ */
+$.fn.cssWidthAnimated = function(oldWidth, newWidth, opts) {
+  opts = opts || {};
+  opts.duration = scout.nvl(opts.duration, 300);
+
+  // Reset to old width first
+  this.cssWidth(oldWidth);
+
+  // Then animate to new width
+  this.animate({
+    width: newWidth
+  }, opts);
+
+  return this;
+};
+
+$.fn.cssHeightAnimated = function(oldHeight, newHeight, opts) {
+  opts = opts || {};
+  opts.duration = scout.nvl(opts.duration, 300);
+
+  // Reset to old height first
+  this.cssHeight(oldHeight);
+
+  // Then animate to new height
+  this.animate({
+    height: newHeight
+  }, opts);
+
+  return this;
+};
+
+$.fn.cssLeftAnimated = function(from, to, opts) {
+  opts = opts || {};
+  opts.duration = scout.nvl(opts.duration, 300);
+
+  // Reset to from first
+  this.cssLeft(from);
+
+  // Then animate to new width
+  this.animate({
+    left: to
+  }, opts);
+
+  return this;
+};
+
+$.fn.cssTopAnimated = function(from, to, opts) {
+  opts = opts || {};
+  opts.duration = scout.nvl(opts.duration, 300);
+
+  // Reset to from first
+  this.cssTop(from);
+
+  // Then animate to new pos
+  this.animate({
+    top: to
+  }, opts);
+
+  return this;
+};
+
+$.fn.cssAnimated = function(fromVals, toVals, opts) {
+  opts = opts || {};
+  opts.duration = scout.nvl(opts.duration, 300);
+
+  // Reset to from first
+  this.css(fromVals);
+
+  // Then animate to new pos
+  this.animate(toVals, opts);
+  return this;
+};
+
+// over engineered animate
+$.fn.widthToContent = function(opts) {
+  var oldW = this.outerWidth(),
+    newW = this.css('width', 'auto').outerWidth();
+
+  this.cssWidthAnimated(oldW, newW, opts);
+  return this;
+};
+
+/**
+ * Offset to a specific ancestor and not to the document as offset() would do.
+ * Not the same as position() which returns the position relative to the offset parent.
+ */
+$.fn.offsetTo = function($to) {
+  var toOffset = $to.offset(),
+    offset = this.offset();
+
+  return {
+    top: offset.top - toOffset.top,
+    left: offset.left - toOffset.left
+  };
+};
+
+$.fn.cssLeft = function(position) {
+  return this.cssPxValue('left', position);
+};
+
+$.fn.cssTop = function(position) {
+  return this.cssPxValue('top', position);
+};
+
+$.fn.cssBottom = function(position) {
+  return this.cssPxValue('bottom', position);
+};
+
+$.fn.cssRight = function(position) {
+  return this.cssPxValue('right', position);
+};
+
+$.fn.cssWidth = function(width) {
+  return this.cssPxValue('width', width);
+};
+
+$.fn.cssHeight = function(height) {
+  return this.cssPxValue('height', height);
+};
+
+$.fn.cssLineHeight = function(height) {
+  return this.cssPxValue('line-height', height);
+};
+
+$.fn.cssPxValue = function(prop, value) {
+  if (value === undefined) {
+    return $.pxToNumber(this.css(prop));
+  }
+  return this.css(prop, value + 'px');
+};
+
+$.fn.cssMarginLeft = function(value) {
+  return this.cssPxValue('margin-left', value);
+};
+
+$.fn.cssMarginBottom = function(value) {
+  return this.cssPxValue('margin-bottom', value);
+};
+
+$.fn.cssMarginRight = function(value) {
+  return this.cssPxValue('margin-right', value);
+};
+
+$.fn.cssMarginTop = function(value) {
+  return this.cssPxValue('margin-top', value);
+};
+
+$.fn.cssMarginX = function(value) {
+  if (value === undefined) {
+    return this.cssMarginLeft() + this.cssMarginRight();
+  }
+  this.cssMarginLeft(value);
+  this.cssMarginRight(value);
+};
+
+$.fn.cssMarginY = function(value) {
+  if (value === undefined) {
+    return this.cssMarginTop() + this.cssMarginBottom();
+  }
+  this.cssMarginTop(value);
+  this.cssMarginBottom(value);
+};
+
+$.fn.cssPaddingTop = function(value) {
+  return this.cssPxValue('padding-top', value);
+};
+
+$.fn.cssBorderBottomWidth = function(value) {
+  return this.cssPxValue('border-bottom-width', value);
+};
+
+$.fn.cssBorderLeftWidth = function(value) {
+  return this.cssPxValue('border-left-width', value);
+};
+
+$.fn.cssBorderRightWidth = function(value) {
+  return this.cssPxValue('border-right-width', value);
+};
+
+$.fn.cssBorderTopWidth = function(value) {
+  return this.cssPxValue('border-top-width', value);
+};
+
+$.fn.cssBorderWidthY = function(value) {
+  if (value === undefined) {
+    return this.cssBorderTopWidth() + this.cssBorderBottomWidth();
+  }
+  this.cssBorderTopWidth(value);
+  this.cssBorderBottomWidth(value);
+};
+
+$.fn.cssBorderWidthX = function(value) {
+  if (value === undefined) {
+    return this.cssBorderLeftWidth() + this.cssBorderRightWidth();
+  }
+  this.cssBorderLeftWidth(value);
+  this.cssBorderRightWidth(value);
+};
+
+/**
+ * Bottom of a html element without margin and border relative to offset parent. Expects border-box model.
+ */
+$.fn.innerBottom = function() {
+  return this.position().top + this.outerHeight(true) - this.cssMarginBottom() - this.cssBorderBottomWidth();
+};
+
+/**
+ * Right of a html element without margin and border relative to offset parent. Expects border-box model.
+ */
+$.fn.innerRight = function() {
+  return this.position().left + this.outerWidth(true) - this.cssMarginRight() - this.cssBorderRightWidth();
+};
+
+$.fn.copyCss = function($origin, props) {
+  var properties = props.split(' ');
+  var $this = this;
+  properties = explodeShorthandProperties(properties);
+  properties.forEach(function(prop) {
+    $this.css(prop, $origin.css(prop));
+  });
+  return $this;
+};
+
+$.fn.copyCssIfGreater = function($origin, props) {
+  var properties = props.split(' ');
+  var $this = this;
+  properties = explodeShorthandProperties(properties);
+  properties.forEach(function(prop) {
+    var originValue = $.pxToNumber($origin.css(prop));
+    var thisValue = $.pxToNumber($this.css(prop));
+    if (originValue > thisValue) {
+      $this.css(prop, originValue + 'px');
     }
-  };
+  });
+  return $this;
+};
 
-  /**
-   * If the given value is "truthy", it is set as attribute on the target. Otherwise, the attribute is removed.
-   */
-  $.fn.attrOrRemove = function(attributeName, value) {
-    if (value) {
-      $(this).attr(attributeName, value);
+$.fn.copyCssClasses = function($other, classString) {
+  var classes = classString.split(' ');
+  var $this = this;
+  classes.forEach(function(cssClass) {
+    if ($other.hasClass(cssClass)) {
+      $this.addClass(cssClass);
+    }
+  });
+  return $this;
+};
+
+$.fn.disableSpellcheck = function() {
+  return this.attr('spellcheck', false);
+};
+
+/**
+ * Returns whether the current element is the given element or has a child which is the given element.
+ */
+$.fn.isOrHas = function(elem) {
+  return this[0] === elem || this.has(elem).length > 0;
+};
+
+/**
+ * Makes any element movable with the mouse. If the argument '$handle' is missing, the entire
+ * element can be used as a handle.
+ *
+ * A callback function can be passed as second argument (optional). The function is called for
+ * every change of the draggable's position with an object as argument:
+ * { top: (top pixels), left: (left pixels) }
+ */
+$.fn.makeDraggable = function($handle, callback) {
+  var $draggable = this;
+  $handle = $handle || $draggable;
+  return $handle.on('mousedown.draggable', function(event) {
+    var orig_offset = $draggable.offset();
+    var orig_event = event;
+    var handleWidth = $handle.width();
+    var windowWidth = $handle.window().width();
+    var windowHeight = $handle.window().height();
+    $handle.parents()
+      .on('mousemove.dragging', function(event) {
+        var top = orig_offset.top + (event.pageY - orig_event.pageY);
+        var left = orig_offset.left + (event.pageX - orig_event.pageX);
+        // do not drop outside of viewport (and leave a margin of 100 pixels)
+        left = Math.max(100 - handleWidth, left);
+        left = Math.min(windowWidth - 100, left);
+        top = Math.max(0, top); // must not be dragged outside of top, otherwise dragging back is impossible
+        top = Math.min(windowHeight - 100, top);
+        var newOffset = {
+          top: top,
+          left: left
+        };
+        $draggable.offset(newOffset);
+        callback && callback(newOffset);
+      })
+      .on('mouseup.dragging', function(e) {
+        $handle.parents().off('.dragging');
+      });
+    event.preventDefault();
+  });
+};
+
+/**
+ * Calls jQuery.fadeOut() and then removes the element from the DOM.
+ * Default fade-out duration is 150 ms.
+ */
+$.fn.fadeOutAndRemove = function(duration, callback) {
+  if (callback === undefined && typeof duration === 'function') {
+    callback = duration;
+    duration = undefined;
+  }
+  duration = scout.nvl(duration, 150);
+  this.stop(true).fadeOut(duration, function() {
+    $(this).remove();
+    if (callback) {
+      callback.call(this);
+    }
+  });
+};
+
+var _oldhide = $.fn.hide;
+$.fn.hide = function() {
+  this.trigger('hide');
+  var returnValue = _oldhide.apply(this, arguments);
+  return returnValue;
+};
+
+/**
+ * Compared to the regular hide it does not remember the current display state, it just sets display to none.
+ * This is a lot faster (1.8sec faster when applying hide to 500 nodes).
+ * It has the drawback that show cannot revert the display style, so you have to know the style.<p>
+ * See also showFast.
+ */
+$.fn.hideFast = function() {
+  //TODO [5.2] cgu: change to use css class (this.addClass('hidden');). Replace jquery hide and show -> should be a lot faster because it is not necessary to remember any state.
+  this[0].style.display = 'none';
+  return this;
+};
+
+/**
+ * Just sets display to block. See hideFast for details.
+ */
+$.fn.showFast = function() {
+  this[0].style.display = 'block';
+  return this;
+};
+
+/**
+ * Sets the given 'text' as text to the jQuery element, using the text() function (i.e. HTML is encoded automatically).
+ * If the text does not contain any non-space characters, the text '&nbsp;' is set instead (using the html() function).
+ * If an 'emptyCssClass' is provided, this CSS class is removed in the former and added in the later case.
+ */
+$.fn.textOrNbsp = function(text, emptyCssClass) {
+  if (scout.strings.hasText(text)) {
+    this.text(text);
+    if (emptyCssClass) {
+      this.removeClass(emptyCssClass);
+    }
+  } else {
+    this.html('&nbsp;');
+    if (emptyCssClass) {
+      this.addClass(emptyCssClass);
+    }
+  }
+  return this;
+};
+
+/**
+ * Same as "textOrNbsp", but with html (caller is responsible for encoding).
+ */
+$.fn.htmlOrNbsp = function(html, emptyCssClass) {
+  if (scout.strings.hasText(html)) {
+    this.html(html);
+    if (emptyCssClass) {
+      this.removeClass(emptyCssClass);
+    }
+  } else {
+    this.html('&nbsp;');
+    if (emptyCssClass) {
+      this.addClass(emptyCssClass);
+    }
+  }
+  return this;
+};
+
+/**
+ * Like toggleClass(), this toggles a HTML attribute on a set of jquery elements.
+ *
+ * @param attr
+ *          Name of the attribute to toggle.
+ * @param state
+ *          Specifies if the attribute should be added or removed (based on whether the argument is truthy or falsy).
+ *          If this argument is not defined, the attribute is added when it exists, and vice-versa. If this behavior
+ *          is not desired, explicitly cast the argument to a boolean using "!!".
+ * @param value
+ *          Value to use when adding the attribute.
+ *          If this argument is not specified, 'attr' is used as value.
+ */
+$.fn.toggleAttr = function(attr, state, value) {
+  if (!attr) {
+    return this;
+  }
+  if (value === undefined) {
+    value = attr;
+  }
+  return this.each(function() {
+    var $element = $(this);
+    if (state === undefined) {
+      // set state according to the current value
+      state = ($element.attr(attr) === undefined);
+    }
+    if (state) {
+      // set attr
+      $element.attr(attr, value);
     } else {
-      $(this).removeAttr(attributeName);
+      // remove attr
+      $element.removeAttr(attr);
     }
-  };
+  });
+};
 
-  $.fn.appendAppLink = function(appLinkBean, func) {
-    return this.appendSpan().appLink(appLinkBean, func);
-  };
+$.fn.backupSelection = function() {
+  var field = this[0];
+  if (field && field === this.activeElement(true)) {
+    return {
+      selectionStart: field.selectionStart,
+      selectionEnd: field.selectionEnd,
+      selectionDirection: field.selectionDirection
+    };
+  }
+  return null;
+};
 
-  /**
-   * @param func Either a function to be called when the app link has been clicked.
-   * Or an object with a method named _onAppLinkAction (e.g. an instance of BeanField).
-   */
-  $.fn.appLink = function(appLinkBean, func) {
-    if (typeof func === 'object' && func._onAppLinkAction) {
-      func = func._onAppLinkAction.bind(func);
-    }
-    return this.addClass('app-link')
-      .text(appLinkBean.name)
-      .attr('tabindex', '0')
-      .attr('data-ref', appLinkBean.ref)
-      .unfocusable()
-      .on('click', func);
-  };
+$.fn.restoreSelection = function(selection) {
+  var field = this[0];
+  if (field && field === this.activeElement(true) && selection) {
+    field.setSelectionRange(selection.selectionStart, selection.selectionEnd, selection.selectionDirection);
+  }
+};
 
-  /**
-   * Adds the class 'unfocusable' to current result set. The class is not used for styling purposes
-   * but has a meaning to the FocusManager.
-   */
-  $.fn.unfocusable = function() {
-    return this.addClass('unfocusable');
-  };
+/**
+ * If the given value is "truthy", it is set as attribute on the target. Otherwise, the attribute is removed.
+ */
+$.fn.attrOrRemove = function(attributeName, value) {
+  if (value) {
+    $(this).attr(attributeName, value);
+  } else {
+    $(this).removeAttr(attributeName);
+  }
+};
 
-  /**
-   * Select all text within an element, e.g. within a content editable div element.
-   */
-  $.fn.selectAllText = function() {
-    var range,
-      myDocument = this.document(true),
-      myWindow = this.window(true),
-      element = this[0];
+$.fn.appendAppLink = function(appLinkBean, func) {
+  return this.appendSpan().appLink(appLinkBean, func);
+};
 
-    if (myDocument.body.createTextRange) {
-      range = myDocument.body.createTextRange();
-      range.moveToElementText(element);
-      range.select();
-      return;
-    }
+/**
+ * @param func Either a function to be called when the app link has been clicked.
+ * Or an object with a method named _onAppLinkAction (e.g. an instance of BeanField).
+ */
+$.fn.appLink = function(appLinkBean, func) {
+  if (typeof func === 'object' && func._onAppLinkAction) {
+    func = func._onAppLinkAction.bind(func);
+  }
+  return this.addClass('app-link')
+    .text(appLinkBean.name)
+    .attr('tabindex', '0')
+    .attr('data-ref', appLinkBean.ref)
+    .unfocusable()
+    .on('click', func);
+};
 
-    if (myWindow.getSelection) {
-      range = myDocument.createRange();
-      range.selectNodeContents(element);
-      myWindow.getSelection().removeAllRanges();
-      myWindow.getSelection().addRange(range);
-    }
-  };
+/**
+ * Adds the class 'unfocusable' to current result set. The class is not used for styling purposes
+ * but has a meaning to the FocusManager.
+ */
+$.fn.unfocusable = function() {
+  return this.addClass('unfocusable');
+};
 
-  /**
-   * Checks if content is truncated.
-   */
-  $.fn.isContentTruncated = function() {
-    return this[0].scrollWidth > this[0].clientWidth;
-  };
+/**
+ * Select all text within an element, e.g. within a content editable div element.
+ */
+$.fn.selectAllText = function() {
+  var range,
+    myDocument = this.document(true),
+    myWindow = this.window(true),
+    element = this[0];
 
-}(jQuery));
+  if (myDocument.body.createTextRange) {
+    range = myDocument.body.createTextRange();
+    range.moveToElementText(element);
+    range.select();
+    return;
+  }
+
+  if (myWindow.getSelection) {
+    range = myDocument.createRange();
+    range.selectNodeContents(element);
+    myWindow.getSelection().removeAllRanges();
+    myWindow.getSelection().addRange(range);
+  }
+};
+
+/**
+ * Checks if content is truncated.
+ */
+$.fn.isContentTruncated = function() {
+  return this[0].scrollWidth > this[0].clientWidth;
+};
+
+// FIXME awe: (graph) consider moving this function to DoubleClickHandler.js
+/**
+ * This function is used to distinct between single and double clicks.
+ * Instead of executing a handler immediately when the first click occurs,
+ * we wait for a given timeout (or by default 300 ms) to check if it is followed by a second click.
+ * This will delay the execution of a single click a bit, so you should use this function wisely.
+ */
+$.fn.onSingleOrDoubleClick = function(singleClickFunc, doubleClickFunc, timeout) {
+  return this.each(function() {
+    var that = this,
+      numClicks = 0,
+      timeout = timeout || 300;
+    $(this).on('click', function(event) {
+      numClicks++;
+      if (numClicks == 1) {
+        setTimeout(function() {
+          if (numClicks == 1) {
+            singleClickFunc.call(that, event);
+          } else {
+            doubleClickFunc.call(that, event);
+          }
+          numClicks = 0;
+        }, timeout);
+      }
+    });
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.css
index 1d89043..1ba4a75 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.css
@@ -1,14 +1,13 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
+/*!
+* Eclipse Scout Login
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
 //@include("scout/main.css")
+//@include("scout/box/Box.css")
 //@include("scout/style/animations.css")
 //@include("scout/style/colors.css")
 //@include("scout/style/fonts.css")
@@ -16,4 +15,4 @@
 //@include("scout/style/mixins.css")
 //@include("scout/style/sizes.css")
 //@include("scout/form/fields/button/Button.css")
-//@include("scout/login/login.css")
+//@include("scout/login/LoginBox.css")
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.js
index c3bf355..562872d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout-login-module.js
@@ -1,21 +1,22 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-__include("jquery/jquery-scout.js");
+/*!
+* Eclipse Scout Login
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
 // protects $ and undefined from being redefined by another library
 (function(scout, $, undefined) {
-__include("scout/main.js");
-__include("scout/text/Texts.js");
-__include("scout/util/strings.js");
-__include("scout/util/Device.js");
-__include("scout/util/strings.js");
-__include("scout/login/login.js");
-__include("scout/login/logout.js");
+  __include("jquery/jquery-scout.js");
+  __include("scout/main.js");
+  __include("scout/box/Box.js");
+  __include("scout/text/Texts.js");
+  __include("scout/util/strings.js");
+  __include("scout/util/Device.js");
+  __include("scout/util/strings.js");
+  __include("scout/login/login.js");
+  __include("scout/login/LoginBox.js");
+  __include("scout/login/logout.js");
+  __include("scout/login/LogoutBox.js");
 }(window.scout = window.scout || {}, jQuery));
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.css
deleted file mode 100644
index 2425c92..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.css
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-//@include("scout/main.css")
-//@include("scout/calendar/Calendar.css")
-//@include("scout/calendar/YearPanel.css")
-//@include("scout/datepicker/DatePicker.css")
-//@include("scout/desktop/Desktop.css")
-//@include("scout/desktop/DesktopNavigation.css")
-//@include("scout/desktop/NavigateButton.css")
-//@include("scout/desktop/outline/Outline.css")
-//@include("scout/desktop/outline/OutlineOverview.css")
-//@include("scout/desktop/outline/SearchOutline.css")
-//@include("scout/desktop/PopupBlockerDesktopNotification.css")
-//@include("scout/desktop/ViewButton.css")
-//@include("scout/filechooser/FileChooser.css")
-//@include("scout/form/Form.css")
-//@include("scout/form/FormToolPopup.css")
-//@include("scout/form/ScoutInfoForm.css")
-//@include("scout/form/fields/FormField.css")
-//@include("scout/form/fields/button/Button.css")
-//@include("scout/form/fields/beanfield/BeanField.css");
-//@include("scout/form/fields/browserfield/BrowserField.css");
-//@include("scout/form/fields/calendarfield/CalendarField.css")
-//@include("scout/form/fields/checkbox/CheckBoxField.css")
-//@include("scout/form/fields/clipboardfield/ClipboardField.css")
-//@include("scout/form/fields/datefield/DateField.css")
-//@include("scout/form/fields/filechooserfield/FileChooserField.css")
-//@include("scout/form/fields/groupbox/GroupBox.css")
-//@include("scout/form/fields/htmlfield/HtmlField.css")
-//@include("scout/form/fields/imagefield/ImageField.css")
-//@include("scout/form/fields/labelfield/LabelField.css")
-//@include("scout/form/fields/listbox/ListBox.css")
-//@include("scout/form/fields/numberfield/NumberField.css")
-//@include("scout/form/fields/placeholder/PlaceholderField.css")
-//@include("scout/form/fields/plannerfield/PlannerField.css")
-//@include("scout/form/fields/radiobutton/RadioButton.css")
-//@include("scout/form/fields/radiobutton/RadioButtonGroup.css")
-//@include("scout/form/fields/sequencebox/SequenceBox.css")
-//@include("scout/form/fields/smartfield/SmartField.css")
-//@include("scout/form/fields/splitbox/SplitBox.css")
-//@include("scout/form/fields/stringfield/StringField.css")
-//@include("scout/form/fields/tabbox/TabBox.css")
-//@include("scout/form/fields/tablefield/TableField.css")
-//@include("scout/form/fields/treebox/TreeBox.css")
-//@include("scout/form/fields/treefield/TreeField.css")
-//@include("scout/form/fields/wizard/WizardProgressField.css")
-//@include("scout/form/fields/wrappedform/WrappedFormField.css")
-//@include("scout/menu/Menu.css")
-//@include("scout/menu/MenuBar.css")
-//@include("scout/messagebox/MessageBox.css")
-//@include("scout/planner/Planner.css")
-//@include("scout/planner/PlannerHeader.css")
-//@include("scout/popup/Popup.css");
-//@include("scout/popup/TouchPopup.css");
-//@include("scout/scrollbar/Scrollbar.css")
-//@include("scout/session/BusyIndicator.css")
-//@include("scout/splitter/Splitter.css")
-//@include("scout/style/animations.css")
-//@include("scout/style/colors.css")
-//@include("scout/style/fonts.css")
-//@include("scout/style/icons.css")
-//@include("scout/style/mixins.css")
-//@include("scout/style/sizes.css")
-//@include("scout/table/Table.css")
-//@include("scout/table/TableFooter.css")
-//@include("scout/table/TableHeader.css")
-//@include("scout/table/TableHeaderMenu.css")
-//@include("scout/table/controls/TableControl.css")
-//@include("scout/table/editor/CellEditorPopup.css")
-//@include("scout/tooltip/Tooltip.css")
-//@include("scout/tree/Tree.css")
-//@include("scout/tree/CompactTree.css")
-//@include("scout/util/BoxButtons.css")
-//@include("scout/util/keybox.css")
-//@include("scout/util/ui-mouse.css")
-//@include("scout/util/ui-resizable.css")
-
-//@include("scout/desktop/MobileDesktopNavigation.css")
-//@include("scout/desktop/outline/MobileOutline.css")
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.js
deleted file mode 100644
index 6ec154b..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-mobile-module.js
+++ /dev/null
@@ -1,325 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-__include("jquery/jquery-scout.js");
-// protects $ and undefined from being redefined by another library
-(function(scout, $, undefined) {
-  __include("scout/main.js");
-  __include("scout/objectFactories.js");
-  __include("scout/widget/Widget.js");
-  __include("scout/widget/NullWidget.js");
-  // Basic utilities
-  __include("scout/util/arrays.js");
-  __include("scout/util/BoxButtons.js");
-  __include("scout/util/dates.js");
-  __include("scout/util/defaultValues.js");
-  __include("scout/util/DeferredGlassPaneTarget.js");
-  __include("scout/util/DetachHelper.js");
-  __include("scout/util/Device.js");
-  __include("scout/util/DoubleClickSupport.js");
-  __include("scout/util/dragAndDrop.js");
-  __include("scout/util/EventSupport.js");
-  __include("scout/util/fonts.js");
-  __include("scout/util/icons.js");
-  __include("scout/util/FocusManager.js");
-  __include("scout/util/FocusContext.js");
-  __include("scout/util/focusUtils.js");
-  __include("scout/util/focusRule.js");
-  __include("scout/util/inspector.js");
-  __include("scout/util/logging.js");
-  __include("scout/util/mimeTypes.js");
-  __include("scout/util/ModelAdapter.js");
-  __include("scout/util/numbers.js");
-  __include("scout/util/ObjectFactory.js");
-  __include("scout/util/objects.js");
-  __include("scout/util/polyfills.js");
-  __include("scout/util/Range.js");
-  __include("scout/util/Status.js");
-  __include("scout/util/strings.js");
-  __include("scout/util/styles.js");
-  __include("scout/util/URL.js");
-  __include("scout/util/GlassPaneRenderer.js");
-  __include("scout/util/filters.js");
-  __include("scout/util/hAlign.js");
-  __include("scout/util/aggregation.js");
-  // Session related
-  __include("scout/session/BackgroundJobPollingSupport.js");
-  __include("scout/session/BusyIndicator.js");
-  __include("scout/session/Event.js");
-  __include("scout/session/Locale.js");
-  __include("scout/session/Reconnector.js");
-  __include("scout/session/ResponseQueue.js");
-  __include("scout/session/Session.js");
-  __include("scout/session/UserAgent.js");
-  // Basic layout
-  __include("scout/layout/graphics.js");
-  __include("scout/layout/AbstractLayout.js");
-  __include("scout/layout/HtmlComponent.js");
-  __include("scout/layout/LayoutConstants.js");
-  __include("scout/layout/LayoutValidator.js");
-  __include("scout/layout/LogicalGridData.js");
-  __include("scout/layout/LogicalGridLayout.js");
-  __include("scout/layout/LogicalGridLayoutInfo.js");
-  __include("scout/layout/NullLayout.js");
-  __include("scout/layout/SingleLayout.js");
-  // Keystroke handling
-  __include("scout/keystroke/keys.js");
-  __include("scout/keystroke/Key.js");
-  __include("scout/keystroke/keyStrokeModifier.js");
-  __include("scout/keystroke/VirtualKeyStrokeEvent.js");
-  __include("scout/keystroke/KeyStrokeManager.js");
-  __include("scout/keystroke/KeyStrokeContext.js");
-  __include("scout/keystroke/KeyStrokeSupport.js");
-  __include("scout/keystroke/InputFieldKeyStrokeContext.js");
-  __include("scout/keystroke/KeyStroke.js");
-  __include("scout/keystroke/RangeKeyStroke.js");
-  __include("scout/keystroke/ContextMenuKeyStroke.js");
-  __include("scout/keystroke/MnemonicKeyStroke.js");
-  __include("scout/keystroke/ClickActiveElementKeyStroke.js");
-  __include("scout/keystroke/FocusAdjacentElementKeyStroke.js");
-  __include("scout/keystroke/CloseKeyStroke.js");
-  // Misc. elements
-  __include("scout/scrollbar/Scrollbar.js");
-  __include("scout/scrollbar/scrollbars.js");
-  __include("scout/splitter/Splitter.js");
-  __include("scout/text/DateFormat.js");
-  __include("scout/text/DecimalFormat.js");
-  __include("scout/text/Texts.js");
-  __include("scout/tooltip/Tooltip.js");
-  __include("scout/util/tooltips.js");
-  __include("scout/action/Action.js");
-  __include("scout/action/ActionKeyStroke.js");
-  __include("scout/popup/Popup.js");
-  __include("scout/popup/PopupLayout.js");
-  __include("scout/popup/PopupWithHead.js");
-  __include("scout/popup/PopupWithHeadLayout.js");
-  __include("scout/popup/TouchPopup.js");
-  __include("scout/popup/TouchPopupLayout.js");
-  __include("scout/datepicker/DatePicker.js");
-  __include("scout/datepicker/DatePickerLayout.js");
-  __include("scout/datepicker/DatePickerPopup.js");
-  __include("scout/datepicker/DatePickerTouchPopup.js");
-  __include("scout/menu/menus.js");
-  __include("scout/menu/Menu.js");
-  __include("scout/menu/MenuKeyStroke.js");
-  __include("scout/menu/MenuBar.js");
-  __include("scout/menu/MenuBarLeftKeyStroke.js");
-  __include("scout/menu/MenuBarRightKeyStroke.js");
-  __include("scout/menu/MenuBarLayout.js");
-  __include("scout/menu/MenuExecKeyStroke.js");
-  __include("scout/menu/MenuItemsOrder.js");
-  __include("scout/menu/ContextMenuPopup.js");
-  __include("scout/menu/menuNavigationKeyStrokes.js");
-  __include("scout/menu/MenuBarPopup.js");
-  __include("scout/menu/ButtonAdapterMenu.js");
-  __include("scout/calendar/Calendar.js");
-  __include("scout/calendar/CalendarComponent.js");
-  __include("scout/calendar/CalendarListComponent.js");
-  __include("scout/calendar/CalendarLayout.js");
-  __include("scout/calendar/DateRange.js");
-  __include("scout/calendar/YearPanel.js");
-  __include("scout/planner/Planner.js");
-  __include("scout/planner/PlannerHeader.js");
-  __include("scout/planner/PlannerLayout.js");
-  __include("scout/planner/PlannerMenuItemsOrder.js");
-  __include("scout/filechooser/FileChooser.js");
-  __include("scout/filechooser/FileChooserController.js");
-  // Table
-  __include("scout/table/Table.js");
-  __include("scout/table/TableMatrix.js");
-  __include("scout/table/TableFooter.js");
-  __include("scout/table/TableFooterLayout.js");
-  __include("scout/table/TableInfoFilterTooltip.js");
-  __include("scout/table/TableInfoLoadTooltip.js");
-  __include("scout/table/TableInfoSelectionTooltip.js");
-  __include("scout/table/TableHeader.js");
-  __include("scout/table/TableHeaderMenu.js");
-  __include("scout/table/TableHeaderMenuLayout.js");
-  __include("scout/table/TableHeaderMenuGroup.js");
-  __include("scout/table/TableHeaderMenuButton.js");
-  __include("scout/table/TableHeaderMenuButtonKeyStroke.js");
-  __include("scout/table/TableLayout.js");
-  __include("scout/table/TableSelectionHandler.js");
-  __include("scout/table/TableTooltip.js");
-  __include("scout/table/columns/comparators.js");
-  __include("scout/table/columns/Column.js");
-  __include("scout/table/columns/BeanColumn.js"); // requires Column.js
-  __include("scout/table/columns/BooleanColumn.js"); // requires Column.js
-  __include("scout/table/columns/DateColumn.js"); // requires Column.js
-  __include("scout/table/columns/IconColumn.js"); //requires Column.js
-  __include("scout/table/columns/NumberColumn.js"); //requires Column.js
-  __include("scout/table/controls/TableControl.js");
-  __include("scout/table/controls/AggregateTableControl.js"); // requires TableControl.js
-  __include("scout/table/editor/CellEditorPopup.js");
-  __include("scout/table/editor/CellEditorPopupLayout.js");
-  __include("scout/table/editor/CellEditorCancelEditKeyStroke.js");
-  __include("scout/table/editor/CellEditorCompleteEditKeyStroke.js");
-  __include("scout/table/editor/CellEditorTabKeyStroke.js");
-  __include("scout/table/keystrokes/AbstractTableNavigationKeyStroke.js");
-  __include("scout/table/keystrokes/TableControlCloseKeyStroke.js");
-  __include("scout/table/keystrokes/TableCopyKeyStroke.js");
-  __include("scout/table/keystrokes/TableSelectAllKeyStroke.js");
-  __include("scout/table/keystrokes/TableStartCellEditKeyStroke.js");
-  __include("scout/table/keystrokes/TableRefreshKeyStroke.js");
-  __include("scout/table/keystrokes/TableToggleRowKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationUpKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationDownKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationHomeKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationEndKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationPageUpKeyStroke.js");
-  __include("scout/table/keystrokes/TableNavigationPageDownKeyStroke.js");
-  __include("scout/table/keystrokes/TableFocusFilterFieldKeyStroke.js");
-  __include("scout/table/userfilter/TableUserFilter.js");
-  __include("scout/table/userfilter/ColumnUserFilter.js");
-  __include("scout/table/userfilter/DateColumnUserFilter.js");
-  __include("scout/table/userfilter/NumberColumnUserFilter.js");
-  __include("scout/table/userfilter/TextColumnUserFilter.js");
-  __include("scout/table/userfilter/TableTextUserFilter.js");
-  // Tree
-  __include("scout/tree/Tree.js");
-  __include("scout/tree/TreeLayout.js");
-  __include("scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeSpaceKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeNavigationUpKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeNavigationDownKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeCollapseAllKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js");
-  __include("scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js");
-  // Compact Tree
-  __include("scout/tree/CompactTree.js");
-  __include("scout/tree/keystrokes/AbstractCompactTreeControlKeyStroke.js");
-  __include("scout/tree/keystrokes/CompactTreeUpKeyStroke.js");
-  __include("scout/tree/keystrokes/CompactTreeDownKeyStroke.js");
-  __include("scout/tree/keystrokes/CompactTreeLeftKeyStroke.js");
-  __include("scout/tree/keystrokes/CompactTreeRightKeyStroke.js");
-  // Desktop
-  __include("scout/desktop/BaseDesktop.js");
-  __include("scout/desktop/Desktop.js");
-  __include("scout/desktop/DesktopKeyStroke.js");
-  __include("scout/desktop/DesktopTaskBarLayout.js");
-  __include("scout/desktop/DesktopViewTab.js");
-  __include("scout/desktop/ViewMenuOpenKeyStroke.js");
-  __include("scout/desktop/ViewMenuPopup.js");
-  __include("scout/desktop/ViewMenuTab.js");
-  __include("scout/desktop/ViewTabSelectKeyStroke.js");
-  __include("scout/desktop/DisableBrowserTabSwitchingKeyStroke.js");
-  __include("scout/desktop/DesktopNavigation.js");
-  __include("scout/desktop/DesktopNotification.js");
-  __include("scout/desktop/DetailTableTreeFilter.js");
-  __include("scout/desktop/NullDesktopNavigation.js");
-  __include("scout/desktop/OfflineDesktopNotification.js");
-  __include("scout/desktop/PopupBlockerHandler.js");
-  __include("scout/desktop/PopupBlockerDesktopNotification.js");
-  __include("scout/desktop/PopupWindow.js");
-  __include("scout/desktop/ViewButton.js");
-  __include("scout/desktop/ViewButtonsLayout.js");
-  __include("scout/desktop/ViewTabsController.js");
-  __include("scout/desktop/outline/Outline.js");
-  __include("scout/desktop/outline/OutlineOverview.js");
-  __include("scout/desktop/outline/OutlineKeyStrokeContext.js");
-  __include("scout/desktop/outline/OutlineLayout.js");
-  __include("scout/desktop/outline/AbstractOutlineNavigationKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigationUpKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigateToTopKeyStroke.js");
-  __include("scout/desktop/outline/OutlineCollapseOrDrillUpKeyStroke.js");
-  __include("scout/desktop/outline/OutlineExpandOrDrillDownKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigationDownKeyStroke.js");
-  __include("scout/desktop/outline/OutlineViewButton.js");
-  __include("scout/desktop/outline/SearchOutline.js");
-  __include("scout/desktop/outline/SearchOutlineLayout.js");
-  // Basics for form fields
-  __include("scout/form/Form.js");
-  __include("scout/form/FormLayout.js");
-  __include("scout/form/FormToolButton.js");
-  __include("scout/form/FormToolPopup.js");
-  __include("scout/form/FormToolPopupLayout.js");
-  __include("scout/form/DialogLayout.js");
-  __include("scout/form/fields/fields.js");
-  __include("scout/form/fields/AppLinkKeyStroke.js");
-  __include("scout/form/fields/DefaultFieldLoadingSupport.js");
-  __include("scout/form/fields/FormField.js");
-  __include("scout/form/fields/FormFieldLayout.js");
-  __include("scout/form/fields/CompositeField.js");
-  __include("scout/form/fields/ValueField.js");
-  __include("scout/form/fields/BasicField.js");
-  __include("scout/form/FormController.js");
-  // Basics for message boxes
-  __include("scout/messagebox/MessageBox.js");
-  __include("scout/messagebox/MessageBoxController.js");
-  // Form fields (A-Z)
-  __include("scout/form/fields/beanfield/BeanField.js");
-  __include("scout/form/fields/browserfield/BrowserField.js");
-  __include("scout/form/fields/button/Button.js");
-  __include("scout/form/fields/button/ButtonLayout.js");
-  __include("scout/form/fields/button/ButtonMnemonicKeyStroke.js");
-  __include("scout/form/fields/button/ButtonKeyStroke.js");
-  __include("scout/form/fields/calendarfield/CalendarField.js");
-  __include("scout/form/fields/checkbox/CheckBoxField.js");
-  __include("scout/form/fields/checkbox/CheckBoxToggleKeyStroke.js");
-  __include("scout/form/fields/clipboardfield/ClipboardField.js");
-  __include("scout/form/fields/colorfield/ColorField.js");
-  __include("scout/form/fields/datefield/DateField.js");
-  __include("scout/form/fields/datefield/DateTimeCompositeLayout.js");
-  __include("scout/form/fields/filechooserfield/FileChooserField.js");
-  __include("scout/form/fields/groupbox/GroupBox.js");
-  __include("scout/form/fields/groupbox/GroupBoxLayout.js");
-  __include("scout/form/fields/groupbox/GroupBoxMenuItemsOrder.js");
-  __include("scout/form/fields/htmlfield/HtmlField.js");
-  __include("scout/form/fields/imagefield/ImageField.js");
-  __include("scout/form/fields/imagefield/ImageFieldLayout.js");
-  __include("scout/form/fields/labelfield/LabelField.js");
-  __include("scout/form/fields/listbox/ListBox.js");
-  __include("scout/form/fields/listbox/ListBoxLayout.js");
-  __include("scout/form/fields/numberfield/NumberField.js");
-  __include("scout/form/fields/placeholder/PlaceholderField.js");
-  __include("scout/form/fields/plannerfield/PlannerField.js");
-  __include("scout/form/fields/radiobutton/RadioButton.js");
-  __include("scout/form/fields/radiobutton/RadioButtonGroup.js");
-  __include("scout/form/fields/radiobutton/RadioButtonGroupLeftKeyStroke.js");
-  __include("scout/form/fields/radiobutton/RadioButtonGroupRightKeyStroke.js");
-  __include("scout/form/fields/radiobutton/RadioButtonKeyStroke.js");
-  __include("scout/form/fields/sequencebox/SequenceBox.js");
-  __include("scout/form/fields/smartfield/SmartField.js");
-  __include("scout/form/fields/smartfield/SmartFieldTouchPopup.js");
-  __include("scout/form/fields/smartfield/SmartFieldLayout.js");
-  __include("scout/form/fields/smartfield/SmartFieldPopup.js");
-  __include("scout/form/fields/smartfield/SmartFieldPopupLayout.js");
-  __include("scout/form/fields/smartfield/ProposalChooser.js");
-  __include("scout/form/fields/smartfield/ProposalChooserLayout.js");
-  __include("scout/form/fields/smartfield/SmartFieldMultiline.js");
-  __include("scout/form/fields/smartfield/SmartFieldMultilineLayout.js");
-  __include("scout/form/fields/splitbox/SplitBox.js");
-  __include("scout/form/fields/splitbox/SplitBoxLayout.js");
-  __include("scout/form/fields/stringfield/StringField.js");
-  __include("scout/form/fields/stringfield/StringFieldEnterKeyStroke.js");
-  __include("scout/form/fields/stringfield/StringFieldCtrlEnterKeyStroke.js");
-  __include("scout/form/fields/tabbox/TabAreaLayout.js");
-  __include("scout/form/fields/tabbox/TabBox.js");
-  __include("scout/form/fields/tabbox/TabItemMnemonicKeyStroke.js");
-  __include("scout/form/fields/tabbox/TabBoxLayout.js");
-  __include("scout/form/fields/tabbox/TabItem.js");
-  __include("scout/form/fields/tabbox/TabItemLayout.js");
-  __include("scout/form/fields/tablefield/TableField.js");
-  __include("scout/form/fields/treebox/TreeBox.js");
-  __include("scout/form/fields/treebox/TreeBoxLayout.js");
-  __include("scout/form/fields/treefield/TreeField.js");
-  __include("scout/form/fields/wizard/WizardProgressField.js");
-  __include("scout/form/fields/wizard/WizardProgressFieldLayout.js");
-  __include("scout/form/fields/wrappedform/WrappedFormField.js");
-  // More misc. elements
-  __include("scout/desktop/DesktopFormController.js");
-  __include("scout/desktop/AbstractNavigateMenu.js"); // requires Menu.js
-  __include("scout/desktop/NavigateDownMenu.js");
-  __include("scout/desktop/NavigateUpMenu.js");
-  __include("scout/table/FilterFieldsGroupBox.js"); // requires GroupBox.js
-
-  __include("scout/table/MobileTable.js");
-  __include("scout/desktop/MobileDesktop.js");
-}(window.scout = window.scout || {}, jQuery));
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.css
index 256c273..af5a79e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.css
@@ -1,29 +1,40 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
+/*!
+* Eclipse Scout
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
 //@include("scout/main.css")
+//@include("scout/box/Box.css")
+//@include("scout/boxbuttons/BoxButtons.css")
 //@include("scout/calendar/Calendar.css")
 //@include("scout/calendar/YearPanel.css")
 //@include("scout/datepicker/DatePicker.css")
 //@include("scout/desktop/Desktop.css")
-//@include("scout/desktop/DesktopNavigation.css")
-//@include("scout/desktop/DesktopNotification.css")
-//@include("scout/desktop/NavigateButton.css")
+//@include("scout/desktop/DesktopLogo.css")
+//@include("scout/desktop/bench/DesktopBench.css")
+//@include("scout/desktop/bench/BenchColumn.css")
+//@include("scout/tabbox/SimpleTabBox.css")
+//@include("scout/collapsehandle/CollapseHandle.css")
+//@include("scout/desktop/header/DesktopHeader.css")
+//@include("scout/desktop/navigation/DesktopNavigation.css")
+//@include("scout/desktop/navigation/DesktopNavigationHandle.css")
+//@include("scout/desktop/notification/DesktopNotification.css")
 //@include("scout/desktop/outline/Outline.css")
 //@include("scout/desktop/outline/OutlineOverview.css")
 //@include("scout/desktop/outline/SearchOutline.css")
-//@include("scout/desktop/PopupBlockerDesktopNotification.css")
-//@include("scout/desktop/ViewButton.css")
+//@include("scout/desktop/outline/navigation/NavigateButton.css")
+//@include("scout/desktop/popupblocker/PopupBlockerDesktopNotification.css")
+//@include("scout/desktop/toolbox/DesktopToolBox.css")
+//@include("scout/desktop/viewbutton/ViewButton.css")
+//@include("scout/desktop/viewbutton/ViewButtonBox.css")
+//@include("scout/desktop/desktoptab/DesktopTab.css")
+//@include("scout/tabbox/SimpleTabArea.css")
 //@include("scout/filechooser/FileChooser.css")
 //@include("scout/form/Form.css")
-//@include("scout/form/FormToolPopup.css")
+//@include("scout/form/FormMenuPopup.css")
 //@include("scout/form/ScoutInfoForm.css")
 //@include("scout/form/fields/FormField.css")
 //@include("scout/form/fields/button/Button.css")
@@ -40,7 +51,6 @@
 //@include("scout/form/fields/labelfield/LabelField.css")
 //@include("scout/form/fields/listbox/ListBox.css")
 //@include("scout/form/fields/numberfield/NumberField.css")
-//@include("scout/form/fields/placeholder/PlaceholderField.css")
 //@include("scout/form/fields/plannerfield/PlannerField.css")
 //@include("scout/form/fields/radiobutton/RadioButton.css")
 //@include("scout/form/fields/radiobutton/RadioButtonGroup.css")
@@ -54,15 +64,18 @@
 //@include("scout/form/fields/treefield/TreeField.css")
 //@include("scout/form/fields/wizard/WizardProgressField.css")
 //@include("scout/form/fields/wrappedform/WrappedFormField.css")
+//@include("scout/keystroke/keybox.css")
 //@include("scout/menu/Menu.css")
-//@include("scout/menu/MenuBar.css")
+//@include("scout/menu/menubar/MenuBar.css")
 //@include("scout/messagebox/MessageBox.css")
 //@include("scout/planner/Planner.css")
 //@include("scout/planner/PlannerHeader.css")
 //@include("scout/popup/Popup.css");
+//@include("scout/popup/MobilePopup.css");
 //@include("scout/popup/TouchPopup.css");
 //@include("scout/scrollbar/Scrollbar.css")
 //@include("scout/session/BusyIndicator.css")
+//@include("scout/slider/Slider.css")
 //@include("scout/splitter/Splitter.css")
 //@include("scout/style/animations.css")
 //@include("scout/style/colors.css")
@@ -74,12 +87,11 @@
 //@include("scout/table/TableFooter.css")
 //@include("scout/table/TableHeader.css")
 //@include("scout/table/TableHeaderMenu.css")
+//@include("scout/table/TableRowDetail.css")
 //@include("scout/table/controls/TableControl.css")
 //@include("scout/table/editor/CellEditorPopup.css")
 //@include("scout/tooltip/Tooltip.css")
 //@include("scout/tree/Tree.css")
 //@include("scout/tree/CompactTree.css")
-//@include("scout/util/BoxButtons.css")
-//@include("scout/util/keybox.css")
 //@include("scout/util/ui-mouse.css")
 //@include("scout/util/ui-resizable.css")
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.js
index a22a2b1..d7a8a3a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout-module.js
@@ -1,26 +1,23 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-__include("jquery/jquery-scout.js");
+/*!
+* Eclipse Scout
+* https://eclipse.org/scout/
+*
+* Copyright (c) BSI Business Systems Integration AG. All rights reserved.
+* Released under the Eclipse Public License v1.0
+* http://www.eclipse.org/legal/epl-v10.html
+*/
 // protects $ and undefined from being redefined by another library
 (function(scout, $, undefined) {
+  __include("jquery/jquery-scout.js");
   __include("scout/main.js");
+  __include("scout/ObjectFactory.js");
   __include("scout/objectFactories.js");
   __include("scout/widget/Widget.js");
   __include("scout/widget/NullWidget.js");
   // Basic utilities
   __include("scout/util/arrays.js");
-  __include("scout/util/BoxButtons.js");
   __include("scout/util/dates.js");
   __include("scout/util/defaultValues.js");
-  __include("scout/util/DeferredGlassPaneTarget.js");
   __include("scout/util/DetachHelper.js");
   __include("scout/util/Device.js");
   __include("scout/util/DoubleClickSupport.js");
@@ -28,16 +25,10 @@
   __include("scout/util/EventSupport.js");
   __include("scout/util/fonts.js");
   __include("scout/util/icons.js");
-  __include("scout/util/FocusManager.js");
-  __include("scout/util/FocusContext.js");
-  __include("scout/util/focusUtils.js");
-  __include("scout/util/focusRule.js");
   __include("scout/util/inspector.js");
   __include("scout/util/logging.js");
   __include("scout/util/mimeTypes.js");
-  __include("scout/util/ModelAdapter.js");
   __include("scout/util/numbers.js");
-  __include("scout/util/ObjectFactory.js");
   __include("scout/util/objects.js");
   __include("scout/util/polyfills.js");
   __include("scout/util/Range.js");
@@ -45,7 +36,6 @@
   __include("scout/util/strings.js");
   __include("scout/util/styles.js");
   __include("scout/util/URL.js");
-  __include("scout/util/GlassPaneRenderer.js");
   __include("scout/util/filters.js");
   __include("scout/util/hAlign.js");
   __include("scout/util/aggregation.js");
@@ -54,6 +44,7 @@
   __include("scout/session/BusyIndicator.js");
   __include("scout/session/Event.js");
   __include("scout/session/Locale.js");
+  __include("scout/session/ModelAdapter.js");
   __include("scout/session/Reconnector.js");
   __include("scout/session/ResponseQueue.js");
   __include("scout/session/Session.js");
@@ -76,7 +67,6 @@
   __include("scout/keystroke/VirtualKeyStrokeEvent.js");
   __include("scout/keystroke/KeyStrokeManager.js");
   __include("scout/keystroke/KeyStrokeContext.js");
-  __include("scout/keystroke/KeyStrokeSupport.js");
   __include("scout/keystroke/InputFieldKeyStrokeContext.js");
   __include("scout/keystroke/KeyStroke.js");
   __include("scout/keystroke/RangeKeyStroke.js");
@@ -86,6 +76,14 @@
   __include("scout/keystroke/FocusAdjacentElementKeyStroke.js");
   __include("scout/keystroke/CloseKeyStroke.js");
   // Misc. elements
+  __include("scout/boxbuttons/BoxButtons.js");
+  __include("scout/collapsehandle/CollapseHandle.js");
+  __include("scout/focus/FocusManager.js");
+  __include("scout/focus/FocusContext.js");
+  __include("scout/focus/focusUtils.js");
+  __include("scout/focus/focusRule.js");
+  __include("scout/glasspane/DeferredGlassPaneTarget.js");
+  __include("scout/glasspane/GlassPaneRenderer.js");
   __include("scout/scrollbar/Scrollbar.js");
   __include("scout/scrollbar/scrollbars.js");
   __include("scout/splitter/Splitter.js");
@@ -93,13 +91,16 @@
   __include("scout/text/DecimalFormat.js");
   __include("scout/text/Texts.js");
   __include("scout/tooltip/Tooltip.js");
-  __include("scout/util/tooltips.js");
+  __include("scout/tooltip/tooltips.js");
   __include("scout/action/Action.js");
   __include("scout/action/ActionKeyStroke.js");
+  __include("scout/box/Box.js");
   __include("scout/popup/Popup.js");
   __include("scout/popup/PopupLayout.js");
   __include("scout/popup/PopupWithHead.js");
   __include("scout/popup/PopupWithHeadLayout.js");
+  __include("scout/popup/MobilePopup.js");
+  __include("scout/popup/MobilePopupLayout.js");
   __include("scout/popup/TouchPopup.js");
   __include("scout/popup/TouchPopupLayout.js");
   __include("scout/datepicker/DatePicker.js");
@@ -109,16 +110,18 @@
   __include("scout/menu/menus.js");
   __include("scout/menu/Menu.js");
   __include("scout/menu/MenuKeyStroke.js");
-  __include("scout/menu/MenuBar.js");
-  __include("scout/menu/MenuBarLeftKeyStroke.js");
-  __include("scout/menu/MenuBarRightKeyStroke.js");
-  __include("scout/menu/MenuBarLayout.js");
   __include("scout/menu/MenuExecKeyStroke.js");
   __include("scout/menu/MenuItemsOrder.js");
   __include("scout/menu/ContextMenuPopup.js");
   __include("scout/menu/menuNavigationKeyStrokes.js");
-  __include("scout/menu/MenuBarPopup.js");
   __include("scout/menu/ButtonAdapterMenu.js");
+  __include("scout/menu/menubox/MenuBox.js");
+  __include("scout/menu/menubox/MenuBoxLayout.js");
+  __include("scout/menu/menubar/MenuBar.js");
+  __include("scout/menu/menubar/MenuBarLayout.js");
+  __include("scout/menu/menubar/MenuBarLeftKeyStroke.js");
+  __include("scout/menu/menubar/MenuBarRightKeyStroke.js");
+  __include("scout/menu/menubar/MenuBarPopup.js");
   __include("scout/calendar/Calendar.js");
   __include("scout/calendar/CalendarComponent.js");
   __include("scout/calendar/CalendarListComponent.js");
@@ -131,6 +134,15 @@
   __include("scout/planner/PlannerMenuItemsOrder.js");
   __include("scout/filechooser/FileChooser.js");
   __include("scout/filechooser/FileChooserController.js");
+  __include("scout/slider/Slider.js");
+  __include("scout/slider/SliderLayout.js");
+  // Form
+  __include("scout/form/Form.js");
+  __include("scout/form/FormLayout.js");
+  __include("scout/form/FormMenu.js");
+  __include("scout/form/FormMenuPopup.js");
+  __include("scout/form/FormMenuPopupLayout.js");
+  __include("scout/form/DialogLayout.js");
   // Table
   __include("scout/table/Table.js");
   __include("scout/table/TableMatrix.js");
@@ -147,6 +159,7 @@
   __include("scout/table/TableHeaderMenuButtonKeyStroke.js");
   __include("scout/table/TableLayout.js");
   __include("scout/table/TableSelectionHandler.js");
+  __include("scout/table/TableRowDetail.js");
   __include("scout/table/TableTooltip.js");
   __include("scout/table/columns/comparators.js");
   __include("scout/table/columns/Column.js");
@@ -156,7 +169,10 @@
   __include("scout/table/columns/IconColumn.js"); //requires Column.js
   __include("scout/table/columns/NumberColumn.js"); //requires Column.js
   __include("scout/table/controls/TableControl.js");
+  __include("scout/table/controls/TableControlAdapterMenu.js"); // requires FormMenu and TableControl
   __include("scout/table/controls/AggregateTableControl.js"); // requires TableControl.js
+  __include("scout/table/controls/FormTableControl.js"); // requires TableControl.js
+  __include("scout/table/controls/FormTableControlLayout.js");
   __include("scout/table/editor/CellEditorPopup.js");
   __include("scout/table/editor/CellEditorPopupLayout.js");
   __include("scout/table/editor/CellEditorCancelEditKeyStroke.js");
@@ -185,10 +201,13 @@
   // Tree
   __include("scout/tree/Tree.js");
   __include("scout/tree/TreeLayout.js");
+  __include("scout/tree/LazyNodeFilter.js");
+  __include("scout/tree/TreeBreadcrumbFilter.js");
   __include("scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js");
   __include("scout/tree/keystrokes/TreeSpaceKeyStroke.js");
   __include("scout/tree/keystrokes/TreeNavigationUpKeyStroke.js");
   __include("scout/tree/keystrokes/TreeNavigationDownKeyStroke.js");
+  __include("scout/tree/keystrokes/TreeNavigationEndKeyStroke.js");
   __include("scout/tree/keystrokes/TreeCollapseAllKeyStroke.js");
   __include("scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js");
   __include("scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js");
@@ -200,47 +219,57 @@
   __include("scout/tree/keystrokes/CompactTreeLeftKeyStroke.js");
   __include("scout/tree/keystrokes/CompactTreeRightKeyStroke.js");
   // Desktop
-  __include("scout/desktop/BaseDesktop.js");
   __include("scout/desktop/Desktop.js");
+  __include("scout/desktop/DesktopLayout.js");
+  __include("scout/desktop/DesktopLogo.js");
   __include("scout/desktop/DesktopKeyStroke.js");
-  __include("scout/desktop/DesktopTaskBarLayout.js");
-  __include("scout/desktop/DesktopViewTab.js");
-  __include("scout/desktop/ViewMenuOpenKeyStroke.js");
-  __include("scout/desktop/ViewMenuPopup.js");
-  __include("scout/desktop/ViewMenuTab.js");
-  __include("scout/desktop/ViewTabSelectKeyStroke.js");
-  __include("scout/desktop/DisableBrowserTabSwitchingKeyStroke.js");
-  __include("scout/desktop/DesktopNavigation.js");
-  __include("scout/desktop/DesktopNotification.js");
-  __include("scout/desktop/DetailTableTreeFilter.js");
-  __include("scout/desktop/NullDesktopNavigation.js");
-  __include("scout/desktop/OfflineDesktopNotification.js");
-  __include("scout/desktop/PopupBlockerHandler.js");
-  __include("scout/desktop/PopupBlockerDesktopNotification.js");
   __include("scout/desktop/PopupWindow.js");
-  __include("scout/desktop/ViewButton.js");
-  __include("scout/desktop/ViewButtonsLayout.js");
-  __include("scout/desktop/ViewTabsController.js");
+  __include("scout/tabbox/SimpleTabBoxController.js");
+  __include("scout/tabbox/SimpleTabBox.js");
+  __include("scout/tabbox/SimpleTabBoxLayout.js");
+  __include("scout/desktop/bench/DesktopBench.js");
+  __include("scout/desktop/bench/DesktopBenchLayout.js");
+  __include("scout/desktop/bench/BenchColumn.js");
+  __include("scout/desktop/bench/BenchColumnLayout.js");
+  __include("scout/desktop/desktoptab/DesktopTabSelectKeyStroke.js");
+  __include("scout/desktop/desktoptab/DisableBrowserTabSwitchingKeyStroke.js");
+  __include("scout/desktop/header/DesktopHeader.js");
+  __include("scout/desktop/header/HeaderTabBoxController.js");
+  __include("scout/desktop/header/DesktopHeaderLayout.js");
+  __include("scout/desktop/navigation/DesktopNavigation.js");
+  __include("scout/desktop/navigation/DesktopNavigationHandle.js");
+  __include("scout/desktop/navigation/DesktopNavigationLayout.js");
+  __include("scout/desktop/navigation/ShrinkNavigationKeyStroke.js");
+  __include("scout/desktop/navigation/EnlargeNavigationKeyStroke.js");
+  __include("scout/desktop/notification/DesktopNotification.js");
+  __include("scout/desktop/notification/OfflineDesktopNotification.js");
+  __include("scout/desktop/popupblocker/PopupBlockerHandler.js");
+  __include("scout/desktop/popupblocker/PopupBlockerDesktopNotification.js");
+  __include("scout/desktop/toolbox/DesktopToolBox.js");
+  __include("scout/desktop/viewbutton/ViewButton.js");
+  __include("scout/desktop/viewbutton/ViewButtonBox.js");
+  __include("scout/desktop/viewbutton/ViewButtonBoxLayout.js");
+  __include("scout/desktop/viewbutton/ViewMenuOpenKeyStroke.js");
+  __include("scout/desktop/viewbutton/ViewMenuPopup.js");
+  __include("scout/desktop/viewbutton/ViewMenuTab.js");
+  __include("scout/tabbox/SimpleTab.js");
+  __include("scout/desktop/desktoptab/DesktopTab.js"); // requires SimpleTab.js
+  __include("scout/tabbox/SimpleTabArea.js");
+  __include("scout/tabbox/SimpleTabAreaLayout.js");
+  __include("scout/desktop/outline/DetailTableTreeFilter.js");
   __include("scout/desktop/outline/Outline.js");
   __include("scout/desktop/outline/OutlineOverview.js");
-  __include("scout/desktop/outline/OutlineKeyStrokeContext.js");
   __include("scout/desktop/outline/OutlineLayout.js");
-  __include("scout/desktop/outline/AbstractOutlineNavigationKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigationUpKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigateToTopKeyStroke.js");
-  __include("scout/desktop/outline/OutlineCollapseOrDrillUpKeyStroke.js");
-  __include("scout/desktop/outline/OutlineExpandOrDrillDownKeyStroke.js");
-  __include("scout/desktop/outline/OutlineNavigationDownKeyStroke.js");
-  __include("scout/desktop/outline/OutlineViewButton.js");
+  __include("scout/desktop/outline/OutlineViewButton.js"); // requires ViewButton.js
+  __include("scout/desktop/outline/PageLayout.js");
   __include("scout/desktop/outline/SearchOutline.js");
   __include("scout/desktop/outline/SearchOutlineLayout.js");
+  __include("scout/desktop/outline/navigation/NavigateButton.js"); // requires Menu.js
+  __include("scout/desktop/outline/navigation/NavigateDownButton.js");
+  __include("scout/desktop/outline/navigation/NavigateUpButton.js");
+  __include("scout/desktop/outline/keystrokes/OutlineKeyStrokeContext.js");
+  __include("scout/desktop/outline/keystrokes/OutlineNavigateToTopKeyStroke.js");
   // Basics for form fields
-  __include("scout/form/Form.js");
-  __include("scout/form/FormLayout.js");
-  __include("scout/form/FormToolButton.js");
-  __include("scout/form/FormToolPopup.js");
-  __include("scout/form/FormToolPopupLayout.js");
-  __include("scout/form/DialogLayout.js");
   __include("scout/form/fields/fields.js");
   __include("scout/form/fields/AppLinkKeyStroke.js");
   __include("scout/form/fields/DefaultFieldLoadingSupport.js");
@@ -286,6 +315,7 @@
   __include("scout/form/fields/radiobutton/RadioButtonGroupRightKeyStroke.js");
   __include("scout/form/fields/radiobutton/RadioButtonKeyStroke.js");
   __include("scout/form/fields/sequencebox/SequenceBox.js");
+  __include("scout/form/fields/slider/SliderField.js");
   __include("scout/form/fields/smartfield/SmartField.js");
   __include("scout/form/fields/smartfield/SmartFieldTouchPopup.js");
   __include("scout/form/fields/smartfield/SmartFieldLayout.js");
@@ -296,6 +326,7 @@
   __include("scout/form/fields/smartfield/SmartFieldMultiline.js");
   __include("scout/form/fields/smartfield/SmartFieldMultilineLayout.js");
   __include("scout/form/fields/splitbox/SplitBox.js");
+  __include("scout/form/fields/splitbox/SplitBoxCollapseKeyStroke.js");
   __include("scout/form/fields/splitbox/SplitBoxLayout.js");
   __include("scout/form/fields/stringfield/StringField.js");
   __include("scout/form/fields/stringfield/StringFieldEnterKeyStroke.js");
@@ -315,8 +346,5 @@
   __include("scout/form/fields/wrappedform/WrappedFormField.js");
   // More misc. elements
   __include("scout/desktop/DesktopFormController.js");
-  __include("scout/desktop/AbstractNavigateMenu.js"); // requires Menu.js
-  __include("scout/desktop/NavigateDownMenu.js");
-  __include("scout/desktop/NavigateUpMenu.js");
   __include("scout/table/FilterFieldsGroupBox.js"); // requires GroupBox.js
-}(window.scout = window.scout || {}, jQuery));
+}(window.scout = window.scout || {}, jQuery)); //NOSONAR
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/ObjectFactory.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/ObjectFactory.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/ObjectFactory.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/ObjectFactory.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/Action.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/Action.js
index 5057cdc..b9cf946 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/Action.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/Action.js
@@ -23,8 +23,8 @@
    * - button: menu looks like a button
    */
   this.actionStyle = scout.Action.ActionStyle.DEFAULT;
-
-  this.actionKeyStroke = this._createActionKeyStroke();
+  this.textVisible = true;
+  this.compact = false;
 };
 scout.inherits(scout.Action, scout.ModelAdapter);
 
@@ -35,7 +35,9 @@
 
 scout.Action.prototype._init = function(model) {
   scout.Action.parent.prototype._init.call(this, model);
+  this.actionKeyStroke = this._createActionKeyStroke();
   this._syncKeyStroke(this.keyStroke);
+  this._syncSelected(this.selected);
 };
 
 scout.Action.prototype._renderProperties = function() {
@@ -49,6 +51,7 @@
   this._renderSelected();
   this._renderVisible();
   this._renderTabbable();
+  this._renderCompact();
   this._renderCssClass(this.cssClass);
 };
 
@@ -59,7 +62,7 @@
 
 scout.Action.prototype._renderText = function() {
   var text = this.text || '';
-  if (text) {
+  if (text && this.textVisible) {
     if (!this.$text) {
       // Create a separate text element to so that setting the text does not remove the icon
       this.$text = this.$container.appendSpan('text');
@@ -92,7 +95,7 @@
   this.$container.setVisible(this.visible);
 };
 
-scout.Action.prototype._renderSelected = function(event) {
+scout.Action.prototype._renderSelected = function() {
   this.$container.select(this.selected);
   this._updateTooltip();
 };
@@ -146,6 +149,11 @@
   // nop
 };
 
+scout.Action.prototype._renderCompact = function() {
+  this.$container.toggleClass('compact', this.compact);
+  this.invalidateLayoutTree();
+};
+
 scout.Action.prototype._configureTooltip = function() {
   return {
     parent: this,
@@ -166,31 +174,26 @@
 };
 
 /**
- * @param event
- *          UI event that triggered the action (e.g. 'mouse down'). This argument
- *          may be used by action implementors to check if the action should really
- *          be performed. E.g. the MenuBarPopup uses it to prevent the popup from
- *          being closed again by the same event when it bubbles to other elements.
  * @return {Boolean}
  *          <code>true</code> if the action has been performed or <code>false</code> if it
  *          has not been performed (e.g. when the button is not enabled).
  */
-scout.Action.prototype.doAction = function(event) {
-  if (!this.prepareDoAction(event)) {
+scout.Action.prototype.doAction = function() {
+  if (!this.prepareDoAction()) {
     return false;
   }
 
   if (this.isToggleAction()) {
-    this.setSelected(!this.selected, event);
+    this.setSelected(!this.selected);
   } else {
     this.sendDoAction();
   }
   return true;
 };
 
-scout.Action.prototype.toggle = function(event) {
+scout.Action.prototype.toggle = function() {
   if (this.isToggleAction()) {
-    this.setSelected(!this.selected, event);
+    this.setSelected(!this.selected);
   }
 };
 
@@ -201,28 +204,11 @@
 /**
  * @returns {Boolean} <code>true</code> if the action may be executed, <code>false</code> if it should be ignored.
  */
-scout.Action.prototype.prepareDoAction = function(event) {
+scout.Action.prototype.prepareDoAction = function() {
   if (!this.enabled || !this.visible) {
     return false;
   }
 
-  // This is required for key-stroke actions. When they are triggered on
-  // key-down, the active field is still focused and its blur-event is not
-  // triggered, which means the acceptInput() is never executed so
-  // the executed action works with a wrong value for the active field.
-  // --> Same check in Button.doAction()
-  if (event && event.target) {
-    var $activeElement = $(event.target.ownerDocument.activeElement),
-      activeValueField = $activeElement.data('valuefield');
-    if (activeValueField === undefined) {
-      // try parent, some times the value field is the parent of the input field (e.g. DateField.js)
-      activeValueField = $activeElement.parent().data('valuefield');
-    }
-    if (activeValueField) {
-      activeValueField.acceptInput();
-    }
-  }
-
   return true;
 };
 
@@ -248,15 +234,17 @@
   // NOP
 };
 
-scout.Action.prototype.setSelected = function(selected, event) {
+scout.Action.prototype.setSelected = function(selected, notifyServer) {
   if (selected === this.selected) {
     return;
   }
   this._setProperty('selected', selected);
-  if (this.rendered) {
-    this._renderSelected(event);
+  if (scout.nvl(notifyServer, true)) {
+    this.sendSelected();
   }
-  this.sendSelected();
+  if (this.rendered) {
+    this._renderSelected();
+  }
 };
 
 scout.Action.prototype.sendSelected = function() {
@@ -265,6 +253,11 @@
   });
 };
 
+scout.Action.prototype._syncSelected = function(selected) {
+  this.setSelected(selected, false);
+  return false;
+};
+
 scout.Action.prototype._syncKeyStroke = function(keyStroke) {
   this.keyStroke = keyStroke;
   this.actionKeyStroke.parseAndSetKeyStroke(keyStroke);
@@ -277,6 +270,23 @@
   }
 };
 
+scout.Action.prototype.setTextVisible = function(textVisible) {
+  this.textVisible = textVisible;
+  if (this.rendered) {
+    this._renderText();
+  }
+};
+
+scout.Action.prototype.setCompact = function(compact) {
+  if (this.compact === compact) {
+    return;
+  }
+  this.compact = compact;
+  if (this.rendered) {
+    this._renderCompact();
+  }
+};
+
 scout.Action.prototype._createActionKeyStroke = function() {
   return new scout.ActionKeyStroke(this);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/ActionKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/ActionKeyStroke.js
index 04c172f..1477ac3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/ActionKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/action/ActionKeyStroke.js
@@ -26,5 +26,5 @@
 };
 
 scout.ActionKeyStroke.prototype.handle = function(event) {
-  this.field.doAction(event);
+  this.field.doAction();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.css
new file mode 100644
index 0000000..0d7dc27
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.css
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+/**
+ * Used for static pages like login, logout, unsupported-browser and noscript section.
+ * Note: This box must not depend on javascript because it is used for the noscript section as well.
+ */
+@box-width: 420px;
+@box-margin-v: 15px;
+.box {
+  display: table;
+  position: absolute;
+  height: 75%;
+  width: 100%;
+  margin: @box-margin-v 0;
+
+  & > .wrapper {
+    display: table-cell;
+    vertical-align: middle;
+  }
+}
+
+
+.box-content {
+  border: 1px solid @palette-gray-5;
+  background-color: @background-color;
+  max-width: @box-width;
+  margin: 0 auto;
+  padding: 40px 70px;
+  #scout.drop-shadow();
+
+  & > .header {
+    text-align: center;
+
+    & > .logo {
+      margin-top: 5px;
+      margin-bottom: 40px;
+    }
+  }
+
+  & > .button-bar {
+    padding-top: 32px;
+    text-align: center;
+
+    & > .button {
+      padding: 7px @button-padding-x;
+    }
+  }
+
+  &.small > .header > .logo {
+    width: 50%;
+  }
+
+  &.centered {
+    text-align: center;
+  }
+}
+
+@media (max-width: (@box-width + 40px)) {
+  .box-content {
+    & > .header > .logo {
+      margin-bottom: 20px;
+    }
+
+    padding: 20px;
+    margin-left: 10px;
+    margin-right: 10px;
+  }
+}
+
+@media (max-height: 400px) {
+  .box-content {
+    & > .header > .logo {
+      margin-bottom: 20px;
+    }
+
+    padding-top: 20px;
+    padding-bottom: 20px;
+  }
+}
+
+@media (max-height: 700px) {
+  .box {
+    height: calc(~'100%' - @box-margin-v * 2);
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.js
new file mode 100644
index 0000000..fabd227
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/box/Box.js
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+/**
+ * Used for static pages like login, logout, unsupported-browser and noscript section.
+ * Beside custom elements it may contain a header with a logo and a button bar.
+ * Note: It does not extend from Widget because widget has too many dependencies which are not needed for this simple use case (login-module does not include these dependencies)
+ */
+scout.Box = function() {
+};
+
+scout.Box.prototype.render = function($parent) {
+  this._render($parent);
+  this.rendered = true;
+};
+
+scout.Box.prototype.remove = function() {
+  this.$container.remove();
+  this.$container = null;
+  this.rendered = false;
+};
+
+scout.Box.prototype._render = function($parent) {
+  this.$container = $('<div>')
+    .addClass('box')
+    .appendTo($parent);
+
+  this.$wrapper = $('<div>')
+    .addClass('wrapper')
+    .appendTo(this.$container);
+
+  this.$content = $('<div>')
+    .addClass('box-content')
+    .appendTo(this.$wrapper);
+
+  if (this.logoUrl) {
+    this.$header = this.$content.appendDiv('header');
+    this.$logo = $('<img>')
+      .addClass('logo')
+      .attr('src', this.logoUrl)
+      .appendTo(this.$header);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/BoxButtons.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/boxbuttons/BoxButtons.css
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/BoxButtons.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/boxbuttons/BoxButtons.css
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/BoxButtons.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/boxbuttons/BoxButtons.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/BoxButtons.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/boxbuttons/BoxButtons.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/Calendar.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/Calendar.js
index c8527d3..0bc3602 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/Calendar.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/Calendar.js
@@ -120,6 +120,12 @@
     scout.dates.parseJsonDate(viewRange.to));
 };
 
+scout.Calendar.prototype._syncMenus = function(menus, oldMenus) {
+  this.menus = menus;
+  // FIXME awe: (calendar) here we should update the menu-bar (see Table.js)
+  $.log.debug('(Calendar#_syncMenus) impl.');
+};
+
 scout.Calendar.prototype._render = function($parent) {
   this.$container = $parent.appendDiv('calendar');
 
@@ -230,8 +236,11 @@
 };
 
 scout.Calendar.prototype._renderMenus = function() {
-  // FIXME awe: (calendar) here we should update the menu-bar (see Table.js)
-  $.log.debug('(Calendar#_renderMenus) impl.');
+  // NOP
+};
+
+scout.Calendar.prototype._removeMenus = function() {
+  // menubar takes care about removal
 };
 
 /* -- basics, events -------------------------------------------- */
@@ -779,7 +788,7 @@
 
 /* -- components, arrangement------------------------------------ */
 
-// FIXME awe, cru: arrange methods should work on the model, not on the DOM
+// FIXME awe, cru: (calendar) arrange methods should work on the model, not on the DOM
 scout.Calendar.prototype._arrangeComponents = function() {
   var k, $day, $children,
     $days = $('.calendar-day', this.$grid);
@@ -832,7 +841,7 @@
 };
 
 scout.Calendar.prototype._arrangeComponentFindPlacement = function($children) {
-  // FIXME awe: placement may be improved, test cases needed
+  // FIXME awe: (calendar) placement may be improved, test cases needed
   // 1: change x if column on the left side free
   // 2: change w if place on the right side not used
   // -> then find new w (just use _arrangeComponentInitialW)
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarComponent.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarComponent.js
index 71a90bc..18c1215 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarComponent.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarComponent.js
@@ -97,7 +97,7 @@
   }
 };
 
-// FIXME awe: tuning
+// FIXME awe: (calendar) tuning
 scout.CalendarComponent.prototype._findDayInGrid = function(date) {
   var $day;
   $('.calendar-day', this.parent.$grid)
@@ -151,7 +151,7 @@
   var oldSelected = this._selected;
   this._selected = selected;
   if (oldSelected !== selected) {
-    this.events.trigger('selected', {
+    this.trigger('selected', {
       selected: selected
     });
     this._renderSelected();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.css
new file mode 100644
index 0000000..75799b8
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.css
@@ -0,0 +1,63 @@
+.collapse-handle {
+  position: absolute;
+  display: table;
+  z-index: 10;
+  bottom: 0;
+  margin-bottom: 9px;
+  box-shadow: 2px 3px 7px 0px rgba(0, 0, 0, 0.4);
+  border-radius: @border-radius;
+
+  &.one-visible {
+    cursor: pointer;
+
+    &:active > .collapse-handle-body {
+      background-color: @collapse-handle-active-background-color;
+    }
+  }
+}
+
+.collapse-handle-body {
+  position: relative;
+  display: table-cell;
+  padding: 8px;
+  background-color: @collapse-handle-background-color;
+  color: fade(@collapse-handle-color, 75%);
+  border: 1px solid fade(@collapse-handle-border-color, 75%);
+  border-radius: @border-radius;
+  cursor: pointer;
+
+  &::before {
+    #scout.font-icon();
+    display: block;
+    padding-right: 1px;
+  }
+
+  &.left {
+    &.both-visible {
+      border-top-right-radius: 0;
+      border-bottom-right-radius: 0;
+    }
+
+    &::before {
+      content: @icon-angle-left;
+    }
+  }
+
+  &.right {
+    &.both-visible {
+      border-top-left-radius: 0;
+      border-bottom-left-radius: 0;
+      border-left: none;
+    }
+
+    &::before {
+      content: @icon-angle-right;
+    }
+  }
+
+  &:active {
+    background-color: @collapse-handle-active-background-color;
+  }
+
+}
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.js
new file mode 100644
index 0000000..d18e8a6
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/collapsehandle/CollapseHandle.js
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.CollapseHandle = function() {
+  scout.CollapseHandle.parent.call(this);
+  this._addEventSupport();
+  this.leftVisible = false;
+  this.rightVisible = false;
+};
+scout.inherits(scout.CollapseHandle, scout.Widget);
+
+scout.CollapseHandle.prototype._init = function(model) {
+  scout.CollapseHandle.parent.prototype._init.call(this, model);
+
+  var defaults = {
+    leftVisible: true,
+    rightVisible: true
+  };
+  $.extend(this, defaults, model);
+};
+
+scout.CollapseHandle.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('collapse-handle');
+  this.$container.on('mousedown', this._onMouseDown.bind(this));
+
+  this.$left = this.$container.appendDiv('collapse-handle-body left');
+  this.$right = this.$container.appendDiv('collapse-handle-body right');
+  this.session.keyStrokeManager.installKeyStrokeContext(this.desktopKeyStrokeContext);
+};
+
+scout.CollapseHandle.prototype._remove = function() {
+  scout.CollapseHandle.parent.prototype._remove.call(this);
+  this.session.keyStrokeManager.uninstallKeyStrokeContext(this.desktopKeyStrokeContext);
+};
+
+scout.CollapseHandle.prototype._renderProperties = function() {
+  this._renderLeftVisible();
+  this._renderRightVisible();
+};
+
+scout.CollapseHandle.prototype._renderLeftVisible = function() {
+  this.$left.setVisible(this.leftVisible);
+  this._updateVisibilityClasses();
+};
+
+scout.CollapseHandle.prototype._renderRightVisible = function() {
+  this.$right.setVisible(this.rightVisible);
+  this._updateVisibilityClasses();
+};
+
+scout.CollapseHandle.prototype._updateVisibilityClasses = function() {
+  var bothVisible = this.leftVisible && this.rightVisible;
+  this.$container.toggleClass('both-visible', bothVisible);
+  this.$left.toggleClass('both-visible', bothVisible);
+  this.$right.toggleClass('both-visible', bothVisible);
+  this.$container.toggleClass('one-visible', (this.leftVisible || this.rightVisible) && !bothVisible);
+};
+
+scout.CollapseHandle.prototype.setLeftVisible = function(visible) {
+  if (this.leftVisible === visible) {
+    return;
+  }
+  this._setProperty('leftVisible', visible);
+  if (this.rendered) {
+    this._renderLeftVisible();
+  }
+};
+
+scout.CollapseHandle.prototype.setRightVisible = function(visible) {
+  if (this.rightVisible === visible) {
+    return;
+  }
+  this._setProperty('rightVisible', visible);
+  if (this.rendered) {
+    this._renderRightVisible();
+  }
+};
+
+scout.CollapseHandle.prototype._onLeftMouseDown = function(event) {
+  this.trigger('action', {
+    left: true
+  });
+};
+
+scout.CollapseHandle.prototype._onRightMouseDown = function(event) {
+  this.trigger('action', {
+    right: true
+  });
+};
+
+scout.CollapseHandle.prototype._onMouseDown = function(event) {
+  var target = event.target;
+  if (this.$left.isOrHas(target)) {
+    this.trigger('action', {
+      left: true
+    });
+    return;
+  }
+  if (this.$right.isOrHas(target)) {
+    this.trigger('action', {
+      right: true
+    });
+    return;
+  }
+
+  // If there is only one box visible, trigger also when container was clicked
+  // Mainly used to make the pixel on the left clickable, when the handle is visible in bench mode
+  if (this.$container.hasClass('one-visible')) {
+    this.trigger('action', {
+      left: this.leftVisible,
+      right: this.rightVisible
+    });
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.css
index ed96c71..e437ca8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.css
@@ -49,7 +49,7 @@
   border-radius: 50%;
   border: 1px solid transparent;
 
-  &:hover {
+  &:hover:not(.date-picker-disabled) {
     border-color: @item-selection-border-color;
     background-color:  @palette-blue-0;
 
@@ -76,8 +76,8 @@
     font-weight: bold;
   }
 
-  &.date-picker-preselected:not(:hover) {
-    border-color:  @item-selection-border-color;
+  &.date-picker-preselected {
+    border-color: @item-selection-border-color;
     border-style: dashed;
 
     &.date-picker-now {
@@ -94,6 +94,11 @@
       color: @palette-white;
     }
   }
+
+  /* Must be after other style definitions, because 'disabled' should overrule other definitions */
+  &.date-picker-disabled {
+    color: @palette-gray-5;
+  }
 }
 
 .date-picker-header {
@@ -145,6 +150,10 @@
   &:hover {
     color: @hover-color;
   }
+
+  &:active {
+    color: @active-color;
+  }
 }
 
 .date-picker-left-y,
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.js
index fa54a78..74efd9f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePicker.js
@@ -18,6 +18,7 @@
   this.selectedDate;
   this.dateFormat;
   this.viewDate;
+  this.allowedDates;
   this.$container;
   this.$currentBox;
   this.$scrollable;
@@ -30,6 +31,7 @@
   scout.DatePicker.parent.prototype._init.call(this, options);
   options = options || {};
   this.dateFormat = options.dateFormat;
+  this.allowedDates = options.allowedDates;
 };
 
 scout.DatePicker.prototype._render = function($parent) {
@@ -86,7 +88,6 @@
   this._updateHeader(viewDate);
 
   var $box = this._build$DateBox();
-  $box.find('.date-picker-day').click(this._onDayClick.bind(this));
   $box[0].addEventListener('mousewheel', this._onMouseWheel.bind(this), false);
 
   if (animated && this.$currentBox && viewDateDiff) {
@@ -109,7 +110,7 @@
     that = this;
   var monthBoxCount = this.$scrollable.find('.date-picker-month').length + 1;
 
-  this.htmlComp._layout._layoutMonth($box);
+  this.htmlComp.layout._layoutMonth($box);
 
   this._boxWidth = $box.width();
   var scrollableWidth = monthBoxCount * this._boxWidth;
@@ -189,8 +190,17 @@
 
 scout.DatePicker.prototype.shiftSelectedDate = function(years, months, days) {
   var date = this.preselectedDate;
+
   if (this.selectedDate) {
-    date = scout.dates.shift(this.selectedDate, years, months, days);
+    if (this.allowedDates) {
+      date = this._findNextAllowedDate(years, months, days);
+    } else {
+      date = scout.dates.shift(this.selectedDate, years, months, days);
+    }
+  }
+
+  if (!date) {
+    return; // do nothing when no date was found
   }
 
   this.trigger('dateSelect', {
@@ -200,9 +210,42 @@
   this.selectDate(date, true);
 };
 
+scout.DatePicker.prototype._findNextAllowedDate = function(years, months, days) {
+  var i, date,
+    sum = years + months + days,
+    dir = sum > 0 ? 1 : -1,
+    now = this.selectedDate || scout.dates.trunc(new Date());
+
+  // if we shift by year or month, shift the 'now' date and then use that date as starting point
+  // to find the next allowed date.
+  if (years !== 0) {
+    now = scout.dates.shift(now, years, 0, 0);
+  } else if (months !== 0) {
+    now = scout.dates.shift(now, 0, months, 0);
+  }
+
+  if (dir === 1) { // find next allowed date, starting from currently selected date
+    for (i = 0; i < this.allowedDates.length; i++) {
+      date = this.allowedDates[i];
+      if (scout.dates.compare(now, date) < 0) {
+        return date;
+      }
+    }
+  } else if (dir === -1) { // find previous allowed date, starting from currently selected date
+    for (i = this.allowedDates.length - 1; i >= 0; i--) {
+      date = this.allowedDates[i];
+      if (scout.dates.compare(now, date) > 0) {
+        return date;
+      }
+    }
+  }
+
+  return null;
+};
+
 scout.DatePicker.prototype._build$DateBox = function() {
   var cl, i, now = new Date();
-  var day, dayInMonth, $day;
+  var day, dayEnabled, dayInMonth, $day;
   var weekdays = this.dateFormat.symbols.weekdaysShortOrdered;
   var start = new Date(this.viewDate);
 
@@ -245,16 +288,39 @@
       cl += ' date-picker-selected';
     }
 
+    dayEnabled = this._isDateAllowed(start);
+    if (!dayEnabled) {
+      cl += ' date-picker-disabled';
+    }
+
     day = (dayInMonth <= 9 ? '0' + dayInMonth : dayInMonth);
     $day = $box
       .appendDiv('date-picker-day' + cl, day)
       .data('dayInMonth', dayInMonth)
       .data('date', new Date(start));
+
+    if (dayEnabled) {
+      $day.on('click', this._onDayClick.bind(this));
+    }
   }
 
   return $box;
 };
 
+scout.DatePicker.prototype._isDateAllowed = function(date) {
+  // when allowedDates is empty or not set, any date is allowed
+  if (!this.allowedDates || this.allowedDates.length === 0) {
+    return true;
+  }
+  // when allowedDates is set, only dates contained in this array are allowed
+  var allowedDateAsTimestamp,
+    dateAsTimestamp = date.getTime();
+  return this.allowedDates.some(function(allowedDate) {
+    allowedDateAsTimestamp = allowedDate.getTime();
+    return allowedDateAsTimestamp === dateAsTimestamp;
+  });
+};
+
 scout.DatePicker.prototype._append$Header = function() {
   var headerHtml =
     '<div class="date-picker-header">' +
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerPopup.js
index caf15a6..6b785f3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerPopup.js
@@ -20,7 +20,8 @@
 
   this.picker = scout.create('DatePicker', {
     parent: this,
-    dateFormat: options.dateFormat
+    dateFormat: options.dateFormat,
+    allowedDates: options.allowedDates
   });
 };
 
@@ -30,20 +31,7 @@
   this.$container
     .addClass('date-picker-popup');
   this.htmlComp = this.picker.htmlComp;
-};
-
-/**
- * @override Popup.js
- */
-scout.DatePickerPopup.prototype._onMouseDown = function(event) {
-  // when user clicks on DateField input-field, cannot prevent default
-  // because text-selection would not work anymore
-  if (this.$anchor.isOrHas(event.target)) {
-    return;
-  }
-
-  // or else: clicked somewhere else on the document -> close
-  scout.DatePickerPopup.parent.prototype._onMouseDown.call(this, event);
+  this.htmlComp.validateRoot = true;
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerTouchPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerTouchPopup.js
index 4ad7395..79d53be 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerTouchPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/datepicker/DatePickerTouchPopup.js
@@ -13,6 +13,11 @@
 };
 scout.inherits(scout.DatePickerTouchPopup, scout.TouchPopup);
 
+scout.DatePickerTouchPopup.prototype._init = function(options) {
+  scout.DatePickerTouchPopup.parent.prototype._init.call(this, options);
+  this._field.on('displayTextChanged', this._onFieldDisplayTextChanged.bind(this));
+};
+
 /**
  * @override TouchPopup.js
  */
@@ -21,22 +26,6 @@
     parent: this,
     dateFormat: options.dateFormat
   });
-
-  this._field._attachDatePickerDateSelectedHandler();
-};
-
-/**
- * @override Popup.js
- */
-scout.DatePickerTouchPopup.prototype._onMouseDown = function(event) {
-  // when user clicks on DateField input-field, cannot prevent default
-  // because text-selection would not work anymore
-  if (this.$anchor.isOrHas(event.target)) {
-    return;
-  }
-
-  // or else: clicked somewhere else on the document -> close
-  scout.DatePickerTouchPopup.parent.prototype._onMouseDown.call(this, event);
 };
 
 /**
@@ -45,3 +34,10 @@
 scout.DatePickerTouchPopup.prototype.getDatePicker = function() {
   return this._widget;
 };
+
+scout.DatePickerTouchPopup.prototype._onFieldDisplayTextChanged = function(event) {
+  // Delegate to original field
+  this._touchField.dateDisplayText = this._field.dateDisplayText;
+  this._touchField.timeDisplayText = this._field.timeDisplayText;
+  this._touchField.setDisplayText(event.displayText);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/BaseDesktop.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/BaseDesktop.js
deleted file mode 100644
index 766b6bf..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/BaseDesktop.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.BaseDesktop = function() {
-  scout.BaseDesktop.parent.call(this);
-  this.offline = false;
-  this.notifications = [];
-};
-scout.inherits(scout.BaseDesktop, scout.ModelAdapter);
-
-scout.BaseDesktop.prototype._renderProperties = function() {
-  scout.BaseDesktop.parent.prototype._renderProperties.call(this);
-  this._renderTitle(this.title);
-};
-
-scout.BaseDesktop.prototype._renderTitle = function(title) {
-  if (title === undefined || title === null) {
-    return;
-  }
-  var $scoutDivs = $('div.scout');
-  if ($scoutDivs.length <= 1) { // only set document title in non-portlet case
-    $scoutDivs.document(true).title = title;
-  }
-};
-
-scout.BaseDesktop.prototype.addNotification = function(notification) {
-  if (!notification) {
-    return;
-  }
-  this.notifications.push(notification);
-  if (this.$notifications) {
-    // Bring to front
-    this.$notifications.appendTo(this.$container);
-  } else {
-    this.$notifications = this.$container.appendDiv('notifications');
-  }
-  notification.fadeIn(this.$notifications);
-};
-
-/**
- * Removes the given notification.
- * @param notification Either an instance of scout.DesktopNavigation or a String containing an ID of a notification instance.
- */
-scout.BaseDesktop.prototype.removeNotification = function(notification) {
-  if (typeof notification === 'string') {
-    var notificationId = notification;
-    notification = scout.arrays.find(this.notifications, function(n) {
-      return notificationId === n.id;
-    });
-  }
-  if (!notification) {
-    return;
-  }
-  if (this.$notifications) {
-    notification.fadeOut(this._onNotificationRemoved.bind(this, notification));
-  } else {
-    scout.arrays.remove(this.notifications, notification);
-  }
-};
-
-scout.BaseDesktop.prototype._onNotificationRemoved = function(notification) {
-  scout.arrays.remove(this.notifications, notification);
-  if (this.notifications.length === 0) {
-    this.$notifications.remove();
-    this.$notifications = null;
-  }
-};
-
-scout.BaseDesktop.prototype._goOffline = function() {
-  if (this.offline) {
-    return;
-  }
-  this.offline = true;
-  this._offlineNotification = scout.create('DesktopNotification.Offline', {
-    parent: this,
-    closeable: false,
-    duration: scout.DesktopNotification.INFINITE,
-    status: {
-      message: this.session.text('ui.ConnectionInterrupted'),
-      severity: scout.Status.Severity.ERROR
-    }
-  });
-  this._offlineNotification.show();
-};
-
-scout.BaseDesktop.prototype._goOnline = function() {
-  if (!this._hideOfflineMessagePending) {
-    this.hideOfflineMessage();
-  }
-};
-
-scout.BaseDesktop.prototype.hideOfflineMessage = function() {
-  this._hideOfflineMessagePending = false;
-  this.removeNotification(this._offlineNotification);
-  this._offlineNotification = null;
-};
-
-scout.BaseDesktop.prototype.onReconnecting = function() {
-  if (!this.offline) {
-    return;
-  }
-  this._offlineNotification.reconnect();
-};
-
-scout.BaseDesktop.prototype.onReconnectingSucceeded = function() {
-  if (!this.offline) {
-    return;
-  }
-  this.offline = false;
-  this._offlineNotification.reconnectSucceeded();
-  this._hideOfflineMessagePending = true;
-  setTimeout(this.hideOfflineMessage.bind(this), 3000);
-};
-
-scout.BaseDesktop.prototype.onReconnectingFailed = function() {
-  if (!this.offline) {
-    return;
-  }
-  this._offlineNotification.reconnectFailed();
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.css
index a72f23b..466cf23 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.css
@@ -8,15 +8,6 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-@desktop-table-header-padding-y: @table-header-padding-y + 5;
-@desktop-table-row-padding-y: @table-row-padding-y + 5;
-@desktop-table-header-padding-x: @bench-padding-x - @table-header-padding-left;
-@desktop-table-data-padding-x: @bench-padding-x - @table-cell-padding-left;
-@desktop-table-header-menubar-padding-right: 10px;
-@taskbar-menu-textandicon-padding-right: 11px;
-
-/* desktop */
-
 .desktop {
   position: absolute;
   top: 0;
@@ -27,386 +18,8 @@
   &:focus {
     outline: none;
   }
-
-  &.has-navigation {
-    & > .desktop-bench,
-    & > .desktop-taskbar {
-      left: @size-desktop-navigation;
-    }
-  }
 }
 
-/* bench */
-
-.desktop-bench-drop-shadow() {
-  position: absolute;
-  content: '';
-  left: 0;
-  top: 3px;
-  width: 10px;
-  height: 100%;
-  box-shadow: -10px 0px 10px 0px rgba(0,0,0,0.4);
-}
-
-.desktop-bench {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background-color: @background-color;
-
-  &.drop-shadow::before {
-    .desktop-bench-drop-shadow();
-  }
-
-  &.has-taskbar {
-    top: @desktop-taskbar-height;
-  }
-
-  & > .table {
-
-    & > .table-header {
-      padding-left: @desktop-table-header-padding-x;
-      padding-right: @desktop-table-header-padding-x;
-
-      & > .table-header-item {
-        padding-top: @desktop-table-header-padding-y;
-        padding-bottom: @desktop-table-header-padding-y;
-
-        & > .table-header-item-state {
-          top: 9px;
-        }
-      }
-
-      & > .menubar-container {
-        padding-left: 6px;
-        padding-right: @desktop-table-header-menubar-padding-right;
-
-        & > .menubar > .menubox > .menu-item {
-          margin-right: 12px;
-        }
-      }
-    }
-
-    & > .table-data {
-      padding-left: @desktop-table-data-padding-x;
-      padding-right: @desktop-table-data-padding-x;
-    }
-
-    & .table-aggregate {
-      margin-left: @bench-padding-x;
-      margin-right: @bench-padding-x;
-
-      & > .table-cell {
-        padding-top: @desktop-table-row-padding-y;
-        padding-bottom: @desktop-table-row-padding-y;
-      }
-    }
-
-    & > .table-data {
-      & > .scrollbar.x-axis {
-        margin-top: 2px;
-        margin-bottom: 2px;
-      }
-
-      & > .table-row,
-      & > .table-aggregate-row {
-        /* Desktop table has a 2px border. Top and bottom border are added to the table cell. */
-        border-left-width: 2px;
-        border-right-width: 2px;
-
-        &.selected {
-          background-color: @item-selection-background-color;
-          border-color: @item-selection-border-color;
-        }
-
-        & > .table-cell {
-          /* Replace first and last pixel of specified row padding by a transparent border. This border will be */
-          /* set to the selection color when the row is selected, thus creating the illusion that the 2px selection */
-          /* border is drawn around the cell. See CSS rules below. */
-          padding-top: @desktop-table-row-padding-y - 1px;
-          padding-bottom: @desktop-table-row-padding-y - 1px;
-          border-top: 1px solid transparent;
-          border-bottom: 1px solid transparent;
-
-          &.checkable {
-            padding-top: @desktop-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
-            padding-bottom: @desktop-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
-          }
-        }
-
-        &.select-top > .table-cell {
-          border-top-color: @item-selection-border-color;
-        }
-
-        &.select-bottom > .table-cell {
-          border-bottom-color: @item-selection-border-color;
-        }
-
-        &.select-single > .table-cell {
-          border-top-color: @item-selection-border-color;
-          border-bottom-color: @item-selection-border-color;
-        }
-      }
-
-      & > .cell-editor-popup > .check-box-field > .cell-editor-field {
-        padding-top: @desktop-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
-      }
-    }
-  }
-}
-
-/* taskbar */
-
-.desktop-taskbar {
-  position: absolute;
-  left: 0;
-  top: 0;
-  right: 0;
-  height: @desktop-taskbar-height;
-  background-color: @desktop-taskbar-background-color;
-  #scout.vertical-align-helper-after();
-
-  /* Has the same effect as "border-bottom: 1px solid @border-color", but is over-drawable by child */
-  /* elements (such as the selected view-tab). The border would not be, because of "overflow: hidden". */
-  &::before {
-    content: '';
-    background-color: @border-color;
-    width: 100%;
-    height: 1px;
-    position: absolute;
-    top: calc(~'100% - 1px');
-    left: 0;
-  }
-}
-
-/* taskbar: view-tabs */
-
-.desktop-view-tabs {
-  position: absolute;
-  top: 0;
-  height: 100%;
-
-  & > .overflow-tab-item {
-    border-right: 1px solid @border-color;
-    display: inline-block;
-    height: 50px;
-    width: 30px;
-    padding-top: 17px;
-    text-align: center;
-    cursor: pointer;
-    vertical-align: top;
-
-    &::before {
-      #scout.font-icon();
-      color: @icon-color;
-      content: @icon-chevron-right;
-    }
-
-    & .num-tabs {
-      color: @disabled-color;
-      font-size: 10px;
-      margin-top: -4px;
-    }
-
-    &.modality-highlight {
-      #scout.animation-flash-gray();
-    }
-  }
-}
-
-.desktop-view-tab {
-  position: relative;
-  display: inline-block;
-  /* 1px smaller than the taskbar because of the bottom border (see .selected rule below) */
-  height: calc(~'100% - 1px');
-  vertical-align: top;
-  width: 220px;
-  padding: 6px 10px 0 20px;
-  cursor: pointer;
-  background-color: @view-tab-background-color;
-  color: @text-color;
-  border-right: 1px solid @border-color;
-  transition: background-color 200ms linear;
-
-  &.small {
-    width: 130px;
-  }
-
-  &:hover {
-    color: @hover-color;
-  }
-
-  &.disabled {
-    color: @disabled-color;
-    cursor: default;
-  }
-
-  &.selected {
-    cursor: default;
-    background-color: @view-tab-active-background-color;
-    color: @view-tab-active-color;
-    /* full size of taskbar to draw over the border-bottom */
-    height: 100%;
-    transition: off;
-
-    &::before {
-      .desktop-bench-drop-shadow();
-      top: 0px;
-      width: 20px;
-      height: 110%;
-    }
-
-    &:not(:first-child)::before {
-      box-shadow: -7px 0px 10px 0px rgba(0,0,0,0.4);
-    }
-  }
-
-/*  &.modality-highlight > .title,
-  &.modality-highlight > .sub-title {
-    #scout.animation-shake();
-  }*/
-
-  &.modality-highlight {
-    #scout.animation-flash-gray();
-  }
-
-  & > .icon {
-    float: right;
-    margin-left: 5px;
-    margin-right: -5px;
-  }
-
-  & > .title {
-    #scout.overflow-ellipsis-nowrap();
-    #scout.font-text-large();
-  }
-
-  & > .sub-title {
-    #scout.overflow-ellipsis-nowrap();
-    #scout.font-text-normal();
-  }
-}
-
-/* taskbar: tools */
-
-.taskbar-tools {
-  position: absolute;
-  top: 0;
-  white-space: nowrap;
-}
-
-.taskbar-tool-item.menu-item {
-  position: relative;
-  height: @desktop-taskbar-height - 1px;
-  color: @text-color;
-  #scout.font-text-plus();
-  border-left: 1px solid transparent;
-  border-right: 1px solid transparent;
-  margin-left: 20px;
-  margin-right: 20px;
-
-  &:hover {
-    color: @hover-color;
-  }
-
-  &.disabled {
-    color: @disabled-color;
-    cursor: default;
-  }
-
-  &.compact {
-    margin-left: 4px;
-    margin-right: 4px;
-  }
-
-  & > .font-icon {
-    color: @icon-color;
-    font-size: 17px;
-  }
-
-  &:hover > .font-icon {
-    color: @hover-color;
-  }
-
-  &.disabled > .font-icon {
-    color: @disabled-color;
-  }
-
-  &.menu-textandicon > .icon {
-    padding-right: @taskbar-menu-textandicon-padding-right;
-  }
-}
-
-/* taskbar: tools popup */
-
-.taskbar-tool-item.popup-head {
-  height: @desktop-taskbar-height - 1px;
-  border-left: 1px solid @border-color;
-  border-right: 1px solid @border-color;
-  background-color: @background-color;
-  cursor: pointer;
-  /*padding: 16px 20px 0 20px;*/
-  box-shadow: none;
-  border-top: none;
-  /*line-height: normal;*/
-  //#scout.vertical-align-helper-before();
-  /* OVERRIDE .taskbar-tool-item.menu-item */
-  margin-left: 0;
-  margin-right: 0;
-  position: absolute;
-
-  .popup.down > & {
-    /* above selector is too less specific */
-    padding-top: 0;
-  }
-
-  &.selected > .font-icon {
-    font-size: 17px;
-    /*vertical-align: 0;*/
-  }
-}
-
-.popup.form-tool-popup {
-  & > .popup-body {
-    border-bottom: 1px solid @border-color;
-  }
-
-  & > .popup-deco {
-    background-color: @background-color;
-  }
-}
-
-/* taskbar: key boxes */
-
-.desktop-view-tab .key-box,
-.taskbar-tool-item.menu-item .key-box {
-  bottom: 4px;
-
-  &.disabled {
-    background-color: @disabled-color;
-  }
-}
-
-/* taskbar: logo */
-
-.taskbar-logo {
-  position: absolute;
-  right: 0;
-  top: 0;
-  margin-top: 8px;
-  margin-left: 20px;
-  margin-right: @bench-padding-x;
-  width: 33px;
-  height: 33px;
-  background: url('taskbar-logo.png');
-  background-size: contain;
-  background-repeat: no-repeat;
-}
-
-/* other elements of the desktop */
-
 .glasspane {
   position: absolute;
   top: 0;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.js
index a2f2888..945bb67 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/Desktop.js
@@ -11,268 +11,213 @@
 scout.Desktop = function() {
   scout.Desktop.parent.call(this);
 
-  this._$viewTabBar;
-  this._$taskBar; // FIXME awe: uniform naming
-  this._$toolBar; // FIXME awe: uniform naming
-  this.$bench;
-
   this.navigation;
-  /**
-   * outline-content = outline form or table
-   */
-  this._outlineContent;
-
-  /**
-   * FIXME dwi: (activeForm): selected tool form action wird nun auch als 'activeForm' verwendet (siehe TableKeystrokeContext.js)
-   * Wahrscheinlich müssen wir das refactoren und eine activeForm property verwenden.  Diese Property muss
-   * mit dem Server synchronisiert werden, damit auch das server-seitige desktop.getActiveForm() stimmt.
-   * Auch im zusammenhang mit focus-handling nochmals überdenken.
-   */
-  this._addAdapterProperties(['viewButtons', 'actions', 'views', 'dialogs', 'outline', 'messageBoxes', 'fileChoosers', 'addOns', 'keyStrokes']);
-
-  this.viewTabsController;
+  this.header;
+  this.bench;
+  this.splitter;
   this.formController;
   this.messageBoxController;
   this.fileChooserController;
-  this.benchVisible = true;
   this.initialFormRendering = false;
+  this.offline = false;
+  this.notifications = [];
+  this.inBackground = false;
+  this._addAdapterProperties(['viewButtons', 'menus', 'views', 'dialogs', 'outline', 'messageBoxes', 'fileChoosers', 'addOns', 'keyStrokes']);
+
+  // event listeners
+  this._benchActiveViewChangedHandler = this._onBenchActivateViewChanged.bind(this);
 };
-scout.inherits(scout.Desktop, scout.BaseDesktop);
+scout.inherits(scout.Desktop, scout.ModelAdapter);
+
+scout.Desktop.DisplayStyle = {
+  DEFAULT: 'default',
+  BENCH: 'bench',
+  COMPACT: 'compact'
+};
 
 scout.Desktop.prototype._init = function(model) {
   scout.Desktop.parent.prototype._init.call(this, model);
-  this.viewTabsController = new scout.ViewTabsController(this);
   this.formController = new scout.DesktopFormController(this, this.session);
   this.messageBoxController = new scout.MessageBoxController(this, this.session);
   this.fileChooserController = new scout.FileChooserController(this, this.session);
-  this._addNullOutline(model.outline);
+  this._resizeHandler = this.onResize.bind(this);
+  this._popstateHandler = this.onPopstate.bind(this);
+  this.updateSplitterVisibility();
+  this._syncViewButtons(this.viewButtons);
+  this._syncMenus(this.menus);
 };
 
-scout.DesktopStyle = {
-  DEFAULT: 'DEFAULT',
-  BENCH: 'BENCH'
+scout.Desktop.prototype._initKeyStrokeContext = function(keyStrokeContext) {
+  scout.Desktop.parent.prototype._initKeyStrokeContext.call(this, keyStrokeContext);
+
+  // Keystroke on the top-level DOM element which works as a catch-all when the busy indicator is active
+  keyStrokeContext.registerKeyStroke(new scout.DesktopKeyStroke(this.session));
+  keyStrokeContext.registerKeyStroke(new scout.DesktopTabSelectKeyStroke(this));
+  keyStrokeContext.registerKeyStroke(new scout.DisableBrowserTabSwitchingKeyStroke(this));
 };
 
 scout.Desktop.prototype._onChildAdapterCreation = function(propertyName, model) {
   if (propertyName === 'viewButtons') {
     model.desktop = this;
-  } else if (propertyName === 'actions') {
+  } else if (propertyName === 'menus') {
     model.desktop = this;
   }
 };
 
+scout.Desktop.prototype._onBenchActivateViewChanged = function(event) {
+  if (this.initialFormRendering) {
+    return;
+  }
+  var view = event.view;
+  if (this.bench.outlineContent !== view && !view.detailForm) {
+    // Notify model that this form is active (only for regular views, not detail forms)
+    this._setFormActivated(view);
+  }
+};
+
 scout.Desktop.prototype._render = function($parent) {
-  var hasNavigation = this._hasNavigation();
-
   this.$container = $parent;
-  this.$container
-    .addClass('desktop')
-    .toggleClass('has-navigation', hasNavigation);
+  this.$container.addClass('desktop');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.DesktopLayout(this));
+  scout.inspector.applyInfo(this, this.$container);
 
-  scout.inspector.applyInfo(this, $parent);
+  // Desktop elements are added before this separator, all overlays are opened after (dialogs, popups, tooltips etc.)
+  this.$overlaySeparator = this.$container.appendDiv().setVisible(false);
 
-  this.navigation = hasNavigation ? new scout.DesktopNavigation(this) : scout.NullDesktopNavigation;
-  this.navigation.render($parent);
-  //TODO [5.2] cgu: maybe better move to desktop navigation?
-  this._installKeyStrokeContextForDesktopViewButtonBar();
-  this._installKeyStrokeContextForDesktop();
-
-  this._renderTaskBar($parent);
-  this._renderBench();
-  // render ToolMenus after bench because menus are a part of the taskbar and main structure with all elements
-  //on desktop should be rendered before fill them. Otherwise there are problems with Popups.
-  this._renderToolMenus();
-  this._createSplitter($parent);
-  this._setSplitterPosition();
-  // TODO [5.2] awe, bsh: Maybe remove this? Addon functionality may be provided by using an own desktop.
+  this._renderNavigationVisible();
+  this._renderHeaderVisible();
+  this._renderBenchVisible();
+  this._renderTitle();
+  this._renderLogoUrl();
+  this._renderSplitterVisible();
+  this._renderInBackground();
+  this._renderDisplayStyle();
   this.addOns.forEach(function(addOn) {
-    addOn.render($parent);
-  });
-  this.navigation.onOutlineChanged(this.outline, true);
+    addOn.render(this.$container);
+  }, this);
 
-  $parent.window().on('resize', this.onResize.bind(this));
+  this.$container.window()
+    .on('resize', this._resizeHandler)
+    .on('popstate', this._popstateHandler);
 
   // prevent general drag and drop, dropping a file anywhere in the application must not open this file in browser
   this._setupDragAndDrop();
 
-  this._disableContextMenu($parent);
+  this._disableContextMenu();
 };
 
-scout.Desktop.prototype._disableContextMenu = function($parent) {
-  // Switch off browser's default context menu for the entire scout desktop (except input fields)
-  $parent.on('contextmenu', function(event) {
-    if (event.target.nodeName !== 'INPUT' && event.target.nodeName !== 'TEXTAREA' && !event.target.isContentEditable) {
-      event.preventDefault();
-    }
-  });
-};
-
-/**
- * goes up in display hierarchy to find the form to select on desktop. null if outline is selected.
- * @param form
- * @returns
- */
-scout.Desktop.prototype._findActiveSelectablePart = function(form) {
-  if (form.parent.isView && form.parent.isDialog) {
-    if (form.parent.isView()) {
-      return form.parent;
-    } else if (form.parent.isDialog()) {
-      return this._findActiveSelectablePart(form.parent);
-    }
-  }
-  return null;
-};
-
-/**
- * Installs the keystrokes referring to the desktop bench, and are keystrokes declared on desktop (desktop.keyStrokes).
- */
-scout.Desktop.prototype._installKeyStrokeContextForDesktopBench = function() {
-  if (!this._hasBench()) {
-    return;
-  }
-  var keyStrokeContext = new scout.KeyStrokeContext();
-
-  keyStrokeContext.invokeAcceptInputOnActiveValueField = true;
-  keyStrokeContext.$bindTarget = this.session.$entryPoint;
-  keyStrokeContext.$scopeTarget = this.$bench;
-  keyStrokeContext.registerKeyStroke(this.keyStrokes);
-
-  this.session.keyStrokeManager.installKeyStrokeContext(keyStrokeContext);
-};
-
-/**
- * Install a keystroke on the top-level DOM element which works as a catch-all when the busy indicator is active.
- */
-scout.Desktop.prototype._installKeyStrokeContextForDesktop = function() {
-  var keyStrokeContext = new scout.KeyStrokeContext();
-
-  keyStrokeContext.$bindTarget = this.session.$entryPoint;
-  keyStrokeContext.$scopeTarget = this.$container;
-  keyStrokeContext.registerKeyStroke(new scout.DesktopKeyStroke(this.session));
-
-  this.session.keyStrokeManager.installKeyStrokeContext(keyStrokeContext);
-};
-
-/**
- * Installs the keystrokes referring to the desktop view button area, and are keystrokes to switch between outlines (desktop.viewButtons).
- */
-scout.Desktop.prototype._installKeyStrokeContextForDesktopViewButtonBar = function() {
-  if (!this._hasNavigation()) {
-    return;
-  }
-  var keyStrokeContext = new scout.KeyStrokeContext();
-
-  keyStrokeContext.invokeAcceptInputOnActiveValueField = true;
-  keyStrokeContext.$bindTarget = this.session.$entryPoint;
-  keyStrokeContext.$scopeTarget = this.navigation.$viewButtons;
-  keyStrokeContext.registerKeyStroke([
-    new scout.ViewMenuOpenKeyStroke(this.navigation)
-  ].concat(this.viewButtons));
-
-  this.session.keyStrokeManager.installKeyStrokeContext(keyStrokeContext);
-};
-
-/**
- * Installs the keystrokes referring to the desktop task bar, and are keystrokes associated with FormToolButtons (desktop.actions).
- */
-scout.Desktop.prototype._installKeyStrokeContextForDesktopTaskBar = function() {
-  if (!this._hasTaskBar()) {
-    return;
-  }
-  var keyStrokeContext = new scout.KeyStrokeContext();
-
-  keyStrokeContext.invokeAcceptInputOnActiveValueField = true;
-  keyStrokeContext.$bindTarget = this.session.$entryPoint;
-  keyStrokeContext.$scopeTarget = this._$taskBar;
-  keyStrokeContext.registerKeyStroke([
-    new scout.ViewTabSelectKeyStroke(this),
-    new scout.DisableBrowserTabSwitchingKeyStroke(this)
-  ].concat(this.actions));
-
-  this.session.keyStrokeManager.installKeyStrokeContext(keyStrokeContext);
+scout.Desktop.prototype._remove = function() {
+  this.formController.remove();
+  this.messageBoxController.remove();
+  this.fileChooserController.remove();
+  this.$container.window()
+    .off('resize', this._resizeHandler)
+    .off('popstate', this._popstateHandler);
+  scout.Desktop.parent.prototype._remove.call(this);
 };
 
 scout.Desktop.prototype._postRender = function() {
-  // keystroke is not handled by default keystrokecontext.
-  this.session.keyStrokeManager.uninstallKeyStrokeContext(this.keyStrokeContext);
-
   // Render attached forms, message boxes and file choosers.
   this.initialFormRendering = true;
   this.formController.render();
   this.messageBoxController.render();
   this.fileChooserController.render();
-  // Align a potential open popup to its respective tool button.
-  this.actions
-    .filter(function(action) {
-      return action.selected && action.popup;
-    })
-    .some(function(action) {
-      action.popup.position();
-      return true;
-    });
+  this._renderDisplayChildsOfOutline();
 
-  // find active form and set selected.
-  var selectable;
-  if (this.activeForm) {
-    var form = this.session.getModelAdapter(this.activeForm);
-    if (form.isDialog()) {
-      // find ui selectable part
-      selectable = this._findActiveSelectablePart(form);
-    } else if (form.isView()) {
-      selectable = form;
-    }
-  }
-  if (!selectable) {
-    this.bringOutlineToFront(this.outline);
-  } else {
-    this.viewTabsController.selectViewTab(this.viewTabsController.viewTab(selectable));
-  }
   this.initialFormRendering = false;
-  this._layoutTaskBar();
 };
 
-scout.Desktop.prototype._renderActiveForm = function($parent) {
-  // NOP -> is handled in _setFormActivated when ui changes active form or if model changes form in _onModelFormShow/_onModelFormActivate
+scout.Desktop.prototype._renderDisplayStyle = function() {
+  var DisplayStyle = scout.Desktop.DisplayStyle,
+    isCompact = this.displayStyle === DisplayStyle.COMPACT;
+
+  if (this.header) {
+    this.header.setToolBoxVisible(!isCompact);
+    this.header.animateRemoval = isCompact;
+  }
+  if (this.navigation) {
+    this.navigation.setToolBoxVisible(isCompact);
+    this.navigation.htmlComp.layoutData.fullWidth = isCompact;
+  }
+  if (this.bench) {
+    this.bench.setOutlineContentVisible(!isCompact);
+  }
+  if (this.outline) {
+    this.outline.setCompact(isCompact);
+    this.outline.setEmbedDetailContent(isCompact);
+  }
+
+  this.invalidateLayoutTree();
 };
 
-scout.Desktop.prototype._renderToolMenus = function() {
-  if (!this._hasTaskBar()) {
+/**
+ * Displays attached forms, message boxes and file choosers.
+ * Outline does not need to be rendered to show the child elements, it needs to be active (necessary if navigation is invisible)
+ */
+scout.Desktop.prototype._renderDisplayChildsOfOutline = function() {
+  if (!this.outline) {
     return;
   }
+  this.outline.formController.render();
+  this.outline.messageBoxController.render();
+  this.outline.fileChooserController.render();
+};
 
-  // we set the menuStyle property to render a menu with a different style
-  // depending on where the menu is located (taskbar VS menubar).
-  this.actions.forEach(function(action) {
-    action._customCssClasses = "taskbar-tool-item";
-    action.popupOpeningDirectionX = 'left';
-    action.render(this._$toolBar);
-  }.bind(this));
-
-  if (this.actions.length) {
-    this.actions[this.actions.length - 1].$container.addClass('last');
+scout.Desktop.prototype._removeDisplayChildsOfOutline = function() {
+  if (!this.outline) {
+    return;
   }
+  this.outline.formController.remove();
+  this.outline.messageBoxController.remove();
+  this.outline.fileChooserController.remove();
+};
+
+scout.Desktop.prototype._renderTitle = function() {
+  var title = this.title;
+  if (title === undefined || title === null) {
+    return;
+  }
+  var $scoutDivs = $('div.scout');
+  if ($scoutDivs.length <= 1) { // only set document title in non-portlet case
+    $scoutDivs.document(true).title = title;
+  }
+};
+
+scout.Desktop.prototype._renderActiveForm = function() {
+  // NOP -> is handled in _setFormActivated when ui changes active form or if model changes form in _onFormShow/_onFormActivate
 };
 
 scout.Desktop.prototype._renderBench = function() {
-  if (!this._hasBench()) {
+  if (this.bench) {
     return;
   }
-  this.$bench = this.$container.appendDiv('desktop-bench');
-  this.$bench.toggleClass('has-taskbar', this._hasTaskBar());
-  new scout.HtmlComponent(this.$bench, this.session);
-
-  this._installKeyStrokeContextForDesktopBench();
+  this.bench = scout.create('DesktopBench', {
+    parent: this,
+    animateRemoval: true,
+    headerTabArea: this.header ? this.header.tabArea : undefined,
+    outlineContentVisible: this.displayStyle !== scout.Desktop.DisplayStyle.COMPACT
+  });
+  this.bench.on('viewActivated', this._benchActiveViewChangedHandler);
+  this.bench.render(this.$container);
+  this.bench.$container.insertBefore(this.$overlaySeparator);
+  this.invalidateLayoutTree();
 };
 
 scout.Desktop.prototype._removeBench = function() {
-  if (!this.$bench) {
+  if (!this.bench) {
     return;
   }
-  this.$bench.remove();
-  this.$bench = null;
+  this.bench.off('viewActivated', this._benchActiveViewChangedHandler);
+  this.bench.on('remove', function() {
+    this.bench = null;
+    this.invalidateLayoutTree();
+  }.bind(this));
+  this.bench.remove();
 };
 
 scout.Desktop.prototype._renderBenchVisible = function() {
+  this.animateLayoutChange = this.rendered;
   if (this.benchVisible) {
     this._renderBench();
   } else {
@@ -280,28 +225,133 @@
   }
 };
 
-scout.Desktop.prototype._renderTaskBar = function($parent) {
-  if (!this._hasTaskBar()) {
+scout.Desktop.prototype._renderNavigation = function() {
+  if (this.navigation) {
     return;
   }
-  this._$taskBar = $parent.appendDiv('desktop-taskbar');
-  var htmlTabbar = new scout.HtmlComponent(this._$taskBar, this.session);
-  htmlTabbar.setLayout(new scout.DesktopTabBarLayout(this));
-  this._$viewTabBar = this._$taskBar.appendDiv('desktop-view-tabs');
-  this._$toolBar = this._$taskBar.appendDiv('taskbar-tools');
-  if (this.session.uiUseTaskbarLogo) {
-    this._$taskBarLogo = this._$taskBar.appendDiv('taskbar-logo');
+  this.navigation = scout.create('DesktopNavigation', {
+    parent: this,
+    outline: this.outline,
+    toolBoxVisible: this.displayStyle === scout.Desktop.DisplayStyle.COMPACT,
+    layoutData: {
+      fullWidth: this.displayStyle === scout.Desktop.DisplayStyle.COMPACT
+    }
+  });
+  this.navigation.render(this.$container);
+  this.navigation.$container.prependTo(this.$container);
+  this.invalidateLayoutTree();
+};
 
-    // in memory of the first one...
-    this._$taskBarLogo.dblclick(function(event) {
-      if (event.altKey && event.ctrlKey) {
-        $(event.target).css('background', 'none');
-        $(event.target).css('font-size', '9px');
-        $(event.target).text('make software not war');
-      }
-    });
+scout.Desktop.prototype._removeNavigation = function() {
+  if (!this.navigation) {
+    return;
   }
-  this._installKeyStrokeContextForDesktopTaskBar();
+  this.navigation.remove();
+  this.navigation = null;
+  this.invalidateLayoutTree();
+};
+
+scout.Desktop.prototype._renderNavigationVisible = function() {
+  this.animateLayoutChange = this.rendered;
+  if (this.navigationVisible) {
+    this._renderNavigation();
+  } else {
+    if (!this.animateLayoutChange) {
+      this._removeNavigation();
+    } else {
+      // re layout to trigger animation
+      this.invalidateLayoutTree();
+    }
+  }
+};
+
+scout.Desktop.prototype._renderNavigationHandleVisible = function() {
+  // NOP
+};
+
+scout.Desktop.prototype._renderHeader = function() {
+  if (this.header) {
+    return;
+  }
+  this.header = scout.create('DesktopHeader', {
+    parent: this,
+    animateRemoval: this.displayStyle === scout.Desktop.DisplayStyle.COMPACT,
+    toolBoxVisible: this.displayStyle !== scout.Desktop.DisplayStyle.COMPACT
+  });
+  this.header.render(this.$container);
+  this.header.$container.insertBefore(this.$overlaySeparator);
+  this.invalidateLayoutTree();
+};
+
+scout.Desktop.prototype._removeHeader = function() {
+  if (!this.header) {
+    return;
+  }
+  this.header.on('remove', function() {
+    this.invalidateLayoutTree();
+    this.header = null;
+  }.bind(this));
+  this.header.remove();
+};
+
+scout.Desktop.prototype._renderHeaderVisible = function() {
+  if (this.headerVisible) {
+    this._renderHeader();
+  } else {
+    this._removeHeader();
+  }
+};
+
+scout.Desktop.prototype._renderLogoUrl = function() {
+  if (this.header) {
+    this.header.setLogoUrl(this.logoUrl);
+  }
+};
+
+scout.Desktop.prototype._renderSplitterVisible = function() {
+  if (this.splitterVisible) {
+    this._renderSplitter();
+  } else {
+    this._removeSplitter();
+  }
+};
+
+scout.Desktop.prototype._renderSplitter = function() {
+  if (this.splitter || !this.navigation) {
+    return;
+  }
+  this.splitter = scout.create('Splitter', {
+    parent: this,
+    $anchor: this.navigation.$container,
+    $root: this.$container
+  });
+  this.splitter.render(this.$container);
+  this.splitter.$container.insertBefore(this.$overlaySeparator);
+  this.splitter.on('move', this._onSplitterMove.bind(this));
+  this.splitter.on('moveEnd', this._onSplitterMoveEnd.bind(this));
+  this.updateSplitterPosition();
+};
+
+scout.Desktop.prototype._removeSplitter = function() {
+  if (!this.splitter) {
+    return;
+  }
+  this.splitter.remove();
+  this.splitter = null;
+};
+
+scout.Desktop.prototype._renderInBackground = function() {
+  if (this.navigationVisible && this.benchVisible) {
+    this.bench.$container.toggleClass('drop-shadow', this.inBackground);
+  }
+};
+
+scout.Desktop.prototype._renderBrowserHistoryEntry = function() {
+  var myWindow = this.$container.window(true),
+    history = this.browserHistoryEntry;
+  myWindow.history.pushState({
+    deepLinkPath: history.deepLinkPath
+  }, history.title, history.path);
 };
 
 scout.Desktop.prototype._setupDragAndDrop = function() {
@@ -320,23 +370,23 @@
   });
 };
 
-scout.Desktop.prototype._createSplitter = function($parent) {
-  if (!this._hasNavigation()) {
-    return;
-  }
-  this.splitter = scout.create('Splitter', {
-    parent: this,
-    $anchor: this.navigation.$navigation,
-    $root: this.$container,
-    maxRatio: 0.5
-  });
-  this.splitter.render($parent);
-  this.splitter.on('resize', this._onSplitterResize.bind(this));
-  this.splitter.on('resizeend', this._onSplitterResizeEnd.bind(this));
+scout.Desktop.prototype.updateSplitterVisibility = function() {
+  // Splitter should only be visible if navigation and bench are visible, but never in compact mode (to prevent unnecessary splitter rendering)
+  this.setSplitterVisible(this.navigationVisible && this.benchVisible && this.displayStyle !== scout.Desktop.DisplayStyle.COMPACT);
 };
 
-scout.Desktop.prototype._setSplitterPosition = function() {
-  if (!this._hasNavigation()) {
+scout.Desktop.prototype.setSplitterVisible = function(visible) {
+  if (this.splitterVisible === visible) {
+    return;
+  }
+  this._setProperty('splitterVisible', visible);
+  if (this.rendered) {
+    this._renderSplitterVisible();
+  }
+};
+
+scout.Desktop.prototype.updateSplitterPosition = function() {
+  if (!this.splitter) {
     return;
   }
   // FIXME awe: (user-prefs) Use user-preferences instead of sessionStorage
@@ -344,291 +394,227 @@
   if (storedSplitterPosition) {
     // Restore splitter position
     var splitterPosition = parseInt(storedSplitterPosition, 10);
-    this.splitter.updatePosition(splitterPosition);
-    this._handleUpdateSplitterPosition(splitterPosition);
+    this.splitter.setPosition(splitterPosition);
+    this.invalidateLayoutTree();
   } else {
-    // Set initial splitter position
-    this.splitter.updatePosition();
-    this._handleUpdateSplitterPosition(this.splitter.position);
+    // Set initial splitter position (default defined by css)
+    this.splitter.setPosition();
+    this.invalidateLayoutTree();
   }
 };
 
-// TODO [5.2] cgu: maybe better change to actual properties and set on server?
-scout.Desktop.prototype._hasNavigation = function() {
-  return this.desktopStyle === scout.DesktopStyle.DEFAULT;
-};
-
-scout.Desktop.prototype._hasTaskBar = function() {
-  return this.desktopStyle === scout.DesktopStyle.DEFAULT;
-};
-
-scout.Desktop.prototype._hasBench = function() {
-  return this.benchVisible;
-};
-
-scout.Desktop.prototype.onResize = function(event) {
-  var selectedViewTab = this.viewTabsController.selectedViewTab();
-  if (selectedViewTab) {
-    selectedViewTab.onResize();
-  }
-  if (this.outline) {
-    this.outline.onResize();
-  }
-  if (this._outlineContent) {
-    this._outlineContent.onResize();
-  }
-  this._layoutTaskBar();
-};
-
-scout.Desktop.prototype._layoutTaskBar = function() {
-  if (this._hasTaskBar()) {
-    var htmlTaskBar = scout.HtmlComponent.get(this._$taskBar);
-    htmlTaskBar.revalidateLayout();
-  }
-};
-
-scout.Desktop.prototype._onSplitterResize = function(event) {
-  this._handleUpdateSplitterPosition(event.data);
-};
-
-scout.Desktop.prototype._onSplitterResizeEnd = function(event) {
-  var splitterPosition = event.data;
-
-  // Store size
-  if (this.cacheSplitterPosition) {
-    sessionStorage.setItem('scout:desktopSplitterPosition', splitterPosition);
-  }
-
-  // Check if splitter is smaller than min size
-  if (splitterPosition < scout.DesktopNavigation.BREADCRUMB_SWITCH_WIDTH) {
-    // Set width of navigation to BREADCRUMB_SWITCH_WIDTH, using an animation.
-    // While animating, update the desktop layout.
-    // At the end of the animation, update the desktop layout, and store the splitter position.
-    this.navigation.$navigation.animate({
-      width: scout.DesktopNavigation.BREADCRUMB_SWITCH_WIDTH
-    }, {
-      progress: function() {
-        this.splitter.updatePosition();
-        this._handleUpdateSplitterPosition(this.splitter.position);
-      }.bind(this),
-      complete: function() {
-        this.splitter.updatePosition();
-        // Store size
-        sessionStorage.setItem('scout:desktopSplitterPosition', this.splitter.position);
-        this._handleUpdateSplitterPosition(this.splitter.position);
-      }.bind(this)
-    });
-  }
-};
-
-scout.Desktop.prototype._handleUpdateSplitterPosition = function(newPosition) {
-  this.navigation.onResize({
-    data: newPosition
-  });
-  this.onResize({
-    data: newPosition
-  });
-};
-
-scout.Desktop.prototype._attachOutlineContent = function() {
-  // Only re-attach content if it was not destroyed in the mean time. Otherweise, re-render it.
-  if (this._outlineContent && this._outlineContent.rendered && !this._outlineContent.destroyed) {
-    this._outlineContent.attach();
-  } else {
-    this.outline.handleOutlineContent();
-  }
-};
-
-scout.Desktop.prototype._detachOutlineContent = function() {
-  if (this._outlineContent) {
-    this._outlineContent.detach();
-  }
-};
-
-/* communication with outline */
-
-scout.Desktop.prototype.setOutlineContent = function(content, bringToFront) {
-  bringToFront = scout.nvl(bringToFront, true);
-  if (this._outlineContent && this._outlineContent !== content) {
-    if (this._outlineContent instanceof scout.Table) {
-      this._outlineContent.storeScrollPosition();
+scout.Desktop.prototype._disableContextMenu = function() {
+  // Switch off browser's default context menu for the entire scout desktop (except input fields)
+  this.$container.on('contextmenu', function(event) {
+    if (event.target.nodeName !== 'INPUT' && event.target.nodeName !== 'TEXTAREA' && !event.target.isContentEditable) {
+      event.preventDefault();
     }
-    this._outlineContent.remove();
-    this._outlineContent = null;
+  });
+};
+
+scout.Desktop.prototype.setOutline = function(outline) {
+  if (this.rendered) {
+    this._removeDisplayChildsOfOutline();
   }
 
-  if (!content) {
+  this.outline = outline;
+  this._setOutlineActivated();
+  if (this.navigation) {
+    this.navigation.setOutline(this.outline);
+  }
+
+  if (this.rendered) {
+    this._renderDisplayChildsOfOutline();
+    this._renderDisplayStyle();
+  }
+
+  this.trigger('outlineChanged');
+};
+
+scout.Desktop.prototype._syncViewButtons = function(viewButtons, oldViewButtons) {
+  this.updateKeyStrokes(viewButtons, oldViewButtons);
+  this.viewButtons = viewButtons;
+};
+
+scout.Desktop.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
+};
+
+scout.Desktop.prototype._syncNavigationVisible = function(visible) {
+  this.setNavigationVisible(visible, false);
+  return false;
+};
+
+scout.Desktop.prototype.setNavigationVisible = function(visible, notifyServer) {
+  if (this.navigationVisible === visible) {
     return;
   }
-
-  this._outlineContent = content;
-  if (bringToFront) {
-    this.viewTabsController.deselectViewTab();
-    this._bringNavigationToFront();
-    if (!content.rendered) {
-      if (content instanceof scout.Table) {
-        content.menuBar.top();
-        content.menuBar.large();
-      }
-      content.render(this.$bench);
-
-      // Request focus on first element in new outlineTab.
-      this.session.focusManager.validateFocus();
-
-      content.htmlComp.validateLayout();
-      content.htmlComp.validateRoot = true;
-      if (content instanceof scout.Table) {
-        content.restoreScrollPosition();
-      }
-    } else if (!content.attached) {
-      content.attach();
-    }
-
-    //set active form to null because outline is active form.
-    this._setOutlineActivated();
-    // Request focus on first element in new outlineTab.
-    this.session.focusManager.validateFocus(); // TODO [5.2] nbu, dwi: why double validate?
+  this._setProperty('navigationVisible', visible);
+  notifyServer = scout.nvl(notifyServer, true);
+  if (notifyServer) {
+    this._sendProperty('navigationVisible');
   }
-
+  if (this.rendered) {
+    this._renderNavigationVisible();
+  }
+  this.updateSplitterVisibility();
 };
 
-scout.Desktop.prototype.setOutline = function(outline, bringToFront) {
-  this.outline = outline;
-  this.navigation.onOutlineChanged(this.outline, bringToFront);
+scout.Desktop.prototype._syncBenchVisible = function(visible) {
+  this.setBenchVisible(visible, false);
+  return false;
 };
 
-scout.Desktop.prototype.setBenchVisible = function(visible) {
-  this.benchVisible = visible;
+scout.Desktop.prototype.setBenchVisible = function(visible, notifyServer) {
+  if (this.benchVisible === visible) {
+    return;
+  }
+  this._setProperty('benchVisible', visible);
+  notifyServer = scout.nvl(notifyServer, true);
+  if (notifyServer) {
+    this._sendProperty('benchVisible');
+  }
   if (this.rendered) {
     this._renderBenchVisible();
   }
+  this.updateSplitterVisibility();
 };
 
-scout.Desktop.prototype._onModelFormShow = function(event) {
-  var form, displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    form = this.session.getOrCreateModelAdapter(event.form, displayParent.formController.displayParent);
-    this._setFormActivated(form, true);
-    // register listener to recover active form when child dialog is removed
-    displayParent.formController.registerAndRender(event.form, event.position, true);
-  }
-};
-
-scout.Desktop.prototype._onModelFormHide = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.formController.unregisterAndRemove(event.form);
-  }
-};
-
-scout.Desktop.prototype._onModelFormActivate = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.formController.activateForm(event.form);
-    this._setFormActivated(this.session.getOrCreateModelAdapter(event.form, displayParent.formController.displayParent), true);
-  }
-};
-
-scout.Desktop.prototype._onModelMessageBoxShow = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.messageBoxController.registerAndRender(event.messageBox);
-  }
-};
-
-scout.Desktop.prototype._onModelMessageBoxHide = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.messageBoxController.unregisterAndRemove(event.messageBox);
-  }
-};
-
-scout.Desktop.prototype._onModelFileChooserShow = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.fileChooserController.registerAndRender(event.fileChooser);
-  }
-};
-
-scout.Desktop.prototype._onModelFileChooserHide = function(event) {
-  var displayParent = this.session.getModelAdapter(event.displayParent);
-  if (displayParent) {
-    displayParent.fileChooserController.unregisterAndRemove(event.fileChooser);
-  }
-};
-
-scout.Desktop.prototype._onModelOpenUri = function(event) {
-  $.log.debug('(Desktop#_onModelOpenUri) uri=' + event.uri + ' action=' + event.action);
-  if (!event.uri) {
+scout.Desktop.prototype.setHeaderVisible = function(visible, notifyServer) {
+  if (this.headerVisible === visible) {
     return;
   }
-
-  if (event.action === 'download') {
-    this._openUriInIFrame(event.uri);
-  } else if (event.action === 'open') {
-    // TODO [5.2] bsh: Does that really work on all platforms?
-    this._openUriInIFrame(event.uri);
-  } else if (event.action === 'new-window') {
-    this._openUriAsNewWindow(event.uri);
+  this._setProperty('headerVisible', visible);
+  notifyServer = scout.nvl(notifyServer, true);
+  if (notifyServer) {
+    this._sendProperty('headerVisible');
+  }
+  if (this.rendered) {
+    this._renderHeaderVisible();
   }
 };
 
-scout.Desktop.prototype._onModelOutlineChanged = function(event) {
-  if (scout.DesktopStyle.DEFAULT === this.desktopStyle) {
-    this.setOutline(this.session.getOrCreateModelAdapter(event.outline, this), false);
+scout.Desktop.prototype.outlineDisplayStyle = function() {
+  if (this.outline) {
+    return this.outline.displayStyle;
   }
 };
 
-scout.Desktop.prototype._onModelOutlineContentActivate = function(event) {
-  if (scout.DesktopStyle.DEFAULT === this.desktopStyle) {
-    this.bringOutlineToFront(this.outline);
-  }
-};
-
-scout.Desktop.prototype._onModelAddNotification = function(event) {
-  scout.create('DesktopNotification', {
-    parent: this,
-    id: event.id,
-    duration: event.duration,
-    status: event.status,
-    closeable: event.closeable
-  }).show();
-};
-
-scout.Desktop.prototype._onModelRemoveNotification = function(event) {
-  this.removeNotification(event.id);
-};
-
-scout.Desktop.prototype.onModelAction = function(event) {
-  if (event.type === 'formShow') {
-    this._onModelFormShow(event);
-  } else if (event.type === 'formHide') {
-    this._onModelFormHide(event);
-  } else if (event.type === 'formActivate') {
-    this._onModelFormActivate(event);
-  } else if (event.type === 'messageBoxShow') {
-    this._onModelMessageBoxShow(event);
-  } else if (event.type === 'messageBoxHide') {
-    this._onModelMessageBoxHide(event);
-  } else if (event.type === 'fileChooserShow') {
-    this._onModelFileChooserShow(event);
-  } else if (event.type === 'fileChooserHide') {
-    this._onModelFileChooserHide(event);
-  } else if (event.type === 'openUri') {
-    this._onModelOpenUri(event);
-  } else if (event.type === 'outlineChanged') {
-    this._onModelOutlineChanged(event);
-  } else if (event.type === 'outlineContentActivate') {
-    this._onModelOutlineContentActivate(event);
-  } else if (event.type === 'addNotification') {
-    this._onModelAddNotification(event);
-  } else if (event.type === 'removeNotification') {
-    this._onModelRemoveNotification(event);
+scout.Desktop.prototype.shrinkNavigation = function() {
+  if (this.navigationVisible && this.outlineDisplayStyle() === scout.Tree.DisplayStyle.DEFAULT) {
+    this.outline.setDisplayStyle(scout.Tree.DisplayStyle.BREADCRUMB);
   } else {
-    scout.Desktop.parent.prototype.onModelAction.call(this, event);
+    this.setNavigationVisible(false);
   }
 };
 
+scout.Desktop.prototype.enlargeNavigation = function() {
+  if (this.navigationVisible && this.outlineDisplayStyle() === scout.Tree.DisplayStyle.BREADCRUMB) {
+    this.outline.setDisplayStyle(scout.Tree.DisplayStyle.DEFAULT);
+  } else {
+    this.setNavigationVisible(true);
+    // Layout immediately to have view tabs positioned correctly before animation starts
+    this.validateLayoutTree();
+  }
+};
+
+scout.Desktop.prototype.switchToBench = function() {
+  this.setHeaderVisible(true);
+  this.setBenchVisible(true);
+  this.setNavigationVisible(false);
+};
+
+scout.Desktop.prototype.switchToNavigation = function() {
+  this.setNavigationVisible(true);
+  this.setHeaderVisible(false);
+  this.setBenchVisible(false);
+};
+
+scout.Desktop.prototype.revalidateHeaderLayout = function() {
+  if (this.header) {
+    this.header.revalidateLayout();
+  }
+};
+
+scout.Desktop.prototype._goOffline = function() {
+  if (this.offline) {
+    return;
+  }
+  this.offline = true;
+  this._offlineNotification = scout.create('DesktopNotification.Offline', {
+    parent: this,
+    closable: false,
+    duration: scout.DesktopNotification.INFINITE,
+    status: {
+      message: this.session.text('ui.ConnectionInterrupted'),
+      severity: scout.Status.Severity.ERROR
+    }
+  });
+  this._offlineNotification.show();
+};
+
+scout.Desktop.prototype._goOnline = function() {
+  if (!this._hideOfflineMessagePending) {
+    this.hideOfflineMessage();
+  }
+};
+
+scout.Desktop.prototype.hideOfflineMessage = function() {
+  this._hideOfflineMessagePending = false;
+  this.removeNotification(this._offlineNotification);
+  this._offlineNotification = null;
+};
+
+scout.Desktop.prototype.addNotification = function(notification) {
+  if (!notification) {
+    return;
+  }
+  this.notifications.push(notification);
+  if (this.$notifications) {
+    // Bring to front
+    this.$notifications.appendTo(this.$container);
+  } else {
+    this.$notifications = this.$container.appendDiv('notifications');
+  }
+  notification.fadeIn(this.$notifications);
+};
+
+/**
+ * Removes the given notification.
+ * @param notification Either an instance of scout.DesktopNavigation or a String containing an ID of a notification instance.
+ */
+scout.Desktop.prototype.removeNotification = function(notification) {
+  if (typeof notification === 'string') {
+    var notificationId = notification;
+    notification = scout.arrays.find(this.notifications, function(n) {
+      return notificationId === n.id;
+    });
+  }
+  if (!notification) {
+    return;
+  }
+  if (this.$notifications) {
+    notification.fadeOut(this._onNotificationRemoved.bind(this, notification));
+  } else {
+    scout.arrays.remove(this.notifications, notification);
+  }
+};
+
+/**
+ * Removes every popup which is a descendant of the given widget.
+ */
+scout.Desktop.prototype.removePopupsFor = function(widget) {
+  this.$container.children('.popup').each(function(i, elem) {
+    var $popup = $(elem),
+      popup = scout.Widget.getWidgetFor($popup);
+
+    if (widget.has(popup)) {
+      popup.remove();
+    }
+  });
+};
+
 scout.Desktop.prototype._openUriInIFrame = function(uri) {
   // Create a hidden iframe and set the URI as src attribute value
   var $iframe = this.session.$entryPoint.appendElement('<iframe>', 'download-frame')
@@ -650,53 +636,50 @@
   }
 };
 
-scout.Desktop.prototype.bringOutlineToFront = function(outline) {
-  this.viewTabsController.deselectViewTab();
-
-  if (this.outline === outline) {
-    if (this.outline.inBackground) {
-      this._attachOutlineContent();
-      this._bringNavigationToFront();
-    }
-  } else {
-    this.setOutline(outline, true);
+scout.Desktop.prototype.bringOutlineToFront = function() {
+  if (!this.inBackground || this.displayStyle === scout.Desktop.DisplayStyle.BENCH) {
+    return;
   }
-  //set active form to null because outline is active form.
+  this.inBackground = false;
   this._setOutlineActivated();
 
-  if (this._hasNavigation()) {
-    this.navigation.revalidateLayout();
+  if (this.navigationVisible) {
+    this.navigation.bringToFront();
   }
+  if (this.benchVisible) {
+    this.bench.bringToFront();
+  }
+  if (this.headerVisible) {
+    this.header.bringToFront();
+  }
+
+  this._renderInBackground();
+};
+
+scout.Desktop.prototype.sendOutlineToBack = function() {
+  if (this.inBackground) {
+    return;
+  }
+  this.inBackground = true;
+  if (this.navigationVisible) {
+    this.navigation.sendToBack();
+  }
+  if (this.benchVisible) {
+    this.bench.sendToBack();
+  }
+  if (this.headerVisible) {
+    this.header.sendToBack();
+  }
+  this._renderInBackground();
 };
 
 /**
- * Called after width of navigation has been updated.
+ * === Method required for objects that act as 'displayParent' ===
+ *
+ * Returns 'true' if the Desktop is currently accessible to the user.
  */
-scout.Desktop.prototype.navigationWidthUpdated = function(navigationWidth) {
-  if (this._hasNavigation()) {
-    if (this._hasTaskBar()) {
-      this._$taskBar.css('left', navigationWidth);
-    }
-    if (this._hasBench()) {
-      this.$bench.css('left', navigationWidth);
-    }
-  }
-};
-
-scout.Desktop.prototype._bringNavigationToFront = function() {
-  this.navigation.bringToFront();
-  this._renderBenchDropShadow(false);
-};
-
-scout.Desktop.prototype._sendNavigationToBack = function() {
-  this.navigation.sendToBack();
-  this._renderBenchDropShadow(true);
-};
-
-scout.Desktop.prototype._renderBenchDropShadow = function(showShadow) {
-  if (this._hasNavigation() && this._hasBench()) {
-    this.$bench.toggleClass('drop-shadow', showShadow);
-  }
+scout.Desktop.prototype.inFront = function() {
+  return true; // Desktop is always available to the user.
 };
 
 /**
@@ -739,55 +722,43 @@
   }, this);
 };
 
-/**
- * === Method required for objects that act as 'displayParent' ===
- *
- * Returns 'true' if the Desktop is currently accessible to the user.
- */
-scout.Desktop.prototype.inFront = function() {
-  return true; // Desktop is always available to the user.
+scout.Desktop.prototype._showForm = function(form, displayParent, position, notifyServer) {
+  this._setFormActivated(form, notifyServer);
+  // register listener to recover active form when child dialog is removed
+  displayParent.formController.registerAndRender(form, position, true);
 };
 
-/**
- * Creates a local "null-outline" and an OutlineViewButton which is used, when no outline is available.
- * This avoids a lot of if/else code. The OVB adds a property 'visibleInMenu' which is only used in
- * the UI to decide whether or not the OVB will be shown in the ViewMenuPopup.js.
- */
-scout.Desktop.prototype._addNullOutline = function(outline) {
-  if (outline) {
-    return;
+scout.Desktop.prototype._hideForm = function(form) {
+  if (this.displayStyle === scout.Desktop.DisplayStyle.COMPACT && form.isView() && this.benchVisible) {
+    var openViews = this.bench.getViews().slice();
+    scout.arrays.remove(openViews, form);
+    if (openViews.length === 0) {
+      // Hide bench and show navigation if this is the last view to be hidden
+      this.switchToNavigation();
+    }
   }
-  var nullOutline = scout.create('Outline', {
-      parent: this
-    }),
-    ovb = scout.create('OutlineViewButton', {
-      parent: this,
-      displayStyle: 'MENU',
-      selected: true,
-      text: this.session.text('ui.Outlines'),
-      desktop: this,
-      visibleInMenu: false
-    });
+  form.displayParent.formController.unregisterAndRemove(form);
+};
 
-  ovb.outline = nullOutline;
-  this.outline = nullOutline;
-  this.viewButtons.push(ovb);
+scout.Desktop.prototype._activateForm = function(form, notifyServer) {
+  form.displayParent.formController.activateForm(form);
+  this._setFormActivated(form, notifyServer);
 };
 
 scout.Desktop.prototype._setOutlineActivated = function() {
   this._setFormActivated();
 };
 
-scout.Desktop.prototype._setFormActivated = function(form, suppressSend) {
-
-  //if desktop is in rendering process the can not set a new active for. instead the active form from the model is set selected.
+scout.Desktop.prototype._setFormActivated = function(form, notifyServer) {
+  // If desktop is in rendering process the can not set a new active for. instead the active form from the model is set selected.
   if (!this.rendered || this.initialFormRendering) {
     return;
   }
 
   if ((form && this.activeForm !== form.id) || (!form && this.activeForm)) {
     this.activeForm = form ? form.id : null;
-    if (!suppressSend) {
+    notifyServer = scout.nvl(notifyServer, true);
+    if (notifyServer) {
       this._sendFormActivated(form);
     }
   }
@@ -802,3 +773,250 @@
     return this.type === previous.type;
   });
 };
+
+/**
+ * Called when the animation triggered by animationLayoutChange is complete (e.g. navigation or bench got visible/invisible)
+ */
+scout.Desktop.prototype.onLayoutAnimationComplete = function() {
+  if (!this.headerVisible) {
+    this._removeHeader();
+  }
+  if (!this.navigationVisible) {
+    this._removeNavigation();
+  }
+  if (!this.benchVisible) {
+    this._removeBench();
+  }
+  this.trigger('animationEnd');
+  this.animateLayoutChange = false;
+};
+
+scout.Desktop.prototype.onResize = function(event) {
+  this.revalidateLayout();
+};
+
+scout.Desktop.prototype.onPopstate = function(event) {
+  var historyState = event.originalEvent.state;
+  if (historyState && historyState.deepLinkPath) {
+    this._send('historyEntryActivated', historyState);
+  }
+};
+
+scout.Desktop.prototype._onSplitterMove = function(event) {
+  // disallow wider than 50%
+  this.resizing = true;
+  var max = Math.floor(this.$container.outerWidth(true) / 2);
+  if (event.position > max) {
+    event.position = max;
+  }
+  this.revalidateLayout();
+};
+
+scout.Desktop.prototype._onSplitterMoveEnd = function(event) {
+  var splitterPosition = event.position;
+
+  // Store size
+  if (this.cacheSplitterPosition) {
+    sessionStorage.setItem('scout:desktopSplitterPosition', splitterPosition);
+  }
+
+  // Check if splitter is smaller than min size
+  if (splitterPosition < scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH) {
+    // Set width of navigation to BREADCRUMB_STYLE_WIDTH, using an animation.
+    // While animating, update the desktop layout.
+    // At the end of the animation, update the desktop layout, and store the splitter position.
+    this.navigation.$container.animate({
+      width: scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH
+    }, {
+      progress: function() {
+        this.resizing = true;
+        this.splitter.setPosition();
+        this.revalidateLayout();
+        this.resizing = false; // progress seems to be called after complete again -> layout requires flag to be properly set
+      }.bind(this),
+      complete: function() {
+        this.resizing = true;
+        this.splitter.setPosition();
+        // Store size
+        sessionStorage.setItem('scout:desktopSplitterPosition', this.splitter.position);
+        this.revalidateLayout();
+        this.resizing = false;
+      }.bind(this)
+    });
+  } else {
+    this.resizing = false;
+  }
+};
+
+scout.Desktop.prototype._onFormShow = function(event) {
+  var form,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    form = this.session.getOrCreateModelAdapter(event.form, displayParent);
+    this._showForm(form, displayParent, event.position, false);
+  }
+};
+
+scout.Desktop.prototype._onFormHide = function(event) {
+  var form,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    form = this.session.getModelAdapter(event.form);
+    this._hideForm(form);
+  }
+};
+
+scout.Desktop.prototype._onFormActivate = function(event) {
+  var form,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    form = this.session.getOrCreateModelAdapter(event.form, displayParent);
+    this._activateForm(form, false);
+  }
+};
+
+scout.Desktop.prototype._onMessageBoxShow = function(event) {
+  var messageBox,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    messageBox = this.session.getOrCreateModelAdapter(event.messageBox, displayParent);
+    displayParent.messageBoxController.registerAndRender(messageBox);
+  }
+};
+
+scout.Desktop.prototype._onMessageBoxHide = function(event) {
+  var messageBox,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    messageBox = this.session.getModelAdapter(event.messageBox);
+    displayParent.messageBoxController.unregisterAndRemove(messageBox);
+  }
+};
+
+scout.Desktop.prototype._onFileChooserShow = function(event) {
+  var fileChooser,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    fileChooser = this.session.getOrCreateModelAdapter(event.fileChooser, displayParent);
+    displayParent.fileChooserController.registerAndRender(fileChooser);
+  }
+};
+
+scout.Desktop.prototype._onFileChooserHide = function(event) {
+  var fileChooser,
+    displayParent = this.session.getModelAdapter(event.displayParent);
+  if (displayParent) {
+    fileChooser = this.session.getModelAdapter(event.fileChooser);
+    displayParent.fileChooserController.unregisterAndRemove(fileChooser);
+  }
+};
+
+scout.Desktop.prototype._onOpenUri = function(event) {
+  $.log.debug('(Desktop#_onOpenUri) uri=' + event.uri + ' action=' + event.action);
+  if (!event.uri) {
+    return;
+  }
+
+  if (event.action === 'download') {
+    if (scout.device.isIos()) {
+      // The iframe trick does not work for ios
+      // Since the file cannot be stored on the file system it will be shown in the browser if possible
+      // -> create a new window to not replace the existing content.
+      // Drawback: Popup-Blocker will show up
+      this._openUriAsNewWindow(event.uri);
+    } else {
+      this._openUriInIFrame(event.uri);
+    }
+  } else if (event.action === 'open') {
+    // Open in same window.
+    // Don't call _openUriInIFrame here, if action is set to open, an url is expected to be opened in the same window
+    // Additionally, some url types require to be opened in the same window like tel or mailto, at least on mobile devices
+    window.location.href = event.uri;
+  } else if (event.action === 'newWindow') {
+    this._openUriAsNewWindow(event.uri);
+  }
+};
+
+scout.Desktop.prototype._onOutlineChanged = function(event) {
+  this.setOutline(this.session.getOrCreateModelAdapter(event.outline, this));
+};
+
+scout.Desktop.prototype._onOutlineContentActivate = function(event) {
+  this.bringOutlineToFront();
+};
+
+scout.Desktop.prototype._onAddNotification = function(event) {
+  scout.create('DesktopNotification', {
+    parent: this,
+    id: event.id,
+    duration: event.duration,
+    status: event.status,
+    closable: event.closable
+  }).show();
+};
+
+scout.Desktop.prototype._onRemoveNotification = function(event) {
+  this.removeNotification(event.id);
+};
+
+scout.Desktop.prototype._onNotificationRemoved = function(notification) {
+  scout.arrays.remove(this.notifications, notification);
+  if (this.notifications.length === 0) {
+    this.$notifications.remove();
+    this.$notifications = null;
+  }
+};
+
+scout.Desktop.prototype.onReconnecting = function() {
+  if (!this.offline) {
+    return;
+  }
+  this._offlineNotification.reconnect();
+};
+
+scout.Desktop.prototype.onReconnectingSucceeded = function() {
+  if (!this.offline) {
+    return;
+  }
+  this.offline = false;
+  this._offlineNotification.reconnectSucceeded();
+  this._hideOfflineMessagePending = true;
+  setTimeout(this.hideOfflineMessage.bind(this), 3000);
+};
+
+scout.Desktop.prototype.onReconnectingFailed = function() {
+  if (!this.offline) {
+    return;
+  }
+  this._offlineNotification.reconnectFailed();
+};
+
+scout.Desktop.prototype.onModelAction = function(event) {
+  if (event.type === 'formShow') {
+    this._onFormShow(event);
+  } else if (event.type === 'formHide') {
+    this._onFormHide(event);
+  } else if (event.type === 'formActivate') {
+    this._onFormActivate(event);
+  } else if (event.type === 'messageBoxShow') {
+    this._onMessageBoxShow(event);
+  } else if (event.type === 'messageBoxHide') {
+    this._onMessageBoxHide(event);
+  } else if (event.type === 'fileChooserShow') {
+    this._onFileChooserShow(event);
+  } else if (event.type === 'fileChooserHide') {
+    this._onFileChooserHide(event);
+  } else if (event.type === 'openUri') {
+    this._onOpenUri(event);
+  } else if (event.type === 'outlineChanged') {
+    this._onOutlineChanged(event);
+  } else if (event.type === 'outlineContentActivate') {
+    this._onOutlineContentActivate(event);
+  } else if (event.type === 'addNotification') {
+    this._onAddNotification(event);
+  } else if (event.type === 'removeNotification') {
+    this._onRemoveNotification(event);
+  } else {
+    scout.Desktop.parent.prototype.onModelAction.call(this, event);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopFormController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopFormController.js
index 875a1b0..183b416 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopFormController.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopFormController.js
@@ -10,6 +10,7 @@
  ******************************************************************************/
 scout.DesktopFormController = function(displayParent, session) {
   scout.DesktopFormController.parent.call(this, displayParent, session);
+  this.desktop = displayParent;
   this._popupWindows = [];
   this._documentPopupWindowReadyHandler = this._onDocumentPopupWindowReady.bind(this);
 
@@ -21,6 +22,44 @@
 
 scout.DesktopFormController.instanceCounter = 0;
 
+scout.DesktopFormController.prototype.render = function() {
+  scout.DesktopFormController.parent.prototype.render.call(this);
+  // find active form and set selected.
+  var selectable;
+  if (this.desktop.activeForm) {
+    var form = this.session.getModelAdapter(this.desktop.activeForm);
+    if (form.isDialog()) {
+      // find ui selectable part
+      selectable = this._findActiveSelectablePart(form);
+    } else if (form.isView()) {
+      selectable = form;
+    }
+  }
+  if (!selectable) {
+    this.desktop.bringOutlineToFront();
+  } else {
+    this.desktop.bench.activateView(selectable);
+  }
+  // ensure in all view stacks the last view is activated
+  if (this.desktop.bench) {
+    this.desktop.bench.postRender();
+  }
+};
+
+/**
+ * Goes up in display hierarchy to find the form to select on desktop. null if outline is selected.
+ */
+scout.DesktopFormController.prototype._findActiveSelectablePart = function(form) {
+  if (form.parent.isView && form.parent.isDialog) {
+    if (form.parent.isView()) {
+      return form.parent;
+    } else if (form.parent.isDialog()) {
+      return this._findActiveSelectablePart(form.parent);
+    }
+  }
+  return null;
+};
+
 /**
  * @override FormController.js
  */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLayout.js
new file mode 100644
index 0000000..50bc96f
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLayout.js
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopLayout = function(desktop) {
+  scout.DesktopLayout.parent.call(this);
+  this.desktop = desktop;
+};
+scout.inherits(scout.DesktopLayout, scout.AbstractLayout);
+
+scout.DesktopLayout.prototype.layout = function($container) {
+  var navigationSize, headerSize, htmlHeader, htmlBench, benchSize, htmlNavigation, animationProps,
+    navigationWidth = 0,
+    headerHeight = 0,
+    desktop = this.desktop,
+    navigation = desktop.navigation,
+    header = desktop.header,
+    bench = desktop.bench,
+    // Animation moves header and bench to the left when navigation gets invisible or moves bench to the right if bench gets invisible (used for mobile)
+    animated = desktop.animateLayoutChange,
+    containerSize = this.containerSize(),
+    fullWidthNavigation = navigation && navigation.htmlComp.layoutData.fullWidth;
+
+  if (navigation) {
+    navigationWidth = this.calculateNavigationWidth(containerSize);
+    if (desktop.splitter) {
+      desktop.splitter.setPosition(navigationWidth, true);
+    }
+
+    if (desktop.navigationVisible) {
+      htmlNavigation = navigation.htmlComp;
+      navigationSize = new scout.Dimension(navigationWidth, containerSize.height)
+        .subtract(htmlNavigation.getMargins());
+      htmlNavigation.setSize(navigationSize);
+    }
+  }
+
+  if (header) {
+    htmlHeader = header.htmlComp;
+    headerHeight = htmlHeader.$comp.outerHeight(true);
+    if (desktop.headerVisible) {
+      // positioning
+      if (!animated) {
+        header.$container.cssLeft(navigationWidth);
+      }
+
+      // sizing
+      headerSize = new scout.Dimension(containerSize.width - navigationWidth, headerHeight)
+        .subtract(htmlHeader.getMargins());
+      if (!animated || fullWidthNavigation) {
+        htmlHeader.setSize(headerSize);
+      }
+
+      if (animated) {
+        animationProps = {
+          left: containerSize.width
+        };
+        prepareAnimate(animationProps, htmlHeader, headerSize);
+        this._animate(animationProps, htmlHeader, headerSize);
+      }
+    }
+  }
+
+  if (bench) {
+    htmlBench = bench.htmlComp;
+    if (desktop.benchVisible) {
+      // positioning
+      bench.$container.cssTop(headerHeight);
+      if (!animated) {
+        bench.$container.cssLeft(navigationWidth);
+      }
+
+      // sizing
+      benchSize = new scout.Dimension(containerSize.width - navigationWidth, containerSize.height - headerHeight)
+        .subtract(htmlBench.getMargins());
+      if (!animated || fullWidthNavigation) {
+        htmlBench.setSize(benchSize);
+      }
+
+      if (animated) {
+        animationProps = {
+          left: containerSize.width
+        };
+        prepareAnimate(animationProps, htmlBench, benchSize);
+        this._animate(animationProps, htmlBench, benchSize);
+      }
+    }
+  }
+
+  function prepareAnimate(animationProps, htmlComp, size) {
+    if (fullWidthNavigation) {
+      // Slide bench in from right to left, don't resize
+      htmlComp.$comp.cssLeft(containerSize.width);
+    } else {
+      // Resize bench
+      animationProps.width = size.width;
+      // Layout once before animation begins
+      // Resizing on every step/progress would result in poor performance (e.g. when a form is open in the bench)
+      htmlComp.setSize(size);
+    }
+    // Move to new point (=0, if navigation is invisible)
+    animationProps.left = navigationWidth;
+  }
+};
+
+/**
+ * Used to animate bench and header
+ */
+scout.DesktopLayout.prototype._animate = function(animationProps, htmlComp, size) {
+  // If animation is already running, stop the existing and don't use timeout to schedule the new to have a smoother transition
+  // Concurrent animation of the same element is bad because jquery messes up the overflow style
+  if (htmlComp.$comp.is(':animated')) {
+    htmlComp.$comp.stop().animate(animationProps, {
+      complete: this.desktop.onLayoutAnimationComplete.bind(this.desktop)
+    });
+  } else {
+    // schedule animation to have a smoother start
+    setTimeout(function() {
+      htmlComp.$comp.stop().animate(animationProps, {
+        complete: this.desktop.onLayoutAnimationComplete.bind(this.desktop)
+      });
+    }.bind(this));
+  }
+};
+
+scout.DesktopLayout.prototype.containerSize = function() {
+  var htmlContainer = this.desktop.htmlComp,
+    containerSize = htmlContainer.getAvailableSize();
+
+  return containerSize.subtract(htmlContainer.getInsets());
+};
+
+scout.DesktopLayout.prototype.calculateNavigationWidth = function(containerSize) {
+  if (!this.desktop.navigationVisible) {
+    return 0;
+  }
+  var navigationLayoutData = this.desktop.navigation.htmlComp.layoutData;
+  if (navigationLayoutData.fullWidth) {
+    return containerSize.width;
+  }
+  var splitterPosition = 0;
+  if (this.desktop.splitterVisible) {
+    splitterPosition = this.desktop.splitter.position;
+  }
+  var outline = this.desktop.outline;
+  if (!this.desktop.resizing && outline && outline.autoToggleBreadcrumbStyle) {
+    // If autoToggleBreadcrumbStyle is true, BREADCRUMB_STYLE_WIDTH triggers the toggling between the two modes.
+    // This code ensures this rule is never violated (necessary if mode is toggled programmatically rather than by the user)
+    if (outline.displayStyle === scout.Tree.DisplayStyle.BREADCRUMB) {
+      splitterPosition = scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH;
+    } else if (splitterPosition <= scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH) {
+      splitterPosition = scout.DesktopNavigation.DEFAULT_STYLE_WIDTH;
+    }
+  }
+  return Math.max(splitterPosition, scout.DesktopNavigation.MIN_WIDTH); // ensure newSize is not negative
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.css
new file mode 100644
index 0000000..b7eaca1
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.css
@@ -0,0 +1,12 @@
+.desktop-logo {
+  position: absolute;
+  right: 0;
+  top: 0;
+  margin-top: 8px;
+  margin-left: 20px;
+  margin-right: @bench-padding-x;
+  width: 33px;
+  height: 33px;
+  background-size: contain;
+  background-repeat: no-repeat;
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.js
new file mode 100644
index 0000000..c6d7958
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopLogo.js
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopLogo = function() {
+  scout.DesktopLogo.parent.call(this);
+};
+scout.inherits(scout.DesktopLogo, scout.Widget);
+
+scout.DesktopLogo.prototype._init = function(model) {
+  scout.DesktopLogo.parent.prototype._init.call(this, model);
+  this.url = model.url;
+};
+
+scout.DesktopLogo.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('desktop-logo');
+
+  // in memory of the first one...
+  this.$container.dblclick(function(event) {
+    if (event.altKey && event.ctrlKey) {
+      $(event.target).css('background', 'none');
+      $(event.target).css('font-size', '9px');
+      $(event.target).text('make software not war');
+    }
+  });
+};
+
+scout.DesktopLogo.prototype._renderProperties = function() {
+  this._renderUrl();
+};
+
+scout.DesktopLogo.prototype._renderUrl = function() {
+  this.$container.css('backgroundImage', 'url(' + this.url + ')');
+};
+
+scout.DesktopLogo.prototype.setUrl = function(url) {
+  this.url = url;
+  if (this.rendered) {
+    this._renderUrl();
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.js
deleted file mode 100644
index 51c06b7..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-// FIXME nbu/AWE: inherit from Widget.js? refactor un-/installKeyStroke
-scout.DesktopNavigation = function(desktop) {
-  this.desktop = desktop;
-  this.session = desktop.session;
-
-  this.$navigation;
-  this.$viewButtons;
-  this.$container;
-  this.htmlViewButtons;
-
-  this.viewMenuTab;
-};
-
-scout.DesktopNavigation.BREADCRUMB_SWITCH_WIDTH = 240; // Same value as in sizes.css // FIXME awe: make dynamic (min. breadcrumb width)
-scout.DesktopNavigation.MIN_SPLITTER_SIZE = 49; // not 50px because last pixel is the border (would not look good)
-
-scout.DesktopNavigation.prototype.render = function($parent) {
-  this.$navigation = $parent.appendDiv('desktop-navigation');
-  this.$viewButtons = this.$navigation.appendDiv('view-buttons');
-  this.htmlViewButtons = new scout.HtmlComponent(this.$viewButtons, this.session);
-  this.htmlViewButtons.setLayout(new scout.ViewButtonsLayout(this.htmlViewButtons));
-  this.viewMenuTab = new scout.ViewMenuTab(this._viewButtons('MENU'), this.session);
-  this.viewMenuTab.render(this.$viewButtons);
-
-  var i, viewTab,
-    viewTabs = this._viewButtons('TAB');
-  for (i = 0; i < viewTabs.length; i++) {
-    viewTab = viewTabs[i];
-    viewTab.render(this.$viewButtons);
-    if (i === viewTabs.length - 1) {
-      viewTab.last();
-    }
-  }
-
-  if (this._breadcrumbEnabled === undefined && this.desktop.outline) {
-    // Read initial value from active outline
-    this.setBreadcrumbEnabled(this.desktop.outline.breadcrumbEnabled);
-  }
-
-  this.$container = this.$navigation.appendDiv('navigation-container')
-    .on('mousedown', this._onNavigationMousedown.bind(this));
-};
-
-scout.DesktopNavigation.prototype._viewButtons = function(displayStyle) {
-  var viewButtons = [];
-  this.desktop.viewButtons.forEach(function(viewButton) {
-    if (displayStyle === undefined ||
-      displayStyle === viewButton.displayStyle) {
-      viewButtons.push(viewButton);
-    }
-  });
-  return viewButtons;
-};
-
-scout.DesktopNavigation.prototype._getNumSelectedTabs = function() {
-  var numSelected = 0;
-  if (this.viewMenuTab.selected) {
-    numSelected++;
-  }
-  this._viewButtons('TAB').forEach(function(viewTab) {
-    if (viewTab.selected) {
-      numSelected++;
-    }
-  });
-  return numSelected;
-};
-
-scout.DesktopNavigation.prototype._onNavigationMousedown = function(event) {
-  if (this.outline.inBackground) {
-    this.desktop.bringOutlineToFront(this.outline);
-  }
-};
-
-scout.DesktopNavigation.prototype.onOutlineChanged = function(outline, bringToFront) {
-  if (this.outline === outline) {
-    return;
-  }
-  if (this.outline) {
-    this.outline.remove();
-  }
-  this.outline = outline;
-  this.outline.setBreadcrumbEnabled(this._breadcrumbEnabled);
-  this.outline.render(this.$container);
-  this.outline.handleOutlineContent(bringToFront);
-  this._updateViewButtons(outline);
-  this.outline.validateFocus();
-};
-
-/**
- * This method updates the state of the view-menu-tab and the selected state of outline-view-buttons.
- * This method must also work in offline mode.
- */
-scout.DesktopNavigation.prototype._updateViewButtons = function(outline) {
-  this.viewMenuTab.onOutlineChanged(outline);
-  this._viewButtons('TAB').forEach(function(viewTab) {
-    if (viewTab instanceof scout.OutlineViewButton) {
-      viewTab.onOutlineChanged(outline);
-    }
-  });
-};
-
-// vertical splitter
-scout.DesktopNavigation.prototype.onResize = function(event) {
-  var newWidth = Math.max(event.data, scout.DesktopNavigation.MIN_SPLITTER_SIZE); // data = newSize, ensure newSize is not negative
-  this.$navigation.width(newWidth);
-  this.htmlViewButtons.revalidateLayout();
-  this.desktop.navigationWidthUpdated(newWidth);
-  this.setBreadcrumbEnabled(newWidth <= scout.DesktopNavigation.BREADCRUMB_SWITCH_WIDTH);
-};
-
-scout.DesktopNavigation.prototype.setBreadcrumbEnabled = function(enabled) {
-  if (this._breadcrumbEnabled === enabled) {
-    return;
-  }
-
-  this._breadcrumbEnabled = enabled;
-  if (this.outline) {
-    this.outline.setBreadcrumbEnabled(enabled);
-  }
-  this.viewMenuTab.setBreadcrumbEnabled(enabled);
-  this._viewButtons('TAB').forEach(function(viewButton) {
-    viewButton.setBreadcrumbEnabled(enabled);
-  });
-  this.$navigation.toggleClass('navigation-breadcrumb', enabled);
-};
-
-scout.DesktopNavigation.prototype.doViewMenuAction = function(event) {
-  this.viewMenuTab.togglePopup(event);
-};
-
-scout.DesktopNavigation.prototype.sendToBack = function() {
-  this.viewMenuTab.sendToBack();
-  this.outline.sendToBack();
-};
-
-scout.DesktopNavigation.prototype.bringToFront = function() {
-  this.viewMenuTab.bringToFront();
-  this.outline.bringToFront();
-};
-
-scout.DesktopNavigation.prototype.revalidateLayout = function() {
-  // this check here is required because there are multiple property change
-  // events while the outline changes. Sometimes we have none at all or two
-  // selected tabs at the same time. This makes it impossible to animate the
-  // view-buttons properly. With this check here we wait until all property
-  // change events have been processed. Assuming that in the end there's always
-  // on single selected view-button.
-  if (this._getNumSelectedTabs() === 1) {
-    this.htmlViewButtons.revalidateLayout();
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopTaskBarLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopTaskBarLayout.js
deleted file mode 100644
index 64358dd..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopTaskBarLayout.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.DesktopTabBarLayout = function(desktop) {
-  scout.DesktopTabBarLayout.parent.call(this);
-
-  this.TAB_WIDTH_LARGE = 220;
-  this.TAB_WIDTH_SMALL = 130;
-  this._desktop = desktop;
-  this._$overflowTab;
-  this._overflowTabsIndizes = [];
-};
-scout.inherits(scout.DesktopTabBarLayout, scout.AbstractLayout);
-
-// create a clone to measure pref. width
-scout.DesktopTabBarLayout.prototype._toolsWidth = function($tools, cssClasses) {
-  var $clone = $tools.clone(),
-    $items = $clone.find('.taskbar-tool-item');
-
-  $items
-    .removeClass('compact')
-    .removeClass('icon-only');
-
-  if (cssClasses) {
-    $items.addClass(cssClasses);
-  }
-  $clone.width('auto').appendTo(this._desktop.session.$entryPoint);
-  var toolsWidth = scout.graphics.getSize($clone, true).width;
-  $clone.remove();
-  return toolsWidth;
-};
-
-/**
- * @override AbstractLayout.js
- */
-scout.DesktopTabBarLayout.prototype.layout = function($container) {
-  var $tabs = $container.find('.desktop-view-tabs'),
-    $tools = $container.find('.taskbar-tools'),
-    contWidth = scout.graphics.getSize($container).width,
-    numTabs = this._desktop.viewTabsController.viewTabCount(),
-    smallPrefTabsWidth = numTabs * this.TAB_WIDTH_SMALL,
-    logoWidth = 0,
-    toolsWidth, tabsWidth;
-
-  if (this._desktop.session.uiUseTaskbarLogo) {
-    var $logo = $container.find('.taskbar-logo');
-    logoWidth = scout.graphics.getSize($logo, true).width;
-  }
-
-  // reset tabs and tool-items
-  if (this._$overflowTab) {
-    this._$overflowTab.remove();
-  }
-
-  $tabs.find('.desktop-view-tab').setVisible(true);
-
-  $tools.find('.taskbar-tool-item').each(function() {
-    var $item = $(this);
-    $item.removeClass('compact');
-    var dataText = $item.data('item-text');
-    if (dataText) {
-      var $title = $item.find('.text');
-      $title.text(dataText);
-    }
-  });
-
-  toolsWidth = this._toolsWidth($tools);
-  tabsWidth = contWidth - toolsWidth - logoWidth;
-  $tools.cssLeft(contWidth - toolsWidth - logoWidth);
-
-  this._overflowTabsIndizes = [];
-  var tabWidth;
-  if (smallPrefTabsWidth <= tabsWidth) {
-    tabWidth = Math.min(this.TAB_WIDTH_LARGE, Math.floor(tabsWidth / numTabs));
-    // 2nd - all Tabs fit when they have small size
-    $tabs.find('.desktop-view-tab').each(function() {
-      $(this).outerWidth(tabWidth);
-    });
-  } else {
-
-    // 1st try to minimize padding around tool-bar items
-    // re-calculate tabsWidth with reduced padding on the tool-bar-items
-    $tools.find('.taskbar-tool-item').each(function() {
-      $(this).addClass('compact');
-    });
-
-    toolsWidth = scout.graphics.getSize($tools, true).width;
-    tabsWidth = contWidth - toolsWidth - logoWidth;
-    $tools.cssLeft(contWidth - toolsWidth - logoWidth);
-
-    if (smallPrefTabsWidth <= tabsWidth) {
-      tabWidth = this.TAB_WIDTH_SMALL;
-      $tabs.find('.desktop-view-tab').each(function() {
-        $(this).outerWidth(tabWidth);
-      });
-      return;
-    }
-
-    // 2nd remove text from tool-bar items, only show icon
-    $tools.find('.taskbar-tool-item').each(function() {
-      var $item = $(this),
-        $title = $item.find('.text'),
-        text = $title.text();
-      $title.empty();
-      $item.data('item-text', text);
-    });
-
-    toolsWidth = scout.graphics.getSize($tools, true).width;
-    tabsWidth = contWidth - toolsWidth - logoWidth;
-    $tools.cssLeft(contWidth - toolsWidth - logoWidth);
-
-    if (smallPrefTabsWidth <= tabsWidth) {
-      tabWidth = this.TAB_WIDTH_SMALL;
-      $tabs.find('.desktop-view-tab').each(function() {
-        $(this).outerWidth(tabWidth);
-      });
-      return;
-    }
-
-    // Still doesn't fit? Put tabs into overflow menu
-    tabsWidth -= 30;
-
-    // check how many tabs fit into remaining tabsWidth
-    var numVisibleTabs = Math.floor(tabsWidth / this.TAB_WIDTH_SMALL),
-      numOverflowTabs = numTabs - numVisibleTabs;
-
-    // FIXME awe: display correct range of tabs (around visible tab)
-    // FIXME awe: tabs have no 'selected' state, this must be added together with activeForm on model Desktop
-    // Never put selected tab into overflow
-    var i = 0, selectedIndex = 0;
-    $tabs.find('.desktop-view-tab').each(function() {
-      if ($(this).hasClass('selected')) {
-        selectedIndex = i;
-      }
-      i++;
-    });
-
-    // determine visible range
-    var rightEnd, leftEnd = selectedIndex - Math.floor(numVisibleTabs / 2);
-    if (leftEnd < 0) {
-      leftEnd = 0;
-      rightEnd = numVisibleTabs - 1;
-    } else {
-      rightEnd = leftEnd + numVisibleTabs - 1;
-      if (rightEnd > numTabs - 1) {
-        rightEnd = numTabs - 1;
-        leftEnd = rightEnd - numVisibleTabs + 1;
-      }
-    }
-
-    this._$overflowTab = $tabs
-      .appendDiv('overflow-tab-item')
-      .on('mousedown', this._onMouseDownOverflow.bind(this));
-    if (numOverflowTabs > 1) {
-      this._$overflowTab.appendDiv('num-tabs').text(numOverflowTabs);
-    }
-
-    var that = this;
-    tabWidth = this.TAB_WIDTH_SMALL;
-    i = 0;
-    $tabs.find('.desktop-view-tab').each(function() {
-      if (i >= leftEnd && i <= rightEnd) {
-        $(this).outerWidth(tabWidth);
-      } else {
-        $(this).setVisible(false);
-        that._overflowTabsIndizes.push(i);
-      }
-      i++;
-    });
-  }
-};
-
-scout.DesktopTabBarLayout.prototype._onMouseDownOverflow = function(event) {
-  var menu, tab, popup, overflowMenus = [],
-    desktop = this._desktop;
-  this._overflowTabsIndizes.forEach(function(i) {
-    // FIXME awe: fix bugs in overflow-menu:
-    // - 1. menu schliesst nicht
-    // - 2. manchmal verschwindet ein (noch offener) Tab - wenn nur einer sichtbar ist
-    // - 3. add selenium tests
-    tab = desktop.viewTabsController.viewTabs()[i];
-    menu = scout.create('Menu', {
-      parent: desktop,
-      text: tab.getMenuText(),
-      tab: tab
-    });
-    menu.remoteHandler = function(event) {
-      if ('doAction' === event.type) {
-        $.log.debug('(DesktopTaskBarLayout#_onMouseDownOverflow) tab=' + this);
-        desktop.viewTabsController.selectViewTab(this);
-      }
-    }.bind(tab);
-    overflowMenus.push(menu);
-  });
-
-  popup = scout.create('ContextMenuPopup', {
-    parent: desktop,
-    menuItems: overflowMenus,
-    cloneMenuItems: false,
-    location: {
-      x: event.pageX,
-      y: event.pageY
-    }
-  });
-  popup.open(undefined, event);
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopViewTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopViewTab.js
deleted file mode 100644
index 08e8ef3..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopViewTab.js
+++ /dev/null
@@ -1,170 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.DesktopViewTab = function() {
-  scout.DesktopViewTab.parent.call(this);
-
-  this._view;
-  this._$bench;
-  this._mouseListener;
-  this.viewTabController;
-
-  // Container for the _Tab_ (not for the view).
-  this.$container;
-
-  this._propertyChangeListener = function(event) {
-    if (scout.arrays.containsAny(event.changedProperties, ['title', 'subTitle', 'iconId'])) {
-      this._titlesUpdated();
-    }
-    if (scout.arrays.containsAny(event.changedProperties, ['cssClass'])) {
-      this._cssClassUpdated(event.newProperties.cssClass, event.oldProperties.cssClass);
-    }
-  }.bind(this);
-
-  // FIXME awe: problem ist, dass Widegt#remove prüft ob rendered ist
-  // im bench mode ist der DesktopViewTab nicht gerendet, _remove wird
-  // darum nicht aufgerufen und das 'remove event vom tab nie getriggert
-  this._removeListener = this._onViewRemoved.bind(this);
-
-  this._addEventSupport();
-};
-scout.inherits(scout.DesktopViewTab, scout.Widget);
-
-scout.DesktopViewTab.prototype._init = function(options) {
-  scout.DesktopViewTab.parent.prototype._init.call(this, options);
-  this._view = options.view;
-  this._view.setParent(this);
-  this.viewTabController = options.viewTabController;
-  this._$bench = options.$bench;
-
-  this._installListeners();
-};
-
-scout.DesktopViewTab.prototype._installListeners = function() {
-  this._view.on('propertyChange', this._propertyChangeListener);
-  this._view.on('remove', this._removeListener);
-};
-
-scout.DesktopViewTab.prototype._uninstallListeners = function() {
-  this._view.off('propertyChange', this._propertyChangeListener);
-  this._view.off('remove', this._removeListener);
-};
-
-scout.DesktopViewTab.prototype._render = function($parent) {
-  var position = this.viewTabController.viewTabs().indexOf(this);
-  if (position === 0) {
-    this.$container = $parent.prependDiv('desktop-view-tab');
-  } else if (position > 0) {
-    var previousTab = this.viewTabController.viewTabs()[position - 1];
-    this.$container = previousTab.$container.afterDiv('desktop-view-tab');
-
-  }
-  this._mouseListener = this._onMouseDown.bind(this);
-  this.$container.on('mousedown', this._mouseListener);
-  this._$title = this.$container.appendDiv('title');
-  this._$subTitle = this.$container.appendDiv('sub-title');
-  this._titlesUpdated();
-  this._cssClassUpdated(this._view.cssClass, null);
-};
-
-scout.DesktopViewTab.prototype._renderView = function($parent) {
-  if (this._view.rendered) {
-    throw new Error('view already rendered');
-  }
-  this._view.render(this._$bench);
-  this._view.$container.addClass('view');
-  this._view.htmlComp.validateLayout();
-  this._view.htmlComp.validateRoot = true;
-  this._view.rendered = true;
-};
-
-scout.DesktopViewTab.prototype.select = function() {
-  this._cssSelect(true);
-  if (this._view.rendered) {
-    this._view.attach();
-  } else {
-    this._renderView();
-    if (this.session.desktop._outlineContent !== this._view) {
-      //notify model this form is active
-      this.session.desktop._setFormActivated(this._view);
-    }
-  }
-};
-
-scout.DesktopViewTab.prototype._cssSelect = function(selected) {
-  if (this.$container) {
-    this.$container.select(selected);
-  }
-};
-
-scout.DesktopViewTab.prototype.deselect = function() {
-  if (this._view.rendered) {
-    this._view.detach();
-  }
-  this._cssSelect(false);
-};
-
-scout.DesktopViewTab.prototype._onMouseDown = function(event) {
-  this.events.trigger('tabClicked', this);
-};
-
-scout.DesktopViewTab.prototype._titlesUpdated = function() {
-  if (!this.$container) {
-    return;
-  }
-
-  // Titles
-  setTitle(this._$title, this._view.title);
-  setTitle(this._$subTitle, this._view.subTitle);
-
-  // Icon
-  this.$container.icon(this._view.iconId);
-
-  // ----- Helper functions -----
-
-  function setTitle($titleElement, title) {
-    $titleElement.textOrNbsp(title);
-  }
-};
-
-scout.DesktopViewTab.prototype._cssClassUpdated = function(cssClass, oldCssClass) {
-  if (!this.$container) {
-    return;
-  }
-  this.$container.removeClass(oldCssClass);
-  this.$container.addClass(cssClass);
-};
-
-/**
- * We cannot not bind the 'remove' event of the view to the remove function
- * of the this tab, because in bench-mode we the tab is never rendered
- * and thus the _remove function is never called. However, we must still
- * trigger the 'remove' event because the ViewTabsController depends on it.
- */
-scout.DesktopViewTab.prototype._onViewRemoved = function() {
-  this._uninstallListeners();
-  if (this.rendered) {
-    this.remove();
-  } else {
-    this._trigger('remove');
-  }
-};
-
-scout.DesktopViewTab.prototype.onResize = function() {
-  this._view.onResize();
-};
-
-scout.DesktopViewTab.prototype.getMenuText = function() {
-  var text = this._view.title;
-  if (this._view.subTitle) {
-    text += ' (' + this._view.subTitle + ')';
-  }
-  return text;
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktop.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktop.js
deleted file mode 100644
index 29ef1cd..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktop.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.MobileDesktop = function() {
-  scout.MobileDesktop.parent.call(this);
-  this.benchVisible = false;
-  this._currentDetailForm;
-};
-scout.inherits(scout.MobileDesktop, scout.Desktop);
-
-scout.MobileDesktop.prototype._init = function(model) {
-  scout.MobileDesktop.parent.prototype._init.call(this, model);
-  this.viewTabsController = new scout.MobileViewTabsController(this);
-};
-
-/**
- * @override
- */
-scout.MobileDesktop.prototype._render = function($parent) {
-  this.$container = $parent;
-  this.$container.addClass('desktop');
-  this.navigation = new scout.DesktopNavigation(this);
-  this.navigation.render($parent);
-  this.navigation.setBreadcrumbEnabled(true);
-  this.navigation.onOutlineChanged(this.outline, true);
-
-  $parent.window().on('resize', this.onResize.bind(this));
-};
-
-/**
- * @override
- */
-scout.MobileDesktop.prototype.setOutline = function(outline, bringToFront) {
-  scout.MobileDesktop.parent.prototype.setOutline.call(this, outline, bringToFront);
-
-  // Never do lazy expanding since it is essential to see all nodes
-  outline.lazyExpandingEnabled = false;
-};
-
-/**
- * @override
- */
-
-scout.MobileDesktop.prototype._hasTaskBar = function() {
-  return false;
-};
-
-/**
- * @override
- */
-scout.MobileDesktop.prototype.setOutlineContent = function(content, bringToFront) {
-  var prefSize, $node,
-    selectedNode = this.outline.selectedNodes[0];
-
-  bringToFront = scout.nvl(bringToFront, true);
-  this.outline.menuBar.hiddenByUi = false;
-  if (this._currentDetailForm) {
-    this._currentDetailForm.remove();
-    this._currentDetailForm = null;
-  }
-
-  if (!selectedNode) {
-    return;
-  }
-
-  $node = selectedNode.$node;
-  if (content && content instanceof scout.Form) {
-    content.render($node);
-    content.htmlComp.pixelBasedSizing = true;
-    prefSize = content.htmlComp.getPreferredSize();
-    content.$container.height(prefSize.height);
-    content.$container.width($node.width());
-    content.htmlComp.validateLayout();
-    this._currentDetailForm = content;
-    this.outline.menuBar.hiddenByUi = true;
-    this.outline.menuBar.updateVisibility();
-  } else {
-    // Temporary set menubar to invisible and await response to recompute visibility again
-    // This is necessary because when moving the menubar to the selected node, the menubar probably has shows the wrong menus.
-    // On client side we do not know which menus belong to which page.
-    // The other solution would be to never show outline menus, instead show the menus of the table resp. show the table itself.
-    var oldHiddenByUi = this.outline.menuBar.hiddenByUi;
-    this.outline.menuBar.hiddenByUi = true;
-    this.outline.menuBar.updateVisibility();
-    waitForServer(this.session, function() {
-      this.outline.menuBar.hiddenByUi = oldHiddenByUi;
-      this.outline.menuBar.updateVisibility();
-    }.bind(this));
-  }
-
-  // Move menubar to the selected node
-  this.outline.menuBar.$container.appendTo($node);
-
-  function waitForServer(session, func) {
-    if (session.areRequestsPending() || session.areEventsQueued()) {
-      session.listen().done(func);
-    } else {
-      func();
-    }
-  }
-};
-
-scout.MobileDesktop.prototype.onResize = function(event) {
-  if (this._currentDetailForm) {
-    this._currentDetailForm.onResize();
-  }
-};
-
-scout.MobileViewTabsController = function(desktop) {
-  scout.MobileViewTabsController.parent.call(this, desktop);
-};
-scout.inherits(scout.MobileViewTabsController, scout.ViewTabsController);
-
-scout.MobileViewTabsController.prototype.createAndRenderViewTab = function(view, position) {
-  // Make sure bench is visible
-  this._desktop.setBenchVisible(true);
-
-  return scout.MobileViewTabsController.parent.prototype.createAndRenderViewTab.call(this, view, position);
-};
-
-scout.MobileViewTabsController.prototype._removeViewTab = function(viewTab, viewId) {
-  scout.MobileViewTabsController.parent.prototype._removeViewTab.call(this, viewTab, viewId);
-  if (this._viewTabs.length === 0) {
-    // Hide bench if no view forms are open -> show navigation
-    this._desktop.setBenchVisible(false);
-  }
-};
-
-// patches Outline.js and prevents creation of outline navigation buttons
-// TODO [5.2] cgu: find better solution, only way I can think of currently is to add a property to the model and set by device transformer.
-// Or maybe make the buttons invisible instead of not creating them
-scout.Outline.prototype._createOutlineNavigationButtons = function(node, staticMenus) {
-  return [];
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NullDesktopNavigation.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NullDesktopNavigation.js
deleted file mode 100644
index a13b215..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NullDesktopNavigation.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/**
- * This class is used in place of scout.DesktopNavigation when desktop has no navigation.
- * Avoids a lot of messy if/else code.
- */
-scout.NullDesktopNavigation = {
-  render: function($parent) {},
-  onOutlineChanged: function(outline) {},
-  bringToFront: function() {},
-  sendToBack: function() {},
-  onResize: function() {}
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButtonsLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButtonsLayout.js
deleted file mode 100644
index 3036825..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButtonsLayout.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.ViewButtonsLayout = function(htmlComp) {
-  scout.ViewButtonsLayout.parent.call(this);
-  this._htmlComp = htmlComp;
-};
-scout.inherits(scout.ViewButtonsLayout, scout.AbstractLayout);
-
-/**
- * Should be the same as in DesktopNavigation.css .view-button-tab > min-width.
- */
-scout.ViewButtonsLayout.MIN_TAB_WIDTH = '50px';
-
-scout.ViewButtonsLayout.prototype.layout = function($container) {
-  var containerBounds = this._htmlComp.getBounds(),
-    tabs = $container.children().length,
-    tabWidth = (containerBounds.width / tabs);
-  $container.children().each(function() {
-    var $tab = $(this);
-    $tab.removeAttr('style');
-    scout.graphics.setSize($tab, new scout.Dimension(tabWidth, containerBounds.height));
-  });
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuTab.js
deleted file mode 100644
index 2bc6e5c..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuTab.js
+++ /dev/null
@@ -1,186 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/**
- * Shows a list of view buttons with displayStyle=MENU
- * and shows the title of the active outline, if the outline is one
- * of the outline-view-buttons contained in the menu.
- */
-scout.ViewMenuTab = function(viewMenus, session) {
-  this.viewMenus = viewMenus;
-  this.session = session;
-
-  this.$container;
-  this.$arrowIcon; // small "arrow down" icon at the right side of the icon
-
-  this.outlineViewButton = null;
-  this.selected = false;
-  this.iconId;
-  this._inBackground = false;
-  this._breadcrumbEnabled = false;
-
-  this.defaultIconId = scout.icons.OUTLINE;
-
-  this._update();
-};
-
-/**
- * 1. look for a selected outline-view-button
- * 2. look for any outline-view-button
- * 3. in rare cases there will be no outline-view-button at all
- */
-scout.ViewMenuTab.prototype._update = function() {
-  var ovb = this._findOutlineViewButton(true);
-  if (ovb) {
-    this.selected = true;
-  } else {
-    ovb = this._findOutlineViewButton(false);
-    this.selected = false;
-  }
-  this.outlineViewButton = ovb;
-
-  // Use iconId from outline view button (defaultIconId as fallback)
-  this.iconId = (this.outlineViewButton && this.outlineViewButton.iconId) || this.defaultIconId;
-};
-
-scout.ViewMenuTab.prototype.render = function($parent) {
-  this.$container = $parent.appendDiv('view-button-tab')
-    .unfocusable()
-    .on('mousedown', this.togglePopup.bind(this));
-  this.$arrowIcon = this.$container
-    .appendSpan('arrow-icon')
-    .on('mousedown', this.togglePopup.bind(this));
-  this._renderProperties();
-};
-
-scout.ViewMenuTab.prototype._renderProperties = function() {
-  this._renderIconId();
-  this._renderSelected();
-};
-
-scout.ViewMenuTab.prototype._renderSelected = function() {
-  this.$container.select(this.selected);
-  this._updateArrowIconVisibility();
-};
-
-scout.ViewMenuTab.prototype._renderIconId = function() {
-  this.$container.icon(this.iconId);
-};
-
-scout.ViewMenuTab.prototype._updateArrowIconVisibility = function() {
-  this.$arrowIcon.toggleClass('hidden', !this.selected || this._inBackground);
-};
-
-/**
- * @param onlySelected when false -> function returns the first viewMenu which is an OutlineViewButton
- *                     when true  -> function returns the first viewMenu which is an OutlineViewButton AND also selected
- */
-scout.ViewMenuTab.prototype._findOutlineViewButton = function(onlySelected) {
-  var viewMenu;
-  for (var i = 0; i < this.viewMenus.length; i++) {
-    viewMenu = this.viewMenus[i];
-    if (viewMenu instanceof scout.OutlineViewButton) {
-      if (!onlySelected ||
-        onlySelected && viewMenu.selected) {
-        return viewMenu;
-      }
-    }
-  }
-  return null;
-};
-
-/**
- * Toggles the 'view menu popup', or brings the outline content to the front if in background.
- */
-scout.ViewMenuTab.prototype.togglePopup = function(event) {
-  if (this.selected) {
-    if (this._inBackground) {
-      this.session.desktop.bringOutlineToFront(this.outlineViewButton.outline);
-    } else {
-      // Open or close the popup.
-      if (this.popup) {
-        this.popup.close(event);
-      } else {
-        this.popup = this._openPopup(event);
-        this.popup.on('remove', function(event) {
-          this.popup = null;
-        }.bind(this));
-      }
-      return false; // menu won't open if we didn't abort the mousedown-event
-    }
-  } else {
-    this.outlineViewButton.doAction(event);
-  }
-};
-
-scout.ViewMenuTab.prototype._openPopup = function(event) {
-  var naviBounds = scout.graphics.bounds(this.$container.parent(), true);
-  var popup = scout.create('ViewMenuPopup', {
-    parent: this.session.desktop,
-    $tab: this.$container,
-    viewMenus: this._popupViewMenus(),
-    naviBounds: naviBounds,
-    breadcrumbEnabled: this._breadcrumbEnabled
-  });
-  popup.headText = this.text;
-  popup.open(null, event);
-  return popup;
-};
-
-/**
- * An OutlineViewButton for a null-outline shouldn't be added to the menus
- * displayed in the popup-menu. We recognize the null-outline be checking
- * the 'visibleInMenu' property.
- */
-scout.ViewMenuTab.prototype._popupViewMenus = function() {
-  var popupMenus = [];
-  this.viewMenus.forEach(function(viewMenu) {
-    if (scout.nvl(viewMenu.visibleInMenu, true)) {
-      popupMenus.push(viewMenu);
-    }
-  });
-  return popupMenus;
-};
-
-scout.ViewMenuTab.prototype.onOutlineChanged = function(outline) {
-  var i, viewMenu, ovb = null;
-  for (i = 0; i < this.viewMenus.length; i++) {
-    viewMenu = this.viewMenus[i];
-    if (viewMenu instanceof scout.OutlineViewButton && viewMenu.outline === outline) {
-      ovb = viewMenu;
-      break;
-    }
-  }
-
-  if (ovb) {
-    this.outlineViewButton = ovb;
-    this.iconId = ovb.iconId || this.defaultIconId;
-    this.selected = true;
-  } else {
-    this.selected = false;
-  }
-
-  this._renderProperties();
-};
-
-scout.ViewMenuTab.prototype.sendToBack = function() {
-  this._inBackground = true;
-  this._renderSelected();
-};
-
-scout.ViewMenuTab.prototype.bringToFront = function() {
-  this._inBackground = false;
-  this._renderSelected();
-};
-
-scout.ViewMenuTab.prototype.setBreadcrumbEnabled = function(enabled) {
-  this._breadcrumbEnabled = enabled;
-  this._renderSelected();
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabsController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabsController.js
deleted file mode 100644
index 79dde73..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabsController.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/**
- * Controller to interact with 'view tab bar'.
- */
-scout.ViewTabsController = function(desktop) {
-  this._desktop = desktop;
-  this._selectedViewTab;
-  this._viewTabs = [];
-  this._viewTabMap = {}; // [key=viewId, value=DesktopViewTab instance]
-};
-
-/**
- * Creates and renders a view tab for the given view.
- */
-scout.ViewTabsController.prototype.createAndRenderViewTab = function(view, position) {
-  var viewId = view.id;
-  // Tab is already existing.
-  var viewTab = this._viewTabMap[viewId],
-    newViewTab = !viewTab;
-  if (newViewTab) {
-
-    // Create the view tab.
-    viewTab = scout.create('DesktopViewTab', {
-      parent: view.displayParent,
-      view: view,
-      $bench: this._desktop.$bench,
-      viewTabController: this
-    });
-
-    // Register lifecycle listener on view tab.
-    viewTab.on('tabClicked', this.selectViewTab.bind(this));
-    viewTab.on('remove', this._removeViewTab.bind(this, viewTab, viewId));
-
-    var index = position;
-    var parentViewTab = this.viewTab(viewTab._view.displayParent);
-    if (parentViewTab) {
-      index = this._viewTabs.indexOf(parentViewTab) + this._calculateExactPosition(parentViewTab, index) + 1;
-    } else if (view.displayParent instanceof scout.Outline) {
-      var indexInOutline = view.displayParent.views.indexOf(view) === -1 ? 0 : view.displayParent.views.indexOf(view);
-      index = indexInOutline + this._desktop.views.length;
-    } else {
-      index = this._calculateExactPosition(this._desktop, index);
-    }
-
-    // Register the view tab.
-    scout.arrays.insert(this._viewTabs, viewTab, index);
-    this._viewTabMap[viewId] = viewTab;
-
-  }
-  // Render the view tab.
-  if (this._desktop._hasTaskBar() && !viewTab.rendered) {
-    viewTab.render(this._desktop._$viewTabBar);
-  }
-
-  // when rendering desktop also add all child tabs
-  if (view.session.desktop.initialFormRendering && newViewTab) {
-    view.formController.render();
-  }
-
-  return viewTab;
-};
-
-scout.ViewTabsController.prototype._calculateExactPosition = function(parent, position) {
-  if (position === 0) {
-    return 0;
-  } else {
-    var tabs = position || parent.views.length;
-    var searchUntil = position || parent.views.length;
-    for (var i = 0; i < searchUntil; i++) {
-      tabs = tabs + this._calculateExactPosition(parent.views[i]);
-    }
-    return tabs;
-  }
-};
-
-/**
- * Method invoked once the given view tab is removed from DOM.
- */
-scout.ViewTabsController.prototype._removeViewTab = function(viewTab, viewId) {
-  // Unregister the view tab.
-  var viewTabIndexBefore = this._viewTabs.indexOf(viewTab) - 1;
-  scout.arrays.remove(this._viewTabs, viewTab);
-  delete this._viewTabMap[viewId];
-
-  // Select next available view tab.
-  // FIXME dwi: (activeForm) use activeForm here or when no form is active, show outline again (from A.WE)
-  if (this._selectedViewTab === viewTab) {
-    if (viewTabIndexBefore >= 0) {
-      this.selectViewTab(this._viewTabs[viewTabIndexBefore]);
-    } else {
-      this._desktop.bringOutlineToFront(this._desktop.outline);
-    }
-  }
-
-  this._desktop._layoutTaskBar();
-};
-
-/**
- * Selects the given view tab and attaches its associated view.
- */
-scout.ViewTabsController.prototype.selectViewTab = function(viewTab) {
-  if (this._selectedViewTab === viewTab) {
-    return;
-  }
-
-  // Hide outline content.
-  this._desktop._sendNavigationToBack();
-  this._desktop._detachOutlineContent();
-
-  // Deselect the current selected tab.
-  this.deselectViewTab();
-
-  // set _selectedViewTab before selecting view tab. if this is not done before there is a problem when refreshing the webpage.
-  // parent is not set as selected, but rendered, before child-> child is rendered into same view because parent is not deselect.
-  // parent viewTab.select calls rendering of child.
-  this._selectedViewTab = viewTab;
-  // Select the new view tab.
-  viewTab.select();
-
-  // Invalidate layout and focus.
-  this._desktop._layoutTaskBar();
-};
-
-/**
- * Deselects the currently selected view tab.
- */
-scout.ViewTabsController.prototype.deselectViewTab = function() {
-  if (!this._selectedViewTab) {
-    return;
-  }
-
-  this._selectedViewTab.deselect();
-  this._selectedViewTab = null;
-};
-
-/**
- * Returns the view tab associated with the given view.
- */
-scout.ViewTabsController.prototype.viewTab = function(view) {
-  return this._viewTabMap[view.id];
-};
-
-/**
- * Returns the all view tabs.
- */
-scout.ViewTabsController.prototype.viewTabs = function() {
-  return this._viewTabs;
-};
-
-/**
- * Returns the selected view tab.
- */
-scout.ViewTabsController.prototype.selectedViewTab = function() {
-  return this._selectedViewTab;
-};
-
-/**
- * Returns the number of view tabs.
- */
-scout.ViewTabsController.prototype.viewTabCount = function() {
-  return this._viewTabs.length;
-};
-
-/**
- * Selects the last view tab.
- */
-scout.ViewTabsController.prototype._selectLastViewTab = function() {
-  if (this._viewTabs.length > 0) {
-    this.selectViewTab(this._viewTabs[this._viewTabs.length - 1]);
-  } else {
-    this.deselectViewTab();
-
-    this._desktop._attachOutlineContent();
-    this._desktop._bringNavigationToFront();
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.css
new file mode 100644
index 0000000..3d48b77
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.css
@@ -0,0 +1,3 @@
+.bench-column {
+  position: absolute;
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.js
new file mode 100644
index 0000000..df0959c
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumn.js
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.BenchColumn = function() {
+  scout.BenchColumn.parent.call(this);
+  this.htmlComp;
+  this.TAB_BOX_INDEX = {
+    TOP: 0,
+    CENTER: 1,
+    BOTTOM: 2
+  };
+  this.tabBoxs = [];
+  this._widgetToTabBox = {}; // [key=viewId, value=SimpleTabBox instance]
+  this.components;
+
+  // event listener functions
+  this._viewAddedHandler = this._onViewAdded.bind(this);
+  this._viewRemovedHandler = this._onViewRemoved.bind(this);
+  this._viewActivatedHandler = this._onViewActivated.bind(this);
+  this._viewDeactivatedHandler = this._onViewDeactivated.bind(this);
+
+  this._addEventSupport();
+};
+scout.inherits(scout.BenchColumn, scout.ModelAdapter);
+
+scout.BenchColumn.prototype._init = function(model) {
+  scout.BenchColumn.parent.prototype._init.call(this, model);
+
+  this._createTabBoxes();
+};
+
+/**
+ * @override ModelAdapter.js
+ */
+scout.BenchColumn.prototype._initKeyStrokeContext = function(keyStrokeContext) {
+  scout.BenchColumn.parent.prototype._initKeyStrokeContext.call(this, this.keyStrokeContext);
+  this.keyStrokeContext.invokeAcceptInputOnActiveValueField = true;
+  this.keyStrokeContext.$bindTarget = this._keyStrokeBindTarget.bind(this);
+};
+
+/**
+ * Returns a $container used as a bind target for the key-stroke context of the group-box.
+ * By default this function returns the container of the form, or when group-box is has no
+ * form as a parent the container of the group-box.
+ */
+scout.BenchColumn.prototype._keyStrokeBindTarget = function() {
+  return this.$container;
+};
+
+scout.BenchColumn.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('bench-column');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(this._createLayout());
+};
+
+scout.BenchColumn.prototype._renderProperties = function() {
+  scout.BenchColumn.parent.prototype._renderProperties.call(this);
+  this._renderTabBoxs();
+  this._revalidateSplitters();
+};
+
+scout.BenchColumn.prototype._renderTabBoxs = function() {
+  this.tabBoxs.forEach(function(tabBox) {
+    if (tabBox.viewCount() > 0) {
+
+      this._renderTabBox(tabBox);
+    }
+  }.bind(this));
+
+};
+
+scout.BenchColumn.prototype._renderTabBox = function(tabBox) {
+  if (!tabBox.rendered) {
+    tabBox.render(this.$container);
+  }
+};
+
+scout.BenchColumn.prototype._remove = function() {
+  scout.SimpleTabBox.parent.prototype._remove.call(this);
+  if (this.scrollable) {
+    scout.scrollbars.uninstall(this.$body);
+  }
+  this.htmlComp = null;
+};
+
+scout.BenchColumn.prototype.postRender = function() {
+  this.tabBoxs.forEach(function(tabBox) {
+    tabBox.postRender();
+  });
+};
+
+scout.BenchColumn.prototype._createLayout = function() {
+  return new scout.BenchColumnLayout(this);
+};
+
+scout.BenchColumn.prototype._onViewAdded = function(event) {
+  this.trigger('viewAdded', {
+    view: event.view
+  });
+};
+
+scout.BenchColumn.prototype._onViewRemoved = function(event) {
+  this.trigger('viewRemoved', {
+    view: event.view
+  });
+};
+
+scout.BenchColumn.prototype._onViewActivated = function(event) {
+  this.trigger('viewActivated', {
+    view: event.view
+  });
+};
+
+scout.BenchColumn.prototype._onViewDeactivated = function(event) {
+  this.trigger('viewDeactivated', {
+    view: event.view
+  });
+};
+
+scout.BenchColumn.prototype.activateView = function(view) {
+  var tabBox = this.getTabBox(view.displayViewId);
+  tabBox.activateView(view);
+};
+
+scout.BenchColumn.prototype._createTabBoxes = function() {
+  for (var i = 0; i < 3; i++) {
+    var tabBox = scout.create('SimpleTabBox', {
+      parent: this
+    });
+    tabBox.on('viewAdded', this._viewAddedHandler);
+    tabBox.on('viewRemoved', this._viewRemovedHandler);
+    tabBox.on('viewActivated', this._viewActivatedHandler);
+    tabBox.on('viewDeactivated', this._viewDeactivatedHandler);
+    this.tabBoxs.push(tabBox);
+  }
+};
+
+scout.BenchColumn.prototype._revalidateSplitters = function(clearPosition) {
+  // remove old splitters
+  if (this.components) {
+    this.components.forEach(function(comp) {
+      if (comp instanceof scout.Splitter) {
+        comp.remove();
+      }
+    });
+  }
+  var splitterParent = this;
+  this.components = this.tabBoxs.filter(function(tabBox) {
+    return tabBox.hasViews();
+  }).reduce(function(arr, col) {
+    if (arr.length > 0) {
+      // add sep
+      var splitter = scout.create('Splitter', {
+        parent: splitterParent,
+        $anchor: arr[arr.length - 1].$container,
+        $root: splitterParent.$container,
+        splitHorizontal: false,
+        maxRatio: 1
+      });
+      splitter.render(splitterParent.$container);
+      splitter.$container.addClass('line');
+      splitter.on('move', splitterParent._onSplitterMove.bind(splitterParent));
+      splitter.on('positionChanged', splitterParent._onSplitterPositionChanged.bind(splitterParent));
+      arr.push(splitter);
+    }
+    arr.push(col);
+    return arr;
+  }, []);
+  // well order the dom elements (reduce is used for simple code reasons, the result of reduce is not of interest).
+  this.components.filter(function(comp) {
+      return comp instanceof scout.SimpleTabBox;
+    })
+    .reduce(function(c1, c2, index) {
+      if (index > 0) {
+        c2.$container.insertAfter(c1.$container);
+      }
+      return c2;
+    }, undefined);
+};
+
+scout.BenchColumn.prototype._onSplitterMove = function(event) {
+  var splitterIndex = this.components.indexOf(event.source);
+  if (splitterIndex > 0 /*cannot be 0 since first element is a SimpleTabBox*/ ) {
+    var $before = this.components[splitterIndex - 1].$container,
+      $after = this.components[splitterIndex + 1].$container,
+      diff = event.position - event.source.position;
+
+    if (($before.outerHeight(true) + diff) < scout.DesktopBench.VIEW_MIN_HEIGHT) {
+      // set to min
+      event.setPosition($before.position().top + scout.DesktopBench.VIEW_MIN_HEIGHT);
+    }
+    if (($after.position().top + $after.outerHeight(true) - event.position) < scout.DesktopBench.VIEW_MIN_HEIGHT) {
+      event.setPosition($after.position().top + $after.outerHeight(true) - scout.DesktopBench.VIEW_MIN_HEIGHT);
+    }
+  }
+};
+scout.BenchColumn.prototype._onSplitterPositionChanged = function() {
+  this.revalidateLayout();
+};
+
+scout.BenchColumn.prototype.addView = function(view, activate) {
+  var tabBox = this.getTabBox(view.displayViewId);
+  this._widgetToTabBox[view.id] = tabBox;
+
+  tabBox.addView(view, activate);
+
+  if (this.rendered && tabBox.viewCount() === 1) {
+    if (!tabBox.rendered) {
+      // lazy render if the first view is added.
+      tabBox.render(this.$container);
+    }
+    this._revalidateSplitters(true);
+    this.htmlComp.invalidateLayoutTree();
+    // Layout immediate to prevent 'laggy' form visualization,
+    // but not initially while desktop gets rendered because it will be done at the end anyway
+    this.htmlComp.validateLayoutTree();
+  }
+};
+
+scout.BenchColumn.prototype.getTabBox = function(displayViewId) {
+  var tabBox;
+  switch (displayViewId) {
+    case 'NW':
+    case 'N':
+    case 'NE':
+      tabBox = this.tabBoxs[this.TAB_BOX_INDEX.TOP];
+      break;
+    case 'SW':
+    case 'S':
+    case 'SE':
+      tabBox = this.tabBoxs[this.TAB_BOX_INDEX.BOTTOM];
+      break;
+    default:
+      tabBox = this.tabBoxs[this.TAB_BOX_INDEX.CENTER];
+      break;
+  }
+  return tabBox;
+};
+
+scout.BenchColumn.prototype.removeView = function(view, showSiblingView) {
+  var tabBox = this._widgetToTabBox[view.id];
+  if (tabBox) {
+    tabBox.removeView(view, showSiblingView);
+    delete this._widgetToTabBox[view.id];
+    if (this.rendered && tabBox.viewCount() === 0) {
+      // remove view area if no view is left.
+      tabBox.remove();
+      this._revalidateSplitters(true);
+      this.htmlComp.invalidateLayoutTree();
+      // Layout immediate to prevent 'laggy' form visualization,
+      // but not initially while desktop gets rendered because it will be done at the end anyway
+      this.htmlComp.validateLayoutTree();
+    }
+  }
+};
+
+scout.BenchColumn.prototype.viewCount = function() {
+  return this.tabBoxs.map(function(tabBox) {
+    return tabBox.viewCount();
+  }).reduce(function(c1, c2) {
+    return c1 + c2;
+  }, 0);
+};
+
+scout.BenchColumn.prototype.hasViews = function() {
+  return this.viewCount() > 0;
+};
+scout.BenchColumn.prototype.getViews = function(displayViewId) {
+  return this.tabBoxs.reduce(function(arr, tabBox) {
+    scout.arrays.pushAll(arr, tabBox.getViews(displayViewId));
+    return arr;
+  }, []);
+};
+
+scout.BenchColumn.prototype.getComponents = function() {
+  return this.components;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumnLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumnLayout.js
new file mode 100644
index 0000000..f8a9de9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/BenchColumnLayout.js
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+
+scout.BenchColumnLayout = function(benchColumn) {
+  scout.BenchColumnLayout.parent.call(this);
+  this.benchColumn = benchColumn;
+  this.containerSize;
+};
+scout.inherits(scout.BenchColumnLayout, scout.AbstractLayout);
+
+scout.BenchColumnLayout.prototype.layout = function($container) {
+  var htmlContainer = this.benchColumn.htmlComp,
+    containerSize = htmlContainer.getAvailableSize(),
+    components = this.benchColumn.getComponents(),
+    layoutBySplitterPosition;
+
+  if (!components) {
+    return;
+  }
+  containerSize = containerSize.subtract(htmlContainer.getInsets());
+  layoutBySplitterPosition = components.filter(function(comp) {
+    return comp instanceof scout.Splitter;
+  }).map(function(splitter) {
+    return $.isNumeric(splitter.position);
+  }).reduce(function(b1, b2, index) {
+    if (index === 0) {
+      return b2;
+    }
+    return b1 && b2;
+  }, false);
+
+  if (!layoutBySplitterPosition) {
+    this._layoutInitial(components, containerSize);
+  } else if (containerSize.equals(this.containerSize)) {
+    this._layoutBySplitterPosition(components, containerSize);
+  } else {
+    this._layoutByRatio(components, containerSize);
+  }
+  this.containerSize = containerSize;
+
+};
+
+scout.BenchColumnLayout.prototype._layoutByRatio = function(components, containerSize) {
+  // set positions from ratio
+  components.forEach(function(comp) {
+    if (comp instanceof scout.Splitter) {
+      comp.setPosition(Math.floor(comp.getRatio() * containerSize.height));
+    }
+  });
+  this._layoutBySplitterPosition(components, containerSize);
+};
+
+scout.BenchColumnLayout.prototype._layoutBySplitterPosition = function(components, containerSize) {
+  var y = 0;
+  components.forEach(function(comp, index) {
+    if (comp instanceof scout.SimpleTabBox) {
+      var bounds = new scout.Rectangle(0, y, containerSize.width, 0);
+      if ((components.length - 1) > index) {
+        bounds.height = components[index + 1].position - y;
+        y = y + bounds.height;
+      } else {
+        bounds.height = containerSize.height - y;
+      }
+      comp.htmlComp.setBounds(bounds);
+    }
+  });
+};
+
+scout.BenchColumnLayout.prototype._layoutInitial = function(components, containerSize) {
+  var rowHeight = containerSize.height;
+  var rowCount = components.filter(function(comp) {
+    return comp instanceof scout.SimpleTabBox;
+  }).length;
+  if (rowCount > 0) {
+    rowHeight = containerSize.height / rowCount;
+  }
+  var y = 0;
+  components.forEach(function(comp, index) {
+    if (comp instanceof scout.Splitter) {
+      comp.setPosition(y, true);
+    } else {
+      var bounds = new scout.Rectangle(0, y, containerSize.width, rowHeight);
+      comp.htmlComp.setBounds(bounds);
+      y = y + rowHeight;
+    }
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.css
new file mode 100644
index 0000000..9a9f67e
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.css
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+
+@detail-table-header-padding-y: @table-header-padding-y + 5;
+@detail-table-row-padding-y: @table-row-padding-y + 5;
+@detail-table-header-padding-x: @bench-padding-x - @table-header-padding-left;
+@detail-table-data-padding-x: @bench-padding-x - @table-cell-padding-left;
+@detail-table-header-menubar-padding-right: 10px;
+
+.desktop-bench-drop-shadow() {
+  position: absolute;
+  content: '';
+  left: 0;
+  top: 3px;
+  width: 10px;
+  height: 100%;
+  box-shadow: -10px 0px 10px 0px rgba(0,0,0,0.4);
+}
+
+.desktop-bench {
+  position: absolute;
+
+  top: 0;
+  background-color: @background-color;
+
+  &.drop-shadow::before {
+    .desktop-bench-drop-shadow();
+  }
+
+  &.removed {
+    #scout.animation-name(slideout-right);
+    #scout.animation-duration(0.5s);
+  }
+}
+
+.detail-table.table {
+
+  & > .table-header {
+    padding-left: @detail-table-header-padding-x;
+    padding-right: @detail-table-header-padding-x;
+
+    & > .table-header-item {
+      padding-top: @detail-table-header-padding-y;
+      padding-bottom: @detail-table-header-padding-y;
+
+      & > .table-header-item-state {
+        top: 9px;
+      }
+    }
+
+    & > .menubar-container {
+      padding-left: 6px;
+      padding-right: @detail-table-header-menubar-padding-right;
+
+      & > .menubar > .menubox > .menu-item {
+        margin-right: 12px;
+      }
+    }
+  }
+
+  & > .table-data {
+    padding-left: @detail-table-data-padding-x;
+    padding-right: @detail-table-data-padding-x;
+  }
+
+  & .table-aggregate {
+    margin-left: @bench-padding-x;
+    margin-right: @bench-padding-x;
+
+    & > .table-cell {
+      padding-top: @detail-table-row-padding-y;
+      padding-bottom: @detail-table-row-padding-y;
+    }
+  }
+
+  & > .table-data {
+    & > .scrollbar.x-axis {
+      margin-top: 2px;
+      margin-bottom: 2px;
+    }
+
+    & > .table-row,
+    & > .table-aggregate-row {
+      /* Desktop table has a 2px border. Top and bottom border are added to the table cell. */
+      border-left-width: 2px;
+      border-right-width: 2px;
+
+      &.selected {
+        background-color: @item-selection-background-color;
+        border-color: @item-selection-border-color;
+      }
+
+      & > .table-cell {
+        /* Replace first and last pixel of specified row padding by a transparent border. This border will be */
+        /* set to the selection color when the row is selected, thus creating the illusion that the 2px selection */
+        /* border is drawn around the cell. See CSS rules below. */
+        padding-top: @detail-table-row-padding-y - 1px;
+        padding-bottom: @detail-table-row-padding-y - 1px;
+        border-top: 1px solid transparent;
+        border-bottom: 1px solid transparent;
+
+        &.checkable {
+          padding-top: @detail-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
+          padding-bottom: @detail-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
+        }
+      }
+
+      &.select-top > .table-cell {
+        border-top-color: @item-selection-border-color;
+      }
+
+      &.select-bottom > .table-cell {
+        border-bottom-color: @item-selection-border-color;
+      }
+
+      &.select-single > .table-cell {
+        border-top-color: @item-selection-border-color;
+        border-bottom-color: @item-selection-border-color;
+      }
+    }
+
+    & > .cell-editor-popup > .check-box-field > .cell-editor-field {
+      padding-top: @detail-table-row-padding-y - @checkable-cell-padding-adjustment - 1px;
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.js
new file mode 100644
index 0000000..28c7399
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBench.js
@@ -0,0 +1,620 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopBench = function() {
+  scout.DesktopBench.parent.call(this);
+  this.htmlComp;
+  this.VIEW_AREA_COLUMN_INDEX = {
+    LEFT: 0,
+    CENTER: 1,
+    RIGHT: 2
+  };
+  this.columns = [];
+  this.components;
+  this.tabBoxMap = {}; // [key=viewId, value=SimpleTabBox instance]
+  this._desktopOutlineChangedHandler = this._onDesktopOutlineChanged.bind(this);
+  this._desktopPropertyChangeHandler = this._onDesktopPropertyChange.bind(this);
+  this._outlineNodesSelectedHandler = this._onOutlineNodesSelected.bind(this);
+  this._outlinePageChangedHandler = this._onOutlinePageChanged.bind(this);
+  this._outlinePropertyChangeHandler = this._onOutlinePropertyChange.bind(this);
+
+  // event listener functions
+  this._viewAddedHandler = this._onViewAdded.bind(this);
+  this._viewRemovedHandler = this._onViewRemoved.bind(this);
+  this._viewActivatedHandler = this._onViewActivated.bind(this);
+  this._viewDeactivatedHandler = this._onViewDeactivated.bind(this);
+
+  this._desktopAnimationEndHandler = this._onDesktopAnimationEnd.bind(this);
+
+  this._addEventSupport();
+};
+scout.inherits(scout.DesktopBench, scout.Widget);
+
+scout.DesktopBench.VIEW_MIN_HEIGHT; // Configured in sizes.css
+scout.DesktopBench.VIEW_MIN_WIDTH; // Configured in sizes.css
+
+scout.DesktopBench.prototype._init = function(model) {
+  scout.DesktopBench.parent.prototype._init.call(this, model);
+
+  scout.DesktopBench.VIEW_MIN_HEIGHT = $.pxToNumber(scout.styles.get('view-tab-box', 'min-height').minHeight);
+  scout.DesktopBench.VIEW_MIN_WIDTH = $.pxToNumber(scout.styles.get('view-tab-box', 'min-width').minWidth);
+
+  this._createColumns();
+  this.desktop = this.session.desktop;
+  this.headerTabArea = model.headerTabArea;
+  // controller for headerTabArea
+  if (this.headerTabArea) {
+    this.headerTabAreaController = new scout.HeaderTabBoxController(this, this.headerTabArea);
+  }
+  this.outlineContentVisible = scout.nvl(model.outlineContentVisible, true);
+  this.setOutline(this.desktop.outline);
+  this.updateNavigationHandleVisibility();
+};
+
+scout.DesktopBench.prototype._createColumns = function() {
+  for (var i = 0; i < 3; i++) {
+    var column = scout.create('BenchColumn', {
+      parent: this
+    });
+    column.on('viewAdded', this._viewAddedHandler);
+    column.on('viewRemoved', this._viewRemovedHandler);
+    column.on('viewActivated', this._viewActivatedHandler);
+    column.on('viewDeactivated', this._viewDeactivatedHandler);
+    this.columns.push(column);
+  }
+};
+
+scout.DesktopBench.prototype._initKeyStrokeContext = function(keyStrokeContext) {
+  scout.DesktopBench.parent.prototype._initKeyStrokeContext.call(this, keyStrokeContext);
+
+  // Bound to desktop
+  this.desktopKeyStrokeContext = new scout.KeyStrokeContext();
+  this.desktopKeyStrokeContext.invokeAcceptInputOnActiveValueField = true;
+  this.desktopKeyStrokeContext.$bindTarget = this.desktop.$container;
+  this.desktopKeyStrokeContext.$scopeTarget = this.$container;
+  this.desktopKeyStrokeContext.registerKeyStroke(this.desktop.keyStrokes);
+};
+
+scout.DesktopBench.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('desktop-bench');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+
+  this.htmlComp.setLayout(new scout.DesktopBenchLayout(this));
+
+  this._renderColumns();
+  this._revalidateSplitters();
+  this._renderNavigationHandleVisible();
+
+  this.session.keyStrokeManager.installKeyStrokeContext(this.desktopKeyStrokeContext);
+  this.desktop.on('propertyChange', this._desktopPropertyChangeHandler);
+  this.desktop.on('outlineChanged', this._desktopOutlineChangedHandler);
+  this.desktop.on('animationEnd', this._desktopAnimationEndHandler);
+};
+
+scout.DesktopBench.prototype._renderColumns = function() {
+  this.columns.forEach(function(column) {
+    if (column.viewCount() > 0) {
+      this._renderColumn(column);
+
+    }
+  }.bind(this));
+};
+
+scout.DesktopBench.prototype._renderColumn = function(column) {
+  if (!column || column.rendered) {
+    return;
+  }
+
+  column.render(this.$container);
+};
+
+scout.DesktopBench.prototype._remove = function() {
+
+  this.desktop.off('propertyChange', this._desktopPropertyChangeHandler);
+  this.desktop.off('outlineChanged', this._desktopOutlineChangedHandler);
+  this.desktop.off('animationEnd', this._desktopAnimationEndHandler);
+  this.session.keyStrokeManager.uninstallKeyStrokeContext(this.desktopKeyStrokeContext);
+  scout.DesktopBench.parent.prototype._remove.call(this);
+
+};
+
+scout.DesktopBench.prototype._renderOutlineContent = function() {
+  if (!this.outlineContent || this.desktop.inBackground) {
+    return;
+  }
+
+  this.addView(this.outlineContent);
+
+  if (this.desktop.rendered) {
+
+    // Request focus on first element in outline content
+    this.session.focusManager.validateFocus();
+  }
+  if (this.outlineContent instanceof scout.Table) {
+    this.outlineContent.restoreScrollPosition();
+  }
+};
+
+scout.DesktopBench.prototype._removeOutlineContent = function() {
+  if (!this.outlineContent) {
+    return;
+  }
+  if (this.outlineContent instanceof scout.Table) {
+    this.outlineContent.storeScrollPosition();
+  }
+  this.removeView(this.outlineContent, false);
+
+};
+
+scout.DesktopBench.prototype._renderNavigationHandle = function() {
+  if (this.navigationHandle) {
+    return;
+  }
+  this.navigationHandle = scout.create('DesktopNavigationHandle', {
+    parent: this,
+    leftVisible: false
+  });
+  this.navigationHandle.render(this.$container);
+  this.navigationHandle.$container.addClass('navigation-closed');
+  this.navigationHandle.on('action', this._onNavigationHandleAction.bind(this));
+};
+
+scout.DesktopBench.prototype._removeNavigationHandle = function() {
+  if (!this.navigationHandle) {
+    return;
+  }
+  this.navigationHandle.remove();
+  this.navigationHandle = null;
+};
+
+scout.DesktopBench.prototype._renderNavigationHandleVisible = function() {
+  if (this.navigationHandleVisible) {
+    this._renderNavigationHandle();
+  } else {
+    this._removeNavigationHandle();
+  }
+};
+
+/**
+ * is called in post render of desktop used to initialize the ui state. E.g. show default views
+ */
+scout.DesktopBench.prototype.postRender = function() {
+  this.columns.forEach(function(column) {
+    column.postRender();
+  });
+};
+
+scout.DesktopBench.prototype.setNavigationHandleVisible = function(visible) {
+  if (this.navigationHandleVisible === visible) {
+    return;
+  }
+  this.navigationHandleVisible = visible;
+  if (this.rendered) {
+    this._renderNavigationHandleVisible();
+  }
+};
+
+scout.DesktopBench.prototype.setOutline = function(outline) {
+  if (this.outline) {
+    this.outline.off('nodesSelected', this._outlineNodesSelectedHandler);
+    this.outline.off('pageChanged', this._outlinePageChangedHandler);
+    this.outline.off('propertyChange', this._outlinePropertyChangeHandler);
+  }
+  this.outline = outline;
+  if (this.outline) {
+    this.outline.on('nodesSelected', this._outlineNodesSelectedHandler);
+    this.outline.on('pageChanged', this._outlinePageChangedHandler);
+    this.outline.on('propertyChange', this._outlinePropertyChangeHandler);
+  }
+  this.updateOutlineContent();
+};
+
+scout.DesktopBench.prototype.setOutlineContent = function(content) {
+  var oldContent = this.outlineContent;
+  if (this.outlineContent === content) {
+    return;
+  }
+
+  if (this.rendered) {
+    this._removeOutlineContent();
+  }
+  // reset view tab relevant properties.
+  if (content) {
+    delete content.title;
+    delete content.subTitle;
+    delete content.iconId;
+  }
+  this._setProperty('outlineContent', content);
+  // Inform header that outline content has changed
+  // (having a listener in the header is quite complex due to initialization phase, a direct call here is much easier to implement)
+  if (this.desktop.header) {
+    this.desktop.header.onBenchOutlineContentChange(content, oldContent);
+  }
+  this._showOutlineContent();
+};
+
+scout.DesktopBench.prototype._showOutlineContent = function() {
+  if (this.outlineContent) {
+    this.addView(this.outlineContent);
+
+    if (this.desktop.rendered) {
+      // Request focus on first element in outline content
+      this.session.focusManager.validateFocus();
+    }
+    if (this.outlineContent instanceof scout.Table) {
+      this.outlineContent.restoreScrollPosition();
+    }
+  }
+};
+
+scout.DesktopBench.prototype.setOutlineContentVisible = function(visible) {
+  if (visible === this.outlineContentVisible) {
+    return;
+  }
+  this.outlineContentVisible = visible;
+  this.updateOutlineContent();
+};
+
+scout.DesktopBench.prototype.bringToFront = function() {
+  if (!this.outlineContent) {
+    return;
+  }
+  this._showOutlineContent();
+};
+
+scout.DesktopBench.prototype.sendToBack = function() {
+  // nop
+};
+
+scout.DesktopBench.prototype._computeDefaultDetailForm = function() {
+  return this.outline.defaultDetailForm;
+};
+
+scout.DesktopBench.prototype._computeOutlineOverview = function() {
+  return this.outline.outlineOverview;
+};
+
+scout.DesktopBench.prototype._computeDetailContentForPage = function(node) {
+  if (!node) {
+    throw new Error('called _showDetailContentForPage without node');
+  }
+
+  var content;
+  if (node.detailForm && node.detailFormVisible && node.detailFormVisibleByUi) {
+    content = node.detailForm;
+    content.uiCssClasses = ['detail-form'];
+  } else if (node.detailTable && node.detailTableVisible) {
+    content = node.detailTable;
+    content.uiCssClasses = ['detail-table'];
+  }
+
+  return content;
+};
+
+scout.DesktopBench.prototype.updateOutlineContent = function() {
+  if (!this.outlineContentVisible || !this.outline) {
+    return;
+  }
+  var content;
+  var selectedPages = this.outline.selectedNodes;
+  if (selectedPages.length === 0) {
+    if (this.outline.defaultDetailForm) {
+      content = this._computeDefaultDetailForm();
+    } else if (this.outline.outlineOverview) {
+      content = this._computeOutlineOverview();
+    }
+  } else {
+    // Outline does not support multi selection -> [0]
+    var selectedPage = selectedPages[0];
+    content = this._computeDetailContentForPage(selectedPage);
+
+  }
+  if (content) {
+    if (content instanceof scout.Table) {
+      content.menuBar.top();
+      content.menuBar.large();
+    }
+    content.displayViewId = 'C';
+  }
+  this.setOutlineContent(content);
+};
+
+scout.DesktopBench.prototype.updateOutlineContentDebounced = function() {
+  clearTimeout(this._updateOutlineContentTimeout);
+  this._updateOutlineContentTimeout = setTimeout(function() {
+    this.updateOutlineContent();
+  }.bind(this), 300);
+};
+
+scout.DesktopBench.prototype.updateNavigationHandleVisibility = function() {
+  // Don't show handle if desktop says handle must not be visible
+  // Only show handle if navigation is invisible
+  this.setNavigationHandleVisible(this.desktop.navigationHandleVisible && !this.desktop.navigationVisible);
+};
+
+scout.DesktopBench.prototype._onDesktopOutlineChanged = function(event) {
+  this.setOutline(this.desktop.outline);
+  this.updateNavigationHandleVisibility();
+};
+
+scout.DesktopBench.prototype._onOutlineNodesSelected = function(event) {
+  if (event.debounce) {
+    this.updateOutlineContentDebounced();
+  } else {
+    this.updateOutlineContent();
+  }
+};
+
+scout.DesktopBench.prototype._onOutlinePageChanged = function(event) {
+  var selectedPage = this.outline.selectedNodes[0];
+  if (!event.page && !selectedPage || event.page === selectedPage) {
+    this.updateOutlineContent();
+  }
+};
+
+scout.DesktopBench.prototype._onOutlinePropertyChange = function(event) {
+  if (event.changedProperties.indexOf('defaultDetailForm') !== -1) {
+    this.updateOutlineContent();
+  }
+};
+
+scout.DesktopBench.prototype._onDesktopNavigationVisibleChange = function(event) {
+  // If navigation gets visible: Hide handle immediately
+  // If navigation gets hidden using animation: Show handle when animation ends
+  if (this.desktop.navigationVisible) {
+    this.updateNavigationHandleVisibility();
+  }
+};
+
+scout.DesktopBench.prototype._onDesktopNavigationHandleVisibleChange = function(event) {
+  this.updateNavigationHandleVisibility();
+};
+
+scout.DesktopBench.prototype._onDesktopAnimationEnd = function(event) {
+  if (!this.desktop.navigationVisible) {
+    this.updateNavigationHandleVisibility();
+  }
+};
+
+scout.DesktopBench.prototype._onDesktopPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('navigationVisible') !== -1) {
+    this._onDesktopNavigationVisibleChange();
+  } else if (event.changedProperties.indexOf('navigationHandleVisible') !== -1) {
+    this._onDesktopNavigationHandleVisibleChange();
+  }
+};
+
+scout.DesktopBench.prototype._onNavigationHandleAction = function(event) {
+  this.desktop.enlargeNavigation();
+};
+
+scout.DesktopBench.prototype._revalidateSplitters = function() {
+  // remove old splitters
+  if (this.components) {
+    this.components.forEach(function(comp) {
+      if (comp instanceof scout.Splitter) {
+        comp.remove();
+      }
+    });
+  }
+  var splitterParent = this;
+  this.components = this.columns.filter(function(column) {
+    return column.hasViews();
+  }).reduce(function(arr, col) {
+    if (arr.length > 0) {
+      // add sep
+      var splitter = scout.create('Splitter', {
+        parent: splitterParent,
+        $anchor: arr[arr.length - 1].$container,
+        $root: splitterParent.$container,
+        maxRatio: 1
+      });
+      splitter.render(splitterParent.$container);
+      splitter.$container.addClass('line');
+      splitter.on('move', splitterParent._onSplitterMove.bind(splitterParent));
+      splitter.on('positionChanged', splitterParent._onSplitterPositionChanged.bind(splitterParent));
+      arr.push(splitter);
+    }
+    arr.push(col);
+    return arr;
+  }, []);
+  // well order the dom elements (reduce is used for simple code reasons, the result of reduce is not of interest).
+  this.components.filter(function(comp) {
+      return comp instanceof scout.BenchColumn;
+    })
+    .reduce(function(c1, c2, index) {
+      if (index > 0) {
+        c2.$container.insertAfter(c1.$container);
+      }
+      return c2;
+    }, undefined);
+
+};
+
+scout.DesktopBench.prototype._onSplitterMove = function(event) {
+  var splitterIndex = this.components.indexOf(event.source);
+  if (splitterIndex > 0 /*cannot be 0 since first element is a BenchColumn*/ ) {
+    var $before = this.components[splitterIndex - 1].$container,
+      $after = this.components[splitterIndex + 1].$container,
+      diff = event.position - event.source.position;
+
+    if (($before.width() + diff) < scout.DesktopBench.VIEW_MIN_WIDTH) {
+      // set to min
+      event.setPosition($before.position().left + scout.DesktopBench.VIEW_MIN_WIDTH);
+    }
+    if (($after.position().left + $after.width() - event.position) < scout.DesktopBench.VIEW_MIN_WIDTH) {
+      event.setPosition($after.position().left + $after.width() - scout.DesktopBench.VIEW_MIN_WIDTH);
+    }
+  }
+};
+
+scout.DesktopBench.prototype._onSplitterPositionChanged = function(event) {
+  this.revalidateLayout();
+};
+
+scout.DesktopBench.prototype._onViewAdded = function(event) {
+  this.trigger('viewAdded', {
+    view: event.view
+  });
+};
+
+scout.DesktopBench.prototype._onViewRemoved = function(event) {
+  this.trigger('viewRemoved', {
+    view: event.view
+  });
+};
+
+scout.DesktopBench.prototype._onViewActivated = function(event) {
+  var view = event.view;
+  if (this.outlineContent === view) {
+    this.desktop.bringOutlineToFront(this.desktop.outline);
+  }
+  this.trigger('viewActivated', {
+    view: view
+  });
+};
+
+scout.DesktopBench.prototype._onViewDeactivated = function(event) {
+  if (this.outlineContent === event.view) {
+    this.desktop.sendOutlineToBack();
+  }
+  this.trigger('viewDeactivated', {
+    view: event.view
+  });
+};
+
+scout.DesktopBench.prototype.addView = function(view, activate) {
+  // normalize displayViewId
+  switch (view.displayViewId) {
+    case 'NW':
+    case 'W':
+    case 'SW':
+    case 'N':
+    case 'C':
+    case 'S':
+    case 'NE':
+    case 'E':
+    case 'SE':
+      break;
+    default:
+      // map all other displayViewIds to center
+      view.displayViewId = 'C';
+      break;
+  }
+  var column = this._getColumn(view.displayViewId);
+  this.tabBoxMap[view.id] = column;
+  column.addView(view, activate);
+
+  if (this.rendered) {
+    if (column.viewCount() === 1) {
+      this._renderColumn(column);
+      this._revalidateSplitters();
+      this.htmlComp.invalidateLayoutTree();
+      // Layout immediate to prevent 'laggy' form visualization,
+      // but not initially while desktop gets rendered because it will be done at the end anyway
+      this.htmlComp.validateLayoutTree();
+    }
+  }
+};
+
+scout.DesktopBench.prototype.activateView = function(view) {
+  var column = this._getColumn(view.displayViewId);
+  if (column) {
+    column.activateView(view);
+  }
+};
+
+scout.DesktopBench.prototype._getColumn = function(displayViewId) {
+  var column;
+
+  switch (displayViewId) {
+    case 'NW':
+    case 'W':
+    case 'SW':
+      column = this.columns[this.VIEW_AREA_COLUMN_INDEX.LEFT];
+      break;
+    case 'NE':
+    case 'E':
+    case 'SE':
+      column = this.columns[this.VIEW_AREA_COLUMN_INDEX.RIGHT];
+      break;
+    default:
+      column = this.columns[this.VIEW_AREA_COLUMN_INDEX.CENTER];
+      break;
+  }
+  return column;
+};
+
+scout.DesktopBench.prototype.removeView = function(view, showSiblingView) {
+  var column = this.tabBoxMap[view.id];
+  if (column) {
+    column.removeView(view, showSiblingView);
+    delete this.tabBoxMap[view.id];
+    // remove if empty
+    if (this.rendered && column.viewCount() === 0) {
+      column.remove();
+      this._revalidateSplitters(true);
+      this.htmlComp.invalidateLayoutTree();
+      // Layout immediate to prevent 'laggy' form visualization,
+      // but not initially while desktop gets rendered because it will be done at the end anyway
+      this.htmlComp.validateLayoutTree();
+    }
+  }
+};
+
+scout.DesktopBench.prototype.getComponents = function() {
+  return this.components;
+};
+
+scout.DesktopBench.prototype.getTabBox = function(displayViewId) {
+  var viewColumn = this._getColumn(displayViewId);
+  if (!viewColumn) {
+    return;
+  }
+  return viewColumn.getTabBox(displayViewId);
+};
+
+scout.DesktopBench.prototype.getViews = function(displayViewId) {
+  return this.columns.reduce(function(arr, column) {
+    scout.arrays.pushAll(arr, column.getViews(displayViewId));
+    return arr;
+  }, []);
+};
+
+scout.DesktopBench.prototype.getViewTab = function(view) {
+  var viewTab;
+  this.getTabs().some(function(vt) {
+    if (vt.view === view) {
+      viewTab = vt;
+      return true;
+    }
+    return false;
+  });
+  return viewTab;
+};
+
+scout.DesktopBench.prototype.getTabs = function() {
+  var tabs = [];
+  // consider right order
+  tabs = tabs.concat(this.getTabBox('NW').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('W').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('SW').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('N').getController().getTabs());
+  if (this.headerTabAreaController) {
+    tabs = tabs.concat(this.headerTabAreaController.getTabs());
+  } else {
+    tabs = tabs.concat(this.getTabBox('C').getController().getTabs());
+  }
+  tabs = tabs.concat(this.getTabBox('S').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('NE').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('E').getController().getTabs());
+  tabs = tabs.concat(this.getTabBox('SE').getController().getTabs());
+  return tabs;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBenchLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBenchLayout.js
new file mode 100644
index 0000000..c659b5e
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/bench/DesktopBenchLayout.js
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+
+scout.DesktopBenchLayout = function(bench) {
+  scout.DesktopBenchLayout.parent.call(this);
+  this.bench = bench;
+  this.containerSize;
+};
+scout.inherits(scout.DesktopBenchLayout, scout.AbstractLayout);
+
+scout.DesktopBenchLayout.prototype.layout = function($container) {
+  var
+    htmlContainer = this.bench.htmlComp,
+    containerSize = htmlContainer.getAvailableSize(),
+    components = this.bench.getComponents(),
+    layoutBySplitterPosition;
+
+  if (!components) {
+    return;
+  }
+  containerSize = containerSize.subtract(htmlContainer.getInsets());
+
+  layoutBySplitterPosition = components.filter(function(comp) {
+    return comp instanceof scout.Splitter;
+  }).map(function(splitter) {
+    return $.isNumeric(splitter.getPosition()) && $.isNumeric(splitter.getRatio());
+  }).reduce(function(b1, b2, index) {
+    if (index === 0) {
+      return b2;
+    }
+    return b1 && b2;
+  }, false);
+
+  if (!layoutBySplitterPosition) {
+    this._layoutInitial(components, containerSize);
+  } else if (containerSize.equals(this.containerSize)) {
+    this._layoutBySplitterPosition(components, containerSize);
+  } else {
+    this._layoutByRatio(components, containerSize);
+  }
+
+  this.containerSize = containerSize;
+
+};
+
+scout.DesktopBenchLayout.prototype._layoutByRatio = function(components, containerSize) {
+  // set positions from ratio
+  components.forEach(function(comp) {
+    if (comp instanceof scout.Splitter) {
+      comp.setPosition(Math.floor(comp.getRatio() * containerSize.width));
+    }
+  });
+  this._layoutBySplitterPosition(components, containerSize);
+};
+
+scout.DesktopBenchLayout.prototype._layoutBySplitterPosition = function(components, containerSize) {
+  var x = 0;
+  components.forEach(function(comp, index) {
+    if (!(comp instanceof scout.Splitter)) {
+      var bounds = new scout.Rectangle(x, 0, 0, containerSize.height);
+      if ((components.length - 1) > index) {
+        bounds.width = components[index + 1].position - x;
+        x = x + bounds.width;
+      } else {
+        bounds.width = containerSize.width - x;
+      }
+      comp.htmlComp.setBounds(bounds);
+    }
+  });
+};
+
+scout.DesktopBenchLayout.prototype._layoutInitial = function(components, containerSize) {
+  var columnWidth = containerSize.width;
+  var columnCount = components.filter(function(comp) {
+    return comp instanceof scout.BenchColumn;
+  }).length;
+  if (columnCount > 0) {
+    columnWidth = containerSize.width / columnCount;
+  }
+  var x = 0;
+  components.forEach(function(comp, index) {
+    if (comp instanceof scout.Splitter) {
+      comp.setPosition(x, true);
+    } else {
+      var bounds = new scout.Rectangle(x, 0, columnWidth, containerSize.height);
+      comp.htmlComp.setBounds(bounds);
+      x = x + columnWidth;
+    }
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.css
new file mode 100644
index 0000000..1be08aa
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.css
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+.desktop-view-tab {
+  position: relative;
+  display: inline-block;
+  /* 1px smaller than the header because of the bottom border (see .selected rule below) */
+  height: calc(~'100% - 1px');
+  vertical-align: top;
+  width: 220px;
+  padding: 6px 10px 0 20px;
+  cursor: pointer;
+  background-color: @view-tab-background-color;
+  color: @text-color;
+  border-right: 1px solid @border-color;
+
+  &.small {
+    width: 130px;
+  }
+
+  &:hover {
+    color: @hover-color;
+  }
+
+  &:active {
+    color: @active-color;
+  }
+
+  &.disabled {
+    color: @disabled-color;
+    cursor: default;
+  }
+
+  &.selected {
+    cursor: default;
+    background-color: @view-tab-active-background-color;
+    color: @view-tab-active-color;
+    /* full size of header to draw over the border-bottom */
+    height: 100%;
+
+
+  }
+
+  &.modality-highlight {
+    #scout.animation-flash-gray();
+  }
+
+  & > .icon {
+    float: right;
+    margin-left: 5px;
+    margin-right: -5px;
+  }
+
+  & > .title {
+    #scout.overflow-ellipsis-nowrap();
+    #scout.font-text-large();
+  }
+
+  & > .sub-title {
+    #scout.overflow-ellipsis-nowrap();
+    #scout.font-text-normal();
+  }
+}
+
+/* key boxes */
+
+.desktop-view-tab .key-box {
+  bottom: 4px;
+
+  &.disabled {
+    background-color: @disabled-color;
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.js
new file mode 100644
index 0000000..f817c7d
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTab.js
@@ -0,0 +1,81 @@
+/*******************************************************************************
+
+* Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopTab = function() {
+  scout.DesktopTab.parent.call(this);
+
+  this.view;
+
+  this._propertyChangeListener = function(event) {
+    if (scout.arrays.containsAny(event.changedProperties, ['title'])) {
+      this.setTitle(this.view.title);
+    } else if (scout.arrays.containsAny(event.changedProperties, ['subTitle'])) {
+      this.setSubTitle(this.view.subTitle);
+    } else if (scout.arrays.containsAny(event.changedProperties, ['iconId'])) {
+      this.setIconId(this.view.iconId);
+    } else if (scout.arrays.containsAny(event.changedProperties, ['cssClass'])) {
+      this._cssClassUpdated(event.newProperties.cssClass, event.oldProperties.cssClass);
+    }
+  }.bind(this);
+
+  // FIXME awe: problem ist, dass Widegt#remove prüft ob rendered ist
+  // im bench mode ist der DesktopTab nicht gerendet, _remove wird
+  // darum nicht aufgerufen und das 'remove event vom tab nie getriggert
+  this._removeListener = this._onViewRemoved.bind(this);
+
+  this._addEventSupport();
+};
+
+scout.inherits(scout.DesktopTab, scout.SimpleTab);
+
+scout.DesktopTab.prototype._init = function(options) {
+  this.view = options.view;
+  options.title = this.view.title;
+  options.subTitle = this.view.subTitle;
+  options.iconId = this.view.iconId;
+
+  scout.DesktopTab.parent.prototype._init.call(this, options);
+
+
+  this._installListeners();
+};
+
+scout.DesktopTab.prototype._installListeners = function() {
+  this.view.on('propertyChange', this._propertyChangeListener);
+  this.view.on('remove', this._removeListener);
+};
+
+scout.DesktopTab.prototype._uninstallListeners = function() {
+  this.view.off('propertyChange', this._propertyChangeListener);
+  this.view.off('remove', this._removeListener);
+};
+
+scout.DesktopTab.prototype._cssClassUpdated = function(cssClass, oldCssClass) {
+  if (!this.$container) {
+    return;
+  }
+  this.$container.removeClass(oldCssClass);
+  this.$container.addClass(cssClass);
+};
+
+/**
+ * We cannot not bind the 'remove' event of the view to the remove function
+ * of the this tab, because in bench-mode we the tab is never rendered
+ * and thus the _remove function is never called.
+ */
+scout.DesktopTab.prototype._onViewRemoved = function() {
+  this._uninstallListeners();
+  if (this.rendered) {
+    this.remove();
+  } else {
+    this.trigger('remove');
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabSelectKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTabSelectKeyStroke.js
similarity index 70%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabSelectKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTabSelectKeyStroke.js
index edfb9b0..5f0ac16 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewTabSelectKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DesktopTabSelectKeyStroke.js
@@ -11,10 +11,9 @@
 /**
  * Composite keystroke to provide a numeric keystroke to select view tabs.
  */
-scout.ViewTabSelectKeyStroke = function(desktop) {
-  scout.ViewTabSelectKeyStroke.parent.call(this);
+scout.DesktopTabSelectKeyStroke = function(desktop) {
+  scout.DesktopTabSelectKeyStroke.parent.call(this);
   this.field = desktop;
-  this._viewTabsController = desktop.viewTabsController;
 
   // modifier
   this.parseAndSetKeyStroke(desktop.selectViewTabsKeyStrokeModifier);
@@ -34,28 +33,33 @@
     return this._viewTabs()[viewIndex].$container;
   }.bind(this);
 };
-scout.inherits(scout.ViewTabSelectKeyStroke, scout.RangeKeyStroke);
+scout.inherits(scout.DesktopTabSelectKeyStroke, scout.RangeKeyStroke);
 
 /**
  * @override KeyStroke.js
  */
-scout.ViewTabSelectKeyStroke.prototype._isEnabled = function() {
-  var enabled = scout.ViewTabSelectKeyStroke.parent.prototype._isEnabled.call(this);
+scout.DesktopTabSelectKeyStroke.prototype._isEnabled = function() {
+  var enabled = scout.DesktopTabSelectKeyStroke.parent.prototype._isEnabled.call(this);
   return enabled && this.field.selectViewTabsKeyStrokesEnabled && this._viewTabs().length > 0;
 };
 
 /**
  * @override KeyStroke.js
  */
-scout.ViewTabSelectKeyStroke.prototype.handle = function(event) {
+scout.DesktopTabSelectKeyStroke.prototype.handle = function(event) {
   var viewIndex = event.which - scout.keys['1'];
 
   if (this._viewTabs().length && (viewIndex < this._viewTabs().length)) {
     var viewTab = this._viewTabs()[viewIndex];
-    this._viewTabsController.selectViewTab(viewTab);
+    if (this.field.bench) {
+      this.field.bench.activateView(viewTab.view);
+    }
   }
 };
 
-scout.ViewTabSelectKeyStroke.prototype._viewTabs = function() {
-  return this._viewTabsController.viewTabs();
+scout.DesktopTabSelectKeyStroke.prototype._viewTabs = function() {
+  if (this.field.bench) {
+    return this.field.bench.getTabs();
+  }
+  return [];
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DisableBrowserTabSwitchingKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DisableBrowserTabSwitchingKeyStroke.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DisableBrowserTabSwitchingKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/desktoptab/DisableBrowserTabSwitchingKeyStroke.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.css
new file mode 100644
index 0000000..a73fdd8
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.css
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+.desktop-header {
+  position: absolute;
+  top: 0;
+  height: @desktop-header-height;
+  background-color: @desktop-header-background-color;
+  #scout.vertical-align-helper-after();
+
+  /* Has the same effect as "border-bottom: 1px solid @border-color", but is over-drawable by child */
+  /* elements (such as the selected view-tab). The border would not be, because of "overflow: hidden". */
+  &::before {
+    content: '';
+    background-color: @border-color;
+    width: 100%;
+    height: 1px;
+    position: absolute;
+    top: calc(~'100% - 1px');
+    left: 0;
+  }
+
+  & > .simple-tab-area {
+    height: @desktop-header-height;
+
+    & > .desktop-view-tab.selected {
+      &::before {
+        .desktop-bench-drop-shadow();
+        top: 0px;
+        width: 20px;
+        height: 110%;
+      }
+
+      &:not(:first-child)::before {
+        box-shadow: -7px 0px 10px 0px rgba(0,0,0,0.4);
+      }
+    }
+  }
+
+  &.removed {
+    #scout.animation-name(slideout-right);
+    #scout.animation-duration(0.5s);
+  }
+}
+
+.desktop-header > .view-button-box  {
+  height: 100%;
+
+  & > .view-button-tab {
+    /* 1px smaller than the header because of the bottom border (see .selected rule for .desktop-view-tab) */
+    height: calc(~'100% - 1px');
+    vertical-align: top;
+    background-color: @header-view-button-tab-background-color;
+    color: @header-view-button-tab-color;
+
+    &.last {
+      border-right-color: @border-color;
+    }
+
+    &:hover {
+      &:not(.selected) > .font-icon {
+        color: @header-view-button-tab-color;
+      }
+    }
+
+    &.selected:not(.in-background) {
+      background-color: @header-view-button-tab-active-background-color;
+      color: @header-view-button-tab-active-color;
+      height: 100%;
+      padding-bottom: 1px;
+
+      &.popup-open {
+        height: calc(~'100% - 1px');
+      }
+
+      &.outline-content-has-menubar {
+        background-color: @main-menubar-background-color;
+      }
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.js
new file mode 100644
index 0000000..a8c4074
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeader.js
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopHeader = function() {
+  scout.DesktopHeader.parent.call(this);
+  this.tabArea;
+  this._desktopPropertyChangeHandler = this._onDesktopPropertyChange.bind(this);
+  this._desktopAnimationEndHandler = this._onDesktopAnimationEnd.bind(this);
+  this._outlineContentMenuBarPropertyChangeHandler = this._onOutlineContentMenuBarPropertyChange.bind(this);
+  this._addEventSupport();
+};
+scout.inherits(scout.DesktopHeader, scout.Widget);
+
+scout.DesktopHeader.prototype._init = function(model) {
+  scout.DesktopHeader.parent.prototype._init.call(this, model);
+  this.desktop = this.session.desktop;
+  this.toolBoxVisible = scout.nvl(model.toolBoxVisible, true);
+  this.viewButtonBoxVisible = scout.nvl(model.viewButtonBoxVisible, false);
+  this.updateViewButtonBoxVisibility();
+  // create view tab box
+  this.tabArea = scout.create('SimpleTabArea', {
+    parent: this
+  });
+};
+
+scout.DesktopHeader.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('desktop-header');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.DesktopHeaderLayout(this));
+  this._renderViewButtonBoxVisible();
+  this._renderViewTabs();
+  this._renderToolBoxVisible();
+  this._renderLogoUrl();
+  this.desktop.on('propertyChange', this._desktopPropertyChangeHandler);
+  this.desktop.on('animationEnd', this._desktopAnimationEndHandler);
+  if (this.desktop.bench) {
+    this.outlineContent = this.desktop.bench.outlineContent;
+  }
+  this._attachOutlineContentMenuBarHandler();
+};
+
+scout.DesktopHeader.prototype._remove = function() {
+  this.desktop.off('propertyChange', this._desktopPropertyChangeHandler);
+  this.desktop.off('animationEnd', this._desktopAnimationEndHandler);
+  this._detachOutlineContentMenuBarHandler();
+  this.outlineContent = null;
+  scout.DesktopHeader.parent.prototype._remove.call(this);
+};
+
+scout.DesktopHeader.prototype._renderViewTabs = function() {
+   this.tabArea.render(this.$container);
+};
+
+scout.DesktopHeader.prototype._renderToolBox = function() {
+  if (this.toolBox) {
+    return;
+  }
+  this.toolBox = scout.create('DesktopToolBox', {
+    parent: this,
+    menus: this.desktop.menus
+  });
+  this.toolBox.render(this.$container);
+};
+
+scout.DesktopHeader.prototype._removeToolBox = function() {
+  if (!this.toolBox) {
+    return;
+  }
+  this.toolBox.remove();
+  this.toolBox = null;
+};
+
+scout.DesktopHeader.prototype._renderToolBoxVisible = function() {
+  if (this.toolBoxVisible) {
+    this._renderToolBox();
+  } else {
+    this._removeToolBox();
+  }
+  this.invalidateLayoutTree();
+};
+
+scout.DesktopHeader.prototype._renderLogoUrl = function() {
+  if (this.logoUrl) {
+    this._renderLogo();
+  } else {
+    this._removeLogo();
+  }
+  this.invalidateLayoutTree();
+};
+
+scout.DesktopHeader.prototype._renderLogo = function() {
+  if (!this.logo) {
+    this.logo = scout.create('DesktopLogo', {
+      parent: this,
+      url: this.logoUrl
+    });
+    this.logo.render(this.$container);
+  } else {
+    this.logo.setUrl(this.logoUrl);
+  }
+};
+
+scout.DesktopHeader.prototype._removeLogo = function() {
+  if (!this.logo) {
+    return;
+  }
+  this.logo.remove();
+  this.logo = null;
+};
+
+scout.DesktopHeader.prototype._renderViewButtonBox = function() {
+  if (this.viewButtonBox) {
+    return;
+  }
+  this.viewButtonBox = scout.create('ViewButtonBox', {
+    parent: this,
+    viewButtons: this.desktop.viewButtons
+  });
+  this.viewButtonBox.render(this.$container);
+  this.viewButtonBox.$container.prependTo(this.$container);
+  if (this.desktop.inBackground) {
+    this.viewButtonBox.sendToBack();
+  }
+  this.updateViewButtonStyling();
+};
+
+scout.DesktopHeader.prototype._removeViewButtonBox = function() {
+  if (!this.viewButtonBox) {
+    return;
+  }
+  this.viewButtonBox.remove();
+  this.viewButtonBox = null;
+};
+
+scout.DesktopHeader.prototype._renderViewButtonBoxVisible = function() {
+  if (this.viewButtonBoxVisible) {
+    this._renderViewButtonBox();
+  } else {
+    this._removeViewButtonBox();
+  }
+  this.invalidateLayoutTree();
+};
+
+scout.DesktopHeader.prototype.sendToBack = function() {
+  if (this.viewButtonBox) {
+    this.viewButtonBox.sendToBack();
+  }
+};
+
+scout.DesktopHeader.prototype.bringToFront = function() {
+  if (this.viewButtonBox) {
+    this.viewButtonBox.bringToFront();
+  }
+};
+
+scout.DesktopHeader.prototype.setLogoUrl = function(logoUrl) {
+  if (this.logoUrl === logoUrl) {
+    return;
+  }
+  this.logoUrl = logoUrl;
+  if (this.rendered) {
+    this._renderLogoUrl();
+  }
+};
+
+scout.DesktopHeader.prototype.setToolBoxVisible = function(visible) {
+  if (this.toolBoxVisible === visible) {
+    return;
+  }
+  this.toolBoxVisible = visible;
+  if (this.rendered) {
+    this._renderToolBoxVisible();
+  }
+};
+
+scout.DesktopHeader.prototype.setViewButtonBoxVisible = function(visible) {
+  if (this.viewButtonBoxVisible === visible) {
+    return;
+  }
+  this.viewButtonBoxVisible = visible;
+  if (this.rendered) {
+    this._renderViewButtonBoxVisible();
+  }
+};
+
+scout.DesktopHeader.prototype.updateViewButtonBoxVisibility = function() {
+  // View buttons are visible in the header if the navigation is not visible
+  // If there are no view buttons at all, don't show the box
+  // With displayStyle is set to compact, the view buttons should never be visible in the header
+  this.setViewButtonBoxVisible(this.desktop.viewButtons.length > 0 && !this.desktop.navigationVisible && this.desktop.displayStyle !== scout.Desktop.DisplayStyle.COMPACT);
+};
+
+scout.DesktopHeader.prototype._attachOutlineContentMenuBarHandler = function() {
+  if (!this.outlineContent) {
+    return;
+  }
+  var menuBar = this._outlineContentMenuBar(this.outlineContent);
+  if (menuBar) {
+    menuBar.on('propertyChange', this._outlineContentMenuBarPropertyChangeHandler);
+  }
+};
+
+scout.DesktopHeader.prototype._detachOutlineContentMenuBarHandler = function() {
+  if (!this.outlineContent) {
+    return;
+  }
+  var menuBar = this._outlineContentMenuBar(this.outlineContent);
+  if (menuBar) {
+    menuBar.off('propertyChange', this._outlineContentMenuBarPropertyChangeHandler);
+  }
+};
+
+scout.DesktopHeader.prototype._outlineContentMenuBar = function(outlineContent) {
+  if (outlineContent instanceof scout.Form) {
+    return outlineContent.rootGroupBox.menuBar;
+  }
+  return outlineContent.menuBar;
+};
+
+scout.DesktopHeader.prototype.updateViewButtonStyling = function() {
+  if (!this.viewButtonBoxVisible || !this.desktop.bench || !this.desktop.bench.outlineContentVisible) {
+    return;
+  }
+  var outlineContent = this.desktop.bench.outlineContent;
+  if (!outlineContent) {
+    // Outline content not available yet (-> needs to be loaded first)
+    return;
+  }
+  var hasMenuBar = false;
+  if (outlineContent instanceof scout.Form) {
+    var rootGroupBox = outlineContent.rootGroupBox;
+    hasMenuBar = rootGroupBox.menuBar && rootGroupBox.menuBarVisible && rootGroupBox.menuBar.visible;
+  } else {
+    hasMenuBar = outlineContent.menuBar && outlineContent.menuBar.visible;
+  }
+  this.viewButtonBox.viewTabs.forEach(function(tab) {
+    tab.$container.toggleClass('outline-content-has-menubar', !!hasMenuBar);
+  }, this);
+  this.viewButtonBox.viewMenuTab.$container.toggleClass('outline-content-has-menubar', !!hasMenuBar);
+};
+
+scout.DesktopHeader.prototype._onDesktopNavigationVisibleChange = function(event) {
+  // If navigation gets visible: Hide view buttons immediately
+  // If navigation gets hidden using animation: Show view buttons when animation ends
+  if (this.desktop.navigationVisible) {
+    this.updateViewButtonBoxVisibility();
+  }
+};
+
+scout.DesktopHeader.prototype._onDesktopAnimationEnd = function(event) {
+  this.updateViewButtonBoxVisibility();
+};
+
+scout.DesktopHeader.prototype.onBenchOutlineContentChange = function(content) {
+  this._detachOutlineContentMenuBarHandler();
+  this.outlineContent = content;
+  this.updateViewButtonStyling();
+  this._attachOutlineContentMenuBarHandler();
+};
+
+scout.DesktopHeader.prototype._onDesktopPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('navigationVisible') !== -1) {
+    this._onDesktopNavigationVisibleChange();
+  }
+};
+
+scout.DesktopHeader.prototype._onOutlineContentMenuBarPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('visible') !== -1) {
+    this.updateViewButtonStyling();
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeaderLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeaderLayout.js
new file mode 100644
index 0000000..3535627
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/DesktopHeaderLayout.js
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopHeaderLayout = function(header) {
+  scout.DesktopHeaderLayout.parent.call(this);
+
+  this.header = header;
+  this.desktop = header.desktop;
+};
+scout.inherits(scout.DesktopHeaderLayout, scout.AbstractLayout);
+
+/**
+ * @override AbstractLayout.js
+ */
+scout.DesktopHeaderLayout.prototype.layout = function($container) {
+  var viewButtonBoxPrefSize, toolBoxPrefSize,
+    htmlContainer = this.header.htmlComp,
+    containerSize = htmlContainer.getSize(),
+    toolBox = this.header.toolBox,
+    viewButtonBox = this.header.viewButtonBox,
+    tabArea = this.header.tabArea,
+    smallTabsPrefSize = tabArea.htmlComp.layout.smallPrefSize(),
+    tabsPrefSize = tabArea.htmlComp.getPreferredSize(),
+    tabsWidth = 0,
+    logoWidth = 0,
+    viewButtonBoxWidth = 0,
+    toolBoxWidth = 0;
+
+  containerSize = containerSize.subtract(htmlContainer.getInsets());
+
+  if (this.header.logo) {
+    logoWidth = scout.graphics.getSize(this.header.logo.$container, true).width;
+  }
+
+  if (viewButtonBox) {
+    viewButtonBoxPrefSize = viewButtonBox.htmlComp.getPreferredSize();
+    viewButtonBoxWidth = viewButtonBoxPrefSize.width;
+    viewButtonBox.htmlComp.setSize(viewButtonBoxPrefSize.subtract(viewButtonBox.htmlComp.getMargins()));
+  }
+  tabArea.htmlComp.$comp.cssLeft(viewButtonBoxWidth);
+
+  if (toolBox) {
+    toolBoxPrefSize = toolBox.htmlComp.getPreferredSize();
+    toolBoxWidth = toolBoxPrefSize.width;
+    setToolBoxSize();
+    setToolBoxLocation();
+  }
+
+  tabsWidth = calcTabsWidth();
+  if (smallTabsPrefSize.width <= tabsWidth) {
+    // All tabs fit when they have small size -> use available size but max the pref size -> prefSize = size of maximumtabs if tabs use their large (max) size
+    tabsWidth = Math.min(tabsPrefSize.width, tabsWidth);
+    tabArea.htmlComp.setSize(new scout.Dimension(tabsWidth, tabsPrefSize.height));
+    return;
+  }
+
+  // 1st try to minimize padding around tool-bar items -> compact mode
+  if (toolBox) {
+    toolBoxPrefSize = toolBox.htmlComp.layout.compactPrefSize();
+    toolBoxWidth = toolBoxPrefSize.width;
+    setToolBoxSize();
+    setToolBoxLocation();
+  }
+
+  tabsWidth = calcTabsWidth();
+  if (smallTabsPrefSize.width <= tabsWidth) {
+      tabArea.htmlComp.setSize(smallTabsPrefSize);
+    setTabsSize();
+    return;
+  }
+
+  // 2nd remove text from tool-bar items, only show icon
+  if (toolBox) {
+    toolBoxPrefSize = toolBox.htmlComp.layout.shrinkPrefSize();
+    toolBoxWidth = toolBoxPrefSize.width;
+    setToolBoxSize();
+    setToolBoxLocation();
+  }
+
+  tabsWidth = calcTabsWidth();
+  tabsWidth = Math.max(Math.min(smallTabsPrefSize.width, tabsWidth), scout.SimpleTabAreaLayout.OVERFLOW_MENU_WIDTH);
+  setTabsSize();
+
+  // 3rd if only the overflow menu is shown make toolBox smaller so that ellipsis may be displayed
+  if (toolBox && tabsWidth <= scout.SimpleTabAreaLayout.OVERFLOW_MENU_WIDTH) {
+    // layout toolBox, now an ellipsis menu may be shown
+    toolBoxWidth = containerSize.width - tabsWidth - logoWidth - viewButtonBoxWidth;
+    setToolBoxSize();
+
+    // update size of the toolBox again with the actual width to make it correctly right aligned
+    toolBoxWidth = toolBox.htmlComp.layout.actualPrefSize().width;
+    setToolBoxSize();
+    setToolBoxLocation();
+  }
+
+  function calcTabsWidth() {
+    return containerSize.width - toolBoxWidth - logoWidth - viewButtonBoxWidth;
+  }
+
+  function setTabsSize() {
+    tabArea.htmlComp.setSize(new scout.Dimension(tabsWidth, tabsPrefSize.height));
+  }
+
+  function setToolBoxSize() {
+    toolBox.htmlComp.setSize(new scout.Dimension(toolBoxWidth, toolBoxPrefSize.height).subtract(toolBox.htmlComp.getMargins()));
+  }
+
+  function setToolBoxLocation() {
+    toolBox.htmlComp.$comp.cssLeft(containerSize.width - toolBoxWidth - logoWidth);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/HeaderTabBoxController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/HeaderTabBoxController.js
new file mode 100644
index 0000000..f392733
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/header/HeaderTabBoxController.js
@@ -0,0 +1,68 @@
+/*******************************************************************************
+
+* Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+
+/**
+ * The {@link {@link scout.HeaderViewTabAreaController}} is used to link the center {@link {@link scout.SimpleTabBox}} (all forms with displayViewId='C')
+ * with a {@link {@link scout.SimpleTabArea}} placed in the header.
+ * It is an extension of {@link {@link scout.SimpleTabBoxController}}.
+ *
+ * @see scout.SimpleTabBoxController
+ */
+scout.HeaderTabBoxController = function(bench, tabArea) {
+  this.bench = bench;
+
+  // event listeners
+  this._tabBoxChangedHandler = this._onViewsChanged.bind(this);
+
+  scout.HeaderTabBoxController.parent.call(this, bench.getTabBox('C'), tabArea);
+
+  this.tabAreaCenter = bench.getTabBox('C').tabArea;
+  this.tabAreaInHeader;
+
+};
+scout.inherits(scout.HeaderTabBoxController, scout.SimpleTabBoxController);
+
+scout.HeaderTabBoxController.prototype._installListeners = function() {
+  scout.HeaderTabBoxController.parent.prototype._installListeners.call(this);
+  this.bench.on('viewAdded', this._tabBoxChangedHandler);
+  this.bench.on('viewRemoved', this._tabBoxChangedHandler);
+};
+
+scout.HeaderTabBoxController.prototype._onViewsChanged = function() {
+  if (this.bench.getViews().some(function(view) {
+      return 'C' !== view.displayViewId;
+    })) {
+    // has views in other view stacks
+    this._setViewTabAreaInHeader(false);
+  } else {
+    // has only views in center
+    this._setViewTabAreaInHeader(true);
+  }
+};
+
+scout.HeaderTabBoxController.prototype._setViewTabAreaInHeader = function(inHeader) {
+  if (this.tabAreaInHeader === inHeader) {
+    return;
+  }
+  this.tabAreaInHeader = inHeader;
+  this.tabAreaCenter.setVisible(!inHeader);
+  this.tabArea.setVisible(inHeader);
+};
+
+
+scout.HeaderTabBoxController.prototype.getTabs = function() {
+  if(this.tabAreaInHeader){
+    return this.tabArea.getTabs();
+  }
+  return this.tabAreaCenter.getTabs();
+
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.css
similarity index 65%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.css
index 069a6cd..5d2ba9a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNavigation.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.css
@@ -8,30 +8,26 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-@view-buttons-height: 50px;
+@view-button-box-height: 50px;
 
 .desktop-navigation {
   position: relative;
   height: 100%;
-  width: @size-desktop-navigation;
+  width: @desktop-navigation-width;
+  min-width: @desktop-navigation-min-width;
   background-color: @navigation-background-color;
   color: @navigation-color;
 }
 
-.navigation-breadcrumb {
-  width: @size-desktop-navigation-breadcrumb;
+.desktop-navigation-breadcrumb {
+  width: @desktop-navigation-breadcrumb-width;
 }
 
-.navigation-container {
-  position: relative;
-  width: 100%;
-  height: calc(~'100%' - @view-buttons-height);
+.navigation-body {
+  position: absolute;
 }
 
-.view-buttons {
-  width: 100%;
-  height: @view-buttons-height;
-  white-space: nowrap;
-  #scout.font-text-large();
-  overflow: hidden;
+.desktop-navigation > .desktop-tool-box {
+  background-color: @palette-white;
+  text-align: right;
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.js
new file mode 100644
index 0000000..d468fe7
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigation.js
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopNavigation = function() {
+  scout.DesktopNavigation.parent.call(this);
+  this.$container;
+  this.$body;
+  this.viewButtonBox;
+  this._outlinePropertyChangeHandler = this._onOutlinePropertyChange.bind(this);
+  this._desktopPropertyChangeHandler = this._onDesktopPropertyChange.bind(this);
+};
+scout.inherits(scout.DesktopNavigation, scout.Widget);
+
+scout.DesktopNavigation.DEFAULT_STYLE_WIDTH; // Configured in sizes.css
+scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH; // Configured in sizes.css
+scout.DesktopNavigation.MIN_WIDTH; // Configured in sizes.css
+
+scout.DesktopNavigation.prototype._init = function(model) {
+  scout.DesktopNavigation.parent.prototype._init.call(this, model);
+  scout.DesktopNavigation.MIN_WIDTH = $.pxToNumber(scout.styles.get('desktop-navigation', 'min-width').minWidth);
+  scout.DesktopNavigation.DEFAULT_STYLE_WIDTH = $.pxToNumber(scout.styles.get('desktop-navigation', 'width').width);
+  scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH = $.pxToNumber(scout.styles.get('desktop-navigation-breadcrumb', 'width').width);
+  this.desktop = this.parent;
+  this.layoutData = model.layoutData || {};
+  this.toolBoxVisible = scout.nvl(model.toolBoxVisible, false);
+  this.updateHandleVisibility();
+  this.setOutline(model.outline);
+};
+
+scout.DesktopNavigation.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('desktop-navigation');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.DesktopNavigationLayout(this));
+  this.htmlComp.layoutData = this.layoutData;
+
+  this.$body = this.$container.appendDiv('navigation-body')
+    .on('mousedown', this._onNavigationBodyMousedown.bind(this));
+  this.htmlCompBody = new scout.HtmlComponent(this.$body, this.session);
+  this.htmlCompBody.setLayout(new scout.SingleLayout());
+
+  this.desktop.on('propertyChange', this._desktopPropertyChangeHandler);
+};
+
+scout.DesktopNavigation.prototype._remove = function() {
+  this.desktop.off('propertyChange', this._desktopPropertyChangeHandler);
+  scout.DesktopNavigation.parent.prototype._remove.call(this);
+};
+
+scout.DesktopNavigation.prototype._renderProperties = function() {
+  this._renderViewButtonBox();
+  this._renderToolBoxVisible();
+  this._renderOutline();
+  this._renderHandleVisible();
+};
+
+scout.DesktopNavigation.prototype._renderViewButtonBox = function() {
+  if (this.desktop.viewButtons.length === 0) {
+    return;
+  }
+  this.viewButtonBox = scout.create('ViewButtonBox', {
+    parent: this,
+    viewButtons: this.desktop.viewButtons
+  });
+  this.viewButtonBox.render(this.$container);
+};
+
+scout.DesktopNavigation.prototype._renderOutline = function() {
+  if (!this.outline) {
+    return;
+  }
+  this.outline.setParent(this);
+  this.outline.render(this.$body);
+  this.outline.validateRoot = true;
+  this.outline.invalidateLayoutTree();
+  // Layout immediate to prevent flickering when breadcrumb mode is enabled
+  // but not initially while desktop gets rendered because it will be done at the end anyway
+  if (this.rendered) {
+    this.outline.validateLayoutTree();
+    this.outline.validateFocus();
+  }
+};
+
+scout.DesktopNavigation.prototype.setOutline = function(outline) {
+  var currentDisplayStyle;
+  if (this.outline === outline) {
+    return;
+  }
+  if (this.outline) {
+    currentDisplayStyle = this.outline.displayStyle;
+    if (this.rendered) {
+      this.outline.remove();
+    }
+  }
+
+  this.outline = outline;
+  if (this.outline) {
+    this.outline.setBreadcrumbTogglingThreshold(scout.DesktopNavigation.BREADCRUMB_STYLE_WIDTH);
+    // Make sure new outline uses same display style as old
+    if (currentDisplayStyle && this.outline.autoToggleBreadcrumbStyle) {
+      this.outline.setDisplayStyle(currentDisplayStyle);
+    }
+    this.outline.inBackground = this.desktop.inBackground;
+    this.outline.on('propertyChange', this._outlinePropertyChangeHandler);
+    this._updateHandle();
+    if (this.rendered) {
+      this._renderOutline();
+    }
+  }
+};
+
+scout.DesktopNavigation.prototype.sendToBack = function() {
+  this.viewButtonBox.sendToBack();
+  if (this.outline) {
+    this.outline.sendToBack();
+  }
+};
+
+scout.DesktopNavigation.prototype.bringToFront = function() {
+  this.viewButtonBox.bringToFront();
+  if (this.outline) {
+    this.outline.bringToFront();
+  }
+};
+
+scout.DesktopNavigation.prototype.setToolBoxVisible = function(toolBoxVisible) {
+  this.toolBoxVisible = toolBoxVisible;
+  if (this.rendered) {
+    this._renderToolBoxVisible();
+  }
+};
+
+scout.DesktopNavigation.prototype.setHandleVisible = function(visible) {
+  if (this.handleVisible === visible) {
+    return;
+  }
+  this.handleVisible = visible;
+  if (this.rendered) {
+    this._renderHandleVisible();
+  }
+};
+
+scout.DesktopNavigation.prototype._updateHandle = function() {
+  if (this.handle) {
+    this.handle.setRightVisible(this.desktop.outlineDisplayStyle() === scout.Tree.DisplayStyle.BREADCRUMB);
+  }
+};
+
+scout.DesktopNavigation.prototype.updateHandleVisibility = function() {
+  // Don't show handle if desktop says handle must not be visible
+  this.setHandleVisible(this.desktop.navigationHandleVisible);
+};
+
+scout.DesktopNavigation.prototype._renderToolBoxVisible = function() {
+  if (this.toolBoxVisible) {
+    this._renderToolBox();
+  } else {
+    this._removeToolBox();
+  }
+};
+
+scout.DesktopNavigation.prototype._renderToolBox = function() {
+  if (this.toolBox) {
+    return;
+  }
+  this.toolBox = scout.create('DesktopToolBox', {
+    parent: this,
+    menus: this.desktop.menus
+  });
+  this.toolBox.render(this.$container);
+};
+
+scout.DesktopNavigation.prototype._removeToolBox = function() {
+  if (!this.toolBox) {
+    return;
+  }
+  this.toolBox.remove();
+  this.toolBox = null;
+};
+
+scout.DesktopNavigation.prototype._renderHandleVisible = function() {
+  if (this.handleVisible) {
+    this._renderHandle();
+  } else {
+    this._removeHandle();
+  }
+};
+
+scout.DesktopNavigation.prototype._renderHandle = function() {
+  if (this.handle) {
+    return;
+  }
+  this.handle = scout.create('DesktopNavigationHandle', {
+    parent: this
+  });
+  this.handle.render(this.$container);
+  this.handle.$container.addClass('navigation-open');
+  this.handle.on('action', this._onHandleAction.bind(this));
+  this._updateHandle();
+};
+
+scout.DesktopNavigation.prototype._removeHandle = function() {
+  if (!this.handle) {
+    return;
+  }
+  this.handle.remove();
+  this.handle = null;
+};
+
+scout.DesktopNavigation.prototype._onNavigationBodyMousedown = function(event) {
+  this.desktop.bringOutlineToFront();
+};
+
+scout.DesktopNavigation.prototype._onOutlinePropertyChange = function(event) {
+  if (event.changedProperties.indexOf('displayStyle') !== -1) {
+    this._updateHandle();
+  }
+};
+
+scout.DesktopNavigation.prototype._onDesktopPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('navigationHandleVisible') !== -1) {
+    this.updateHandleVisibility();
+  }
+};
+
+scout.DesktopNavigation.prototype._onHandleAction = function(event) {
+  if (event.left) {
+    this.desktop.shrinkNavigation();
+  } else {
+    this.desktop.enlargeNavigation();
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.css
new file mode 100644
index 0000000..23d384b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.css
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+ .desktop-navigation-handle.collapse-handle {
+  position: absolute;
+
+  &.navigation-open {
+    left: auto;
+    margin-right: 5px;
+    right: 0;
+  }
+
+  &.navigation-closed {
+    left: 0;
+    right: auto;
+    padding-left: 1px;
+    margin-bottom: 36px;
+  }
+
+  &:active > .collapse-handle-body {
+    background-color: @desktop-navigation-handle-active-background-color;
+  }
+
+  & > .collapse-handle-body {
+    background-color: @desktop-navigation-handle-background-color;
+    border-color: fade(@desktop-navigation-handle-border-color, 75%);
+    color: fade(@desktop-navigation-handle-color, 75%);
+  }
+}
+
+.navigation-handle-key-box {
+  margin-top: -6px;
+
+  &.left {
+    margin-right: -4px;
+  }
+
+  &.right {
+    margin-left: -4px;
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.js
new file mode 100644
index 0000000..dd381f9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationHandle.js
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopNavigationHandle = function() {
+  scout.DesktopNavigationHandle.parent.call(this);
+};
+scout.inherits(scout.DesktopNavigationHandle, scout.CollapseHandle);
+
+scout.DesktopNavigationHandle.prototype._initKeyStrokeContext = function(keyStrokeContext) {
+  scout.DesktopNavigationHandle.parent.prototype._initKeyStrokeContext.call(this, keyStrokeContext);
+
+  // Bound to desktop
+  this.desktopKeyStrokeContext = new scout.KeyStrokeContext();
+  this.desktopKeyStrokeContext.invokeAcceptInputOnActiveValueField = true;
+  this.desktopKeyStrokeContext.$bindTarget = this.session.desktop.$container;
+  this.desktopKeyStrokeContext.$scopeTarget = this.$container;
+  this.desktopKeyStrokeContext.registerKeyStroke([
+    new scout.ShrinkNavigationKeyStroke(this),
+    new scout.EnlargeNavigationKeyStroke(this)
+  ]);
+};
+
+scout.DesktopNavigationHandle.prototype._render = function($parent) {
+  scout.DesktopNavigationHandle.parent.prototype._render.call(this, $parent);
+  this.$container.addClass('desktop-navigation-handle');
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationLayout.js
new file mode 100644
index 0000000..7fb1a51
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/DesktopNavigationLayout.js
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopNavigationLayout = function(navigation) {
+  scout.DesktopNavigationLayout.parent.call(this);
+  this.navigation = navigation;
+};
+scout.inherits(scout.DesktopNavigationLayout, scout.AbstractLayout);
+
+scout.DesktopNavigationLayout.prototype.layout = function($container) {
+  var bodySize, viewButtonBoxSize, viewButtonBoxPrefSize,
+    htmlContainer = this.navigation.htmlComp,
+    containerSize = htmlContainer.getSize(),
+    htmlBody = this.navigation.htmlCompBody,
+    toolBox = this.navigation.toolBox,
+    viewButtonBox = this.navigation.viewButtonBox,
+    viewButtonBoxHeight = 0,
+    viewButtonBoxWidth = 0;
+
+  containerSize = containerSize.subtract(htmlContainer.getInsets());
+
+  if (viewButtonBox) {
+    viewButtonBoxPrefSize = viewButtonBox.htmlComp.getPreferredSize();
+    viewButtonBoxHeight = viewButtonBoxPrefSize.height;
+    viewButtonBoxWidth = containerSize.width;
+    if (toolBox) {
+      viewButtonBoxWidth = viewButtonBoxPrefSize.width;
+    }
+
+    viewButtonBoxSize = new scout.Dimension(viewButtonBoxWidth, viewButtonBoxHeight)
+      .subtract(viewButtonBox.htmlComp.getMargins());
+    viewButtonBox.htmlComp.setSize(viewButtonBoxSize);
+  }
+
+  if (toolBox) {
+    toolBox.$container.cssLeft(viewButtonBoxWidth);
+    toolBox.htmlComp.setSize(new scout.Dimension(containerSize.width - viewButtonBoxWidth, viewButtonBoxHeight));
+  }
+
+  bodySize = new scout.Dimension(containerSize.width, containerSize.height - viewButtonBoxHeight)
+    .subtract(htmlBody.getMargins());
+  htmlBody.setSize(bodySize);
+  htmlBody.$comp.cssTop(viewButtonBoxHeight);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/EnlargeNavigationKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/EnlargeNavigationKeyStroke.js
new file mode 100644
index 0000000..bf9284f
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/EnlargeNavigationKeyStroke.js
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.EnlargeNavigationKeyStroke = function(handle) {
+  scout.EnlargeNavigationKeyStroke.parent.call(this);
+  this.field = handle;
+  this.desktop = handle.session.desktop;
+  this.ctrl = true;
+  this.shift = true;
+  this.which = [scout.keys.ANGULAR_BRACKET];
+  this.renderingHints.$drawingArea = function($drawingArea, event) {
+    return this.desktop.$container;
+  }.bind(this);
+};
+scout.inherits(scout.EnlargeNavigationKeyStroke, scout.KeyStroke);
+
+scout.EnlargeNavigationKeyStroke.prototype._isEnabled = function() {
+  var enabled = scout.EnlargeNavigationKeyStroke.parent.prototype._isEnabled.call(this);
+  return enabled && this.field.rightVisible;
+};
+
+scout.EnlargeNavigationKeyStroke.prototype.handle = function(event) {
+  this.desktop.enlargeNavigation();
+};
+
+scout.EnlargeNavigationKeyStroke.prototype._postRenderKeyBox = function($drawingArea, $keyBox) {
+  var handleOffset, keyBoxLeft, keyBoxTop,
+    handle = this.field;
+
+  $keyBox.addClass('navigation-handle-key-box right');
+
+  handleOffset = handle.$right.offsetTo(this.desktop.$container);
+  keyBoxLeft = handleOffset.left + handle.$right.outerWidth();
+  keyBoxTop = handleOffset.top;
+
+  $keyBox.cssLeft(keyBoxLeft)
+    .cssTop(keyBoxTop);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/ShrinkNavigationKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/ShrinkNavigationKeyStroke.js
new file mode 100644
index 0000000..27e64ee
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/navigation/ShrinkNavigationKeyStroke.js
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.ShrinkNavigationKeyStroke = function(handle) {
+  scout.ShrinkNavigationKeyStroke.parent.call(this);
+  this.field = handle;
+  this.desktop = handle.session.desktop;
+  this.ctrl = true;
+  this.which = [scout.keys.ANGULAR_BRACKET];
+  this.renderingHints.$drawingArea = function($drawingArea, event) {
+    return this.desktop.$container;
+  }.bind(this);
+};
+scout.inherits(scout.ShrinkNavigationKeyStroke, scout.KeyStroke);
+
+scout.ShrinkNavigationKeyStroke.prototype._isEnabled = function() {
+  var enabled = scout.ShrinkNavigationKeyStroke.parent.prototype._isEnabled.call(this);
+  return enabled && this.field.leftVisible;
+};
+
+scout.ShrinkNavigationKeyStroke.prototype.handle = function(event) {
+  this.desktop.shrinkNavigation();
+};
+
+scout.ShrinkNavigationKeyStroke.prototype._postRenderKeyBox = function($drawingArea, $keyBox) {
+  var handleOffset, keyBoxLeft, keyBoxTop,
+    handle = this.field;
+
+  $keyBox.addClass('navigation-handle-key-box left');
+
+  handleOffset = handle.$left.offsetTo(this.desktop.$container);
+  keyBoxLeft = handleOffset.left - $keyBox.outerWidth(true);
+  keyBoxTop = handleOffset.top;
+
+  $keyBox.cssLeft(keyBoxLeft)
+    .cssTop(keyBoxTop);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.css
similarity index 77%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.css
index 78bfe47..82fca51 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.css
@@ -18,9 +18,9 @@
  * notifications.
  */
 .keyframes-notification-slide-in() {
-  0%   { left: 250px; margin-bottom: 0;   }
-  80%  { left: 15px;                      }
-  100% { left: 0;     margin-bottom: 20px;}
+  00%   { left: 250px; margin-bottom: 0; }
+  80%  { left: 15px; }
+  100% { left: 0; margin-bottom: 20px; }
 }
 
 .animation-notification-slide-in() {
@@ -40,8 +40,8 @@
 @keyframes notification-fade-out { .keyframes-notification-fade-out(); }
 
 .keyframes-notification-fade-out() {
-  0%   { opacity: 1.0; margin-bottom:  20px; }
-  100% { opacity:   0; margin-bottom: -37px; }
+  00%   { opacity: 1.0; margin-bottom: 20px; }
+  100% { opacity: 0; margin-bottom: -37px; }
 }
 
 .animation-notification-fade-out() {
@@ -79,27 +79,17 @@
   &.error {
     border-left-color: @palette-red-3;
   }
+}
 
-  & > .notification-content {
-    border: 1px solid @border-color;
-    border-left-width: 0;
-    padding: 10px;
+.notification-content {
+  border: 1px solid @border-color;
+  border-left-width: 0;
+  padding: 10px;
 
-    & > .close {
-      position: absolute;
-      right: 10px;
-      top: 10px;
-      color: @icon-light-color;
-
-      &:hover {
-        color: @icon-color;
-        cursor: pointer;
-      }
-      &::before {
-        #scout.font-icon();
-        content: @icon-remove;
-      }
-    }
+  & > .closer {
+    position: absolute;
+    right: 10px;
+    top: 10px;
   }
 }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.js
similarity index 92%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.js
index 924cba2..401482b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DesktopNotification.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/DesktopNotification.js
@@ -1,6 +1,6 @@
 scout.DesktopNotification = function() {
   scout.DesktopNotification.parent.call(this);
-  this.closeable = true;
+  this.closable = true;
   this._removeTimeout;
   this._removing = false;
 };
@@ -16,7 +16,7 @@
   this.id = model.id;
   this.duration = model.duration;
   this.status = model.status;
-  this.closeable = scout.nvl(model.closeable, true);
+  this.closable = scout.nvl(model.closable, true);
   this.desktop = this.parent;
 };
 
@@ -25,7 +25,7 @@
  */
 scout.DesktopNotification.prototype._renderProperties = function() {
   this._renderMessage();
-  this._renderCloseable();
+  this._renderClosable();
 };
 
 scout.DesktopNotification.prototype._render = function($parent) {
@@ -57,10 +57,10 @@
       this.status.message : '');
 };
 
-scout.DesktopNotification.prototype._renderCloseable = function() {
-  if (this.closeable) {
+scout.DesktopNotification.prototype._renderClosable = function() {
+  if (this.closable) {
     this.$content
-      .appendDiv('close')
+      .appendDiv('closer')
       .on('click', this._onCloseIconClick.bind(this));
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/OfflineDesktopNotification.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/OfflineDesktopNotification.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/OfflineDesktopNotification.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/notification/OfflineDesktopNotification.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/AbstractOutlineNavigationKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/AbstractOutlineNavigationKeyStroke.js
deleted file mode 100644
index a2fe381..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/AbstractOutlineNavigationKeyStroke.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.AbstractOutlineNavigationKeyStroke = function(tree) {
-  scout.AbstractOutlineNavigationKeyStroke.parent.call(this);
-  this.field = tree;
-  this.stopPropagation = true;
-  this.renderingHints.hAlign = scout.hAlign.RIGHT;
-
-  this.ctrl = true;
-  this.shift = true;
-
-  this.keyStrokeMode = scout.keyStrokeMode.DOWN;
-};
-scout.inherits(scout.AbstractOutlineNavigationKeyStroke, scout.KeyStroke);
-
-scout.AbstractOutlineNavigationKeyStroke.prototype._accept = function(event) {
-  var accepted = scout.AbstractOutlineNavigationKeyStroke.parent.prototype._accept.call(this, event);
-  if (!accepted) {
-    return false;
-  }
-
-  var $currentNode = this.field.$selectedNodes().eq(0);
-  event._$treeCurrentNode = $currentNode;
-  event._treeCurrentNode = $currentNode.data('node');
-  return true;
-};
-
-scout.AbstractOutlineNavigationKeyStroke.prototype.handle = function(event) {
-  var newNodeSelection = this._handleInternal(event._$treeCurrentNode, event._treeCurrentNode);
-  if (newNodeSelection) {
-    this.field.selectNodes(newNodeSelection, true, true);
-    this.field.scrollTo(newNodeSelection);
-    this.field.handleOutlineContentDebounced(true);
-  }
-};
-
-scout.AbstractOutlineNavigationKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  throw new Error('method must be overwritten by subclass');
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DetailTableTreeFilter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/DetailTableTreeFilter.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DetailTableTreeFilter.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/DetailTableTreeFilter.js
index 1814e36..3a56991 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/DetailTableTreeFilter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/DetailTableTreeFilter.js
@@ -15,8 +15,6 @@
  * Must correspond with logic in P_TableFilterBasedTreeNodeFilter
  */
 scout.DetailTableTreeFilter.prototype.accept = function(node) {
-  var row;
-
   if (!node.parentNode) {
     // top level nodes may not be filtered
     return true;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.css
index a56340e..e30e03a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.css
@@ -8,121 +8,148 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-@breadcrumb-border-color: @outline-selection-background-color;
-@outline-title-border-color: @outline-selection-background-color;
+@outline-breadcrumb-node-padding-v: 12px;
 @outline-title-margin-left: 12px;
 @outline-title-margin-right: 12px;
 @outline-title-margin-bottom: 12px;
+@compact-outline-node-padding-h: 16px;
+@compact-outline-node-padding-v: @outline-breadcrumb-node-padding-v;
 
-/* we have to combine this with .outline, otherwise the definition would not be specific enough */
-.outline.tree {
-  & .scrollbar-thumb {
-    background-color: fade(@scrollbar-thumb-inverted-color, 30%);
-  }
+.outline {
 
-  & .scrollbar-thumb-move,
-  & .scrollbar-thumb:hover {
-    background-color: fade(@scrollbar-thumb-inverted-color, 60%);
-  }
-
-  &.in-background .tree-node.selected {
+  &.in-background > .tree-data > .tree-node.selected {
     background-color: @outline-in-background-selection-background-color;
     color: @palette-white;
   }
 
-  & > .outline-title {
-    #scout.font-text-large();
-    #scout.overflow-ellipsis-nowrap();
-    margin: 0 @outline-title-margin-right @outline-title-margin-bottom @outline-title-margin-left;
-    border-bottom: 1px solid @outline-title-border-color;
+  & > .tree-data  {
+    & > .scrollbar {
+      &.y-axis {
+        margin-right: 6px;
+      }
+
+      & > .scrollbar-thumb {
+        background-color: fade(@scrollbar-thumb-inverted-color, 30%);
+      }
+
+      & > .scrollbar-thumb-move,
+      & > .scrollbar-thumb:hover {
+        background-color: fade(@scrollbar-thumb-inverted-color, 60%);
+      }
+    }
 
     & > .key-box {
-      top: 19px;
+      top: 7px !important;
     }
 
-    & > .outline-title-text {
-      padding: 21px 2px 13px 6px;
+    & > .tree-node,
+    & > .animation-wrapper > .tree-node {
       cursor: pointer;
-      display: block;
-      width: auto;
-    }
+      border: 0;
 
-    & > .menubar {
-      display: block;
-      background-color: @navigation-background-color;
-      width: auto;
-      position: absolute;
-      right: @outline-title-margin-right;
-      top: @outline-title-margin-bottom;
-      border: none;
+      /* leave some space for the scrollbar */
+      padding-right: 8px;
+      /* set top/bottom padding for item */
+      padding-top: 8px;
+      padding-bottom: 8px;
+
+      &.group {
+        background-color: @outline-group-background-color;
+      }
+
+      &.selected {
+        color: @outline-selection-color;
+        background-color: @outline-selection-background-color;
+        border: 0;
+      }
+
+      & > .text {
+        font-size: @font-size-plus;
+      }
+
+      & > .menubar {
+        border: 0;
+        background-color: inherit;
+      }
+
+      & > .tree-node-control {
+        /* adjust control position */
+        margin-left: -@outline-node-control-size - 5px;
+        margin-top: -3px;
+
+        width: @outline-node-control-size;
+        height: @outline-node-control-size;
+        line-height: @outline-node-control-size;
+
+        &::before {
+          font-size: @outline-node-control-size;
+          /* always use same color as the tree-node label */
+          color: inherit;
+        }
+
+        &:hover::before {
+          color: @highlight-color;
+        }
+      }
+    }
+  }
+}
+
+.outline-title {
+  #scout.font-text-large();
+  #scout.overflow-ellipsis-nowrap();
+  margin: 0 @outline-title-margin-right @outline-title-margin-bottom @outline-title-margin-left;
+  border-bottom: 1px solid @outline-title-border-color;
+
+  & > .key-box {
+    top: 19px;
+  }
+
+  & > .menubar {
+    display: block;
+    background-color: @navigation-background-color;
+    width: auto;
+    position: absolute;
+    right: @outline-title-margin-right;
+    top: @outline-title-margin-bottom + 2; /* + 2 necessary to have it aligned with the text*/
+    border: none;
+    color: @navigation-color;
+
+    & > .menubox > .menu-item:not(.disabled) {
       color: @navigation-color;
 
-      & > .menubox > .menu-item:not(.disabled) {
+      &:hover,
+      &:active {
         color: @navigation-color;
       }
 
-      & > .menubox > .menu-item:not(.menu-textandicon):focus::after  {
-        #scout.focus-border-inverted();
+      &:focus,
+      &:not(.menu-button):focus {
+        color: @navigation-color;
+
+        &::after {
+          border-color: @navigation-color;
+          #scout.glow(@navigation-color);
+        }
       }
     }
+
+    & > .menubox > .menu-item:not(.menu-textandicon):focus::after  {
+      #scout.focus-border-inverted();
+    }
   }
 }
 
-.outline > .tree-data {
-  & > .scrollbar.y-axis {
-    margin-right: 6px;
-  }
-
-  & > .key-box {
-    top: 7px !important;
-  }
-
-  & > .tree-node,
-  & > .animation-wrapper > .tree-node {
-    #scout.font-text-plus();
-    cursor: pointer;
-    border: 0;
-
-    /* leave some space for the scrollbar */
-    padding-right: 8px;
-    /* set top/bottom padding for item */
-    padding-top: 8px;
-    padding-bottom: 8px;
-
-    &.group {
-      background-color: @outline-group-background-color;
-    }
-
-    &.selected {
-      color: @outline-selection-color;
-      background-color: @outline-selection-background-color;
-      border: 0;
-    }
-
-     & > .tree-node-control {
-      /* adjust control position */
-      margin-left: -@outline-node-control-size - 5px;
-      margin-top: -3px;
-
-      width: @outline-node-control-size;
-      height: @outline-node-control-size;
-      line-height: @outline-node-control-size;
-
-      &::before {
-        font-size: @outline-node-control-size;
-        /* always use same color as the tree-node label */
-        color: inherit;
-      }
-
-      &:hover::before {
-        color: @highlight-color;
-      }
-    }
-  }
+.outline-title-text {
+  /* outline title height should be the same as main menubar and desktop header height (if there are no view buttons visible) */
+  padding: 20px 2px 12px 6px;
+  cursor: pointer;
+  display: block;
+  width: auto;
 }
 
-/* bread crumb mode */
-.outline.breadcrumb {
+/* bread crumb style (different colors and bigger font and arrow than original breadcrumb style) */
+.outline.tree.breadcrumb {
 
   & > .outline-title {
     text-align: center;
@@ -132,71 +159,122 @@
   & > .tree-data {
     & > .tree-node,
     & > .animation-wrapper > .tree-node {
-      overflow: visible;
-      white-space: normal;
-      text-align: center;
-
-      display: none;
-      border-bottom: 1px solid @breadcrumb-border-color;
+      border-bottom: 1px solid @outline-breadcrumb-border-color;
 
       /* !important is necessary here to override the element specific left-padding (calculated by Tree.js for level indentation). */
-      padding: 12px 2px !important;
+      padding: @outline-breadcrumb-node-padding-v 2px !important;
 
       &.ancestor-of-selected,
       &.child-of-selected,
       &.selected {
-        #scout.font-text-plus();
-        display: block;
         background-color: @outline-group-background-color;
       }
 
+      &:active {
+        background-color: @navigation-background-color;
+      }
+
       &.selected {
         background-color: @outline-selection-background-color;
         color: @outline-selection-color;
         cursor: default;
       }
 
-      /* arrow is created using ::before and ::after*/
-      &.ancestor-of-selected::before,
-      &.ancestor-of-selected::after,
-      &.selected::before {
-        position: absolute;
-        left: 50%;
-        margin-left: -13px;
-        border: solid transparent;
-        content: '';
-        height: 0;
-        width: 0;
-        z-index: 1;
-      }
-
       &.ancestor-of-selected::before {
-        border-color: @outline-selection-background-color transparent transparent transparent;
+        border-top-color: @outline-selection-background-color;
         border-width: 8px 13px 0 13px;
         bottom: -9px;
       }
 
       &.ancestor-of-selected::after {
-        border-color: @outline-group-background-color transparent transparent transparent;
+        border-top-color: @outline-group-background-color;
         border-width: 8px 13px 0 13px;
         bottom: -8px;
       }
 
       &.selected::before {
-        border-color: @outline-selection-background-color transparent transparent transparent;
+        border-top-color: @outline-selection-background-color;
         border-width: 8px 13px 0 13px;
         bottom: -8px;
       }
 
-      &.ancestor-of-selected.leaf::before,
-      &.ancestor-of-selected.leaf::after,
-      &.selected.leaf::before {
-        display: none;
+      &.selected::after {
+        border: 0;
       }
     }
 
-    & > .tree-node-control {
-      display: none;
+    &.has-detail-content > .tree-node.selected,
+    &.has-detail-content > .animation-wrapper > .tree-node.selected {
+      & > .text {
+        font-weight: bold;
+      }
+    }
+  }
+
+  &:focus > .tree-data,
+  &.focused > .tree-data {
+    & > .tree-node,
+    & > .animation-wrapper > .tree-node {
+
+      &.parent-of-selected {
+        border-color: @outline-breadcrumb-border-color;
+      }
+
+      &.parent-of-selected::before {
+        border: 0;
+      }
+
+      &.selected {
+        border-color: @outline-breadcrumb-border-color;
+      }
+
+      &.selected::before {
+        border-top-color: @outline-selection-background-color;
+      }
+    }
+  }
+}
+
+.compact.outline.breadcrumb {
+  & > .outline-title {
+    text-align: left;
+
+    & > .outline-title-text {
+      padding-left: @compact-outline-node-padding-h;
+    }
+  }
+
+  & > .tree-data {
+
+    & > .tree-node  {
+      text-align: left;
+      padding: 0 !important;
+
+      & > .text {
+        display: inline-block;
+        padding: @compact-outline-node-padding-v @compact-outline-node-padding-h;
+      }
+
+      & > .node-menubar {
+        position: absolute;
+        right: 0;
+        top: 0;
+        width: auto;
+        padding: @compact-outline-node-padding-v - 3px @compact-outline-node-padding-h 0 0;
+      }
+
+      & > .detail-menubar {
+        padding: 0 @compact-outline-node-padding-h @compact-outline-node-padding-v @compact-outline-node-padding-h;
+      }
+
+      & > .form > .root-group-box > .group-box-body {
+        padding-left: @compact-outline-node-padding-h - @mandatory-indicator-width;
+        padding-right: @compact-outline-node-padding-h;
+      }
+    }
+
+    &.detail-content-visible > .tree-node > .menubar {
+      padding-bottom: 0;
     }
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
index 2ffaad3..7e5e5bb 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
@@ -11,28 +11,48 @@
 scout.Outline = function() {
   scout.Outline.parent.call(this);
   this._addAdapterProperties(['defaultDetailForm', 'views', 'dialogs', 'messageBoxes', 'fileChoosers']);
-  this.navigateUpInProgress = false; // see NavigateUpMenu.js
+  this.navigateUpInProgress = false; // see NavigateUpButton.js
   this._additionalContainerClasses += ' outline';
   this._treeItemPaddingLeft = 37;
   this._treeItemPaddingLevel = 20;
   this._detailTableListener;
   this.inBackground = false;
+  this.embedDetailContent = false;
+  this.compact = false;
   this.formController;
   this.messageBoxController;
   this.fileChooserController;
   this._nodeIdToRowMap = {};
+  this._scrolldirections = 'y';
 };
 scout.inherits(scout.Outline, scout.Tree);
 
 scout.Outline.prototype._init = function(model) {
+  //add filter before first traversal of tree-> tree is only traversed once.
+  this.addFilter(new scout.DetailTableTreeFilter(), true);
   scout.Outline.parent.prototype._init.call(this, model);
 
   this.formController = new scout.FormController(this, this.session);
   this.messageBoxController = new scout.MessageBoxController(this, this.session);
   this.fileChooserController = new scout.FileChooserController(this, this.session);
-  this.addFilter(new scout.DetailTableTreeFilter());
   this.titleVisible = true;
   this._syncDefaultDetailForm(this.defaultDetailForm);
+  this.titleMenuBar = scout.create('MenuBar', {
+    parent: this,
+    menuOrder: new scout.GroupBoxMenuItemsOrder()
+  });
+  this._updateTitleMenuBar();
+  this.nodeMenuBar = scout.create('MenuBar', {
+    parent: this,
+    menuOrder: new scout.GroupBoxMenuItemsOrder()
+  });
+  this.nodeMenuBar.bottom();
+  this.detailMenuBar = scout.create('MenuBar', {
+    parent: this,
+    menuOrder: new scout.GroupBoxMenuItemsOrder()
+  });
+  this.detailMenuBar.bottom();
+  this.updateDetailContent();
 };
 
 scout.Outline.prototype._createKeyStrokeContext = function() {
@@ -48,15 +68,17 @@
  * @override Tree.js
  */
 scout.Outline.prototype._initTreeKeyStrokeContext = function(keyStrokeContext) {
+  var modifierBitMask = scout.keyStrokeModifier.CTRL | scout.keyStrokeModifier.SHIFT;
+
   keyStrokeContext.registerKeyStroke([
-      new scout.TreeSpaceKeyStroke(this),
-      new scout.OutlineNavigationUpKeyStroke(this),
-      new scout.OutlineNavigationDownKeyStroke(this),
-      new scout.OutlineNavigateToTopKeyStroke(this),
-      new scout.OutlineCollapseOrDrillUpKeyStroke(this),
-      new scout.OutlineExpandOrDrillDownKeyStroke(this)
-    ]
-    .concat(this.menus));
+    new scout.TreeNavigationUpKeyStroke(this, modifierBitMask),
+    new scout.TreeNavigationDownKeyStroke(this, modifierBitMask),
+    new scout.OutlineNavigateToTopKeyStroke(this, modifierBitMask),
+    new scout.TreeNavigationEndKeyStroke(this, modifierBitMask),
+    new scout.TreeCollapseOrDrillUpKeyStroke(this, modifierBitMask),
+    new scout.TreeExpandOrDrillDownKeyStroke(this, modifierBitMask)
+  ]);
+
   keyStrokeContext.$bindTarget = function() {
     return this.session.$entryPoint;
   }.bind(this);
@@ -70,15 +92,11 @@
 
   // Override layout
   this.htmlComp.setLayout(new scout.OutlineLayout(this));
-
-  if (this.selectedNodes.length === 0) {
-    if (this.defaultDetailForm) {
-      this._showDefaultDetailForm(true);
-    } else if (this.outlineOverview) {
-      this._showOutlineOverview();
-    }
-  }
-
+  this._renderCompact();
+  this._renderEmbedDetailContent();
+  this._renderDetailContent();
+  this._renderDetailMenuBarVisible();
+  this._renderNodeMenuBarVisible();
 };
 
 scout.Outline.prototype._renderProperties = function() {
@@ -104,10 +122,6 @@
 };
 
 scout.Outline.prototype._renderTitleMenuBar = function() {
-  this.titleMenuBar = scout.create('MenuBar', {
-    parent: this,
-    menuOrder: new scout.GroupBoxMenuItemsOrder()
-  });
   if (this.$title) {
     this.titleMenuBar.render(this.$title);
     this.titleMenuBar.$container.toggleClass('prevent-initial-focus', true);
@@ -116,7 +130,6 @@
 
 scout.Outline.prototype._removeTitleMenuBar = function() {
   this.titleMenuBar.remove();
-  this.titleMenuBar = null;
 };
 
 scout.Outline.prototype._removeTitle = function() {
@@ -142,39 +155,10 @@
   }
 };
 
-scout.Outline.prototype.handleOutlineContentDebounced = function(bringToFront) {
-  clearTimeout(this._handleOutlineTimeout);
-  this._handleOutlineTimeout = setTimeout(function() {
-    this.handleOutlineContent(bringToFront);
-  }.bind(this), 300);
-};
-
-scout.Outline.prototype.handleOutlineContent = function(bringToFront) {
-  // Outline does not support multi selection -> [0]
-  var node = this.selectedNodes[0];
-  if (node) {
-    this._updateOutlineNode(node, bringToFront);
-  } else {
-    this._showDefaultDetailForm(bringToFront);
-  }
-};
-
 scout.Outline.prototype._postRender = function() {
   //used to render glasspane
-  this._trigger('rendered');
-  //first set Outline content to prevent errors while rendering existing glasspanes. the outline content is a glasspane target
-  //and if this is null there could be errors when the form controller tries to render a popup with a glasspane behind it.
-  //The content is not rendered or attached twice because handleOutlineContent() checks if this is already done.
-  this.handleOutlineContent();
+  this.trigger('rendered');
   scout.Outline.parent.prototype._postRender.call(this);
-
-  // Ensure outline layout is valid (because DialogLayout relies on that)
-  this.htmlComp.validateLayout();
-
-  // Display attached forms, message boxes and file choosers.
-  this.formController.render();
-  this.messageBoxController.render();
-  this.fileChooserController.render();
 };
 
 /**
@@ -188,8 +172,8 @@
 /**
  * @override
  */
-scout.Outline.prototype._initTreeNode = function(node, parentNode) {
-  scout.Outline.parent.prototype._initTreeNode.call(this, node, parentNode);
+scout.Outline.prototype._initTreeNodeInternal = function(node, parentNode) {
+  scout.Outline.parent.prototype._initTreeNodeInternal.call(this, node, parentNode);
   node.detailFormVisibleByUi = true;
   if (node.detailTable) {
     node.detailTable = this.session.getOrCreateModelAdapter(node.detailTable, this);
@@ -213,10 +197,11 @@
 };
 
 scout.Outline.prototype._initDetailTable = function(node) {
-  var menus = this._createOutlineNavigationButtons(node, node.detailTable.staticMenus),
-    button = this._getMenu(menus, scout.NavigateDownMenu),
-    that = this;
-  node.detailTable.staticMenus = menus;
+  var that = this;
+
+  if (this.navigateButtonsVisible) {
+    this._appendNavigateButtonsForDetailTable(node);
+  }
 
   // link already existing rows (rows which are inserted later are linked by _onDetailTableRowInitialized)
   node.detailTable.rows.forEach(function(row) {
@@ -233,15 +218,20 @@
 };
 
 scout.Outline.prototype._initDetailForm = function(node) {
-  var menus = this._createOutlineNavigationButtons(node, node.detailForm.staticMenus);
-  node.detailForm.rootGroupBox.staticMenus = menus;
+  if (this.navigateButtonsVisible) {
+    this._appendNavigateButtonsForDetailForm(node);
+  }
+
+  // Mark form as detail form
+  node.detailForm.detailForm = true;
+
   node.detailForm.one('destroy', function() {
     // Unlink detail form if it was closed. May happen in the following case:
     // The form gets closed on execPageDeactivated. No pageChanged event will
     // be fired because the deactivated page is not selected anymore.
     node.detailForm = null;
-    // Also make sure desktop holds no reference to a destroyed form
-    this._updateOutlineNode(node, false);
+    // Also make sure other objects hold no reference to a destroyed form (e.g. bench)
+    this._triggerPageChanged(node);
   }.bind(this));
 };
 
@@ -266,18 +256,18 @@
   scout.inspector.applyInfo(node, node.$node);
 };
 
-scout.Outline.prototype._createOutlineNavigationButtons = function(node, staticMenus) {
+scout.Outline.prototype._createNavigateButtons = function(node, staticMenus) {
   var menus = scout.arrays.ensure(staticMenus);
-  if (!this._hasMenu(menus, scout.NavigateUpMenu)) {
-    var upButton = scout.create('NavigateUpMenu', {
+  if (!this._hasMenu(menus, scout.NavigateUpButton)) {
+    var upButton = scout.create('NavigateUpButton', {
       parent: this,
       outline: this,
       node: node
     });
     menus.push(upButton);
   }
-  if (!this._hasMenu(menus, scout.NavigateDownMenu)) {
-    var downButton = scout.create('NavigateDownMenu', {
+  if (!this._hasMenu(menus, scout.NavigateDownButton)) {
+    var downButton = scout.create('NavigateDownButton', {
       parent: this,
       outline: this,
       node: node
@@ -307,18 +297,10 @@
 scout.Outline.prototype.navigateToTop = function() {
   this.deselectAll();
   this.collapseAll();
-  if (this.defaultDetailForm) {
-    this._showDefaultDetailForm(true);
-  } else if (this.outlineOverview) {
-    this._showOutlineOverview();
-  }
-
   this.handleInitialExpanded();
-
-  this.handleOutlineContentDebounced(true);
 };
 
-scout.Outline.prototype.handleInitialExpanded = function(){
+scout.Outline.prototype.handleInitialExpanded = function() {
   this._visitNodes(this.nodes, function(node) {
     if (node.initialExpanded) {
       this.expandNode(node, {
@@ -336,26 +318,35 @@
     node.detailTable = null;
   }
   // If last node is removed, navigate back to top
-  if (this.nodes && this.nodes.length === 0) {
+  if (this.nodes.length === 0) {
     this.navigateToTop();
   }
 };
 
 scout.Outline.prototype.selectNodes = function(nodes, notifyServer, debounceSend) {
-  scout.Outline.parent.prototype.selectNodes.call(this, nodes, notifyServer, debounceSend);
+  nodes = scout.arrays.ensure(nodes);
+  if (nodes.length > 0 && this.isNodeSelected(nodes[0])) {
+    // Already selected, do nothing
+    return;
+  }
+  if (nodes.length === 0 && this.selectedNodes.length === 0) {
+    // Already unselected, do nothing
+    return;
+  }
   if (this.navigateUpInProgress) {
     this.navigateUpInProgress = false;
   } else {
-    nodes = scout.arrays.ensure(nodes);
     if (nodes.length === 1) {
       // When a node is selected, the detail form should never be hidden
-      nodes[0].detailFormVisibleByUi = true;
+      this.setDetailFormVisibleByUi(nodes[0], true);
     }
   }
+  scout.Outline.parent.prototype.selectNodes.call(this, nodes, notifyServer, debounceSend);
+  this.updateDetailContent();
 };
 
 scout.Outline.prototype._renderDefaultDetailForm = function() {
-    this._showDefaultDetailForm(!this.inBackground);
+  // nop
 };
 
 scout.Outline.prototype._syncDefaultDetailForm = function(defaultDetailForm) {
@@ -376,52 +367,66 @@
   }
 };
 
-scout.Outline.prototype._showDefaultDetailForm = function(bringToFront) {
-  if (this.defaultDetailForm && this.session.desktop.outline === this) {
-    this.session.desktop.setOutlineContent(this.defaultDetailForm, bringToFront);
+scout.Outline.prototype._syncNavigateButtonsVisible = function(navigateButtonsVisible) {
+  this.navigateButtonsVisible = navigateButtonsVisible;
+  this._visitNodes(this.nodes, this._syncNavigateButtonsVisibleForNode.bind(this));
+};
+
+scout.Outline.prototype._syncNavigateButtonsVisibleForNode = function(node, parentNode) {
+  if (this.navigateButtonsVisible) {
+    if (node.detailForm) {
+      this._appendNavigateButtonsForDetailForm(node);
+    }
+    if (node.detailTable) {
+      this._appendNavigateButtonsForDetailTable(node);
+    }
+  } else {
+    if (node.detailForm) {
+      this._removeNavigateButtonsForDetailForm(node);
+    }
+    if (node.detailTable) {
+      this._removeNavigateButtonsForDetailTable(node);
+    }
   }
 };
 
-scout.Outline.prototype._showOutlineOverview = function() {
-  this.session.desktop.setOutlineContent(this.outlineOverview, true);
+scout.Outline.prototype._appendNavigateButtonsForDetailForm = function(node) {
+  var menus = this._createNavigateButtons(node, node.detailForm.staticMenus);
+  node.detailForm.rootGroupBox.setStaticMenus(menus);
 };
 
-/**
- * @override Tree.js
- */
-scout.Outline.prototype._onNodeMouseDown = function(event) {
-  if (scout.Outline.parent.prototype._onNodeMouseDown.call(this, event)) {
-    this.handleOutlineContent(true);
-  }
+scout.Outline.prototype._appendNavigateButtonsForDetailTable = function(node) {
+  var menus = this._createNavigateButtons(node, node.detailTable.staticMenus);
+  node.detailTable.setStaticMenus(menus);
 };
 
-/**
- * @override Tree.js
- */
-scout.Outline.prototype._onNodeControlMouseDown = function(event) {
-  if (scout.Outline.parent.prototype._onNodeControlMouseDown.call(this, event)) {
-    this.handleOutlineContent(true);
-  }
+scout.Outline.prototype._removeNavigateButtonsForDetailForm = function(node) {
+  var staticMenus = [];
+  node.detailForm.rootGroupBox.staticMenus.forEach(function(menu) {
+    if (menu instanceof scout.NavigateUpButton || menu instanceof scout.NavigateDownButton) {
+      menu.destroy();
+    } else {
+      staticMenus.push(menu);
+    }
+  });
+  node.detailForm.rootGroupBox.setStaticMenus(staticMenus);
 };
 
-scout.Outline.prototype._updateOutlineNode = function(node, bringToFront) {
-  bringToFront = scout.nvl(bringToFront, true);
-  if (!node) {
-    throw new Error('called _updateOutlineNode without node');
-  }
+scout.Outline.prototype._removeNavigateButtonsForDetailTable = function(node) {
+  var menus = [];
+  var staticMenus = [];
+  node.detailTable.staticMenus.forEach(function(menu) {
+    if (menu instanceof scout.NavigateUpButton || menu instanceof scout.NavigateDownButton) {
+      menu.destroy();
+    } else {
+      staticMenus.push(menu);
+    }
+  });
+  node.detailTable.setStaticMenus(staticMenus);
+};
 
-  if (this.session.desktop.outline !== this || !scout.isOneOf(node, this.selectedNodes)) {
-    return;
-  }
-
-  var content;
-  if (node.detailForm && node.detailFormVisible && node.detailFormVisibleByUi) {
-    content = node.detailForm;
-  } else if (node.detailTable && node.detailTableVisible) {
-    content = node.detailTable;
-  }
-
-  this.session.desktop.setOutlineContent(content, bringToFront);
+scout.Outline.prototype._renderNavigateButtonsVisible = function() {
+  // nop
 };
 
 /**
@@ -468,7 +473,7 @@
  * @override
  */
 scout.Outline.prototype._isGroupingEnd = function(node) {
-  return node.nodeType == 'table';
+  return node.nodeType === 'table';
 };
 
 /**
@@ -478,69 +483,9 @@
   return false;
 };
 
-/* event handling */
-
-scout.Outline.prototype._onDetailTableRowsSelected = function(event) {
-  var button = this._getMenu(event.detailTable.staticMenus, scout.NavigateDownMenu);
-  button.updateEnabled();
-};
-
-scout.Outline.prototype._onDetailTableRowsFiltered = function(event) {
-  this.filter();
-};
-
-scout.Outline.prototype._onDetailTableRowInitialized = function(event) {
-  this._linkNodeWithRow(event.row);
-};
-
-scout.Outline.prototype._onDetailTableEvent = function(event) {
-  if (event.type === 'rowInitialized') {
-    this._onDetailTableRowInitialized(event);
-  } else if (event.type === 'rowsFiltered') {
-    this._onDetailTableRowsFiltered(event);
-  } else if (event.type === 'rowsSelected') {
-    this._onDetailTableRowsSelected(event);
-  }
-};
-
-scout.Outline.prototype._onPageChanged = function(event) {
-  if (event.nodeId) {
-    var node = this.nodesMap[event.nodeId];
-
-    node.detailFormVisible = event.detailFormVisible;
-    node.detailForm = this.session.getOrCreateModelAdapter(event.detailForm, this);
-    if (node.detailForm) {
-      this._initDetailForm(node);
-    }
-
-    node.detailTableVisible = event.detailTableVisible;
-    node.detailTable = this.session.getOrCreateModelAdapter(event.detailTable, this);
-    if (node.detailTable) {
-      this._initDetailTable(node);
-    }
-
-    // If the following condition is false, the selection state is not synchronized yet which
-    // means there is a selection event in the queue which will be processed right afterwards.
-    if (this.selectedNodes.indexOf(node) !== -1) {
-      this._updateOutlineNode(node, this.inFront());
-    }
-  } else {
-    this.defaultDetailForm = this.session.getOrCreateModelAdapter(event.detailForm, this);
-    this._showDefaultDetailForm(this.inFront());
-  }
-};
-
-scout.Outline.prototype._onNodesSelected = function(nodeIds) {
-  scout.Outline.parent.prototype._onNodesSelected.call(this, nodeIds);
-  this.handleOutlineContent(this.inFront());
-};
-
-scout.Outline.prototype.onModelAction = function(event) {
-  if (event.type === 'pageChanged') {
-    this._onPageChanged(event);
-  } else {
-    scout.Outline.parent.prototype.onModelAction.call(this, event);
-  }
+scout.Outline.prototype.setDetailFormVisibleByUi = function(node, visible) {
+  node.detailFormVisibleByUi = visible;
+  this._triggerPageChanged(node);
 };
 
 scout.Outline.prototype.validateFocus = function() {
@@ -571,6 +516,350 @@
   this.$container.toggleClass('in-background', this.inBackground);
 };
 
+scout.Outline.prototype._renderCompact = function() {
+  this.$container.toggleClass('compact', this.compact);
+};
+
+scout.Outline.prototype._renderEmbedDetailContent = function() {
+  this.$data.toggleClass('has-detail-content', this.embedDetailContent);
+};
+
+scout.Outline.prototype._renderDetailContent = function() {
+  if (!this.detailContent || this.detailContent.rendered) {
+    return;
+  }
+  var page = this.selectedNodes[0];
+  if (!page.rendered) {
+    return;
+  }
+
+  this.detailContent.render(page.$node);
+  if (this.detailContent.htmlComp) {
+    this.detailContent.htmlComp.validateRoot = false;
+    this.detailContent.htmlComp.pixelBasedSizing = true;
+  }
+  this._ensurePageLayout(page);
+  this.$data.addClass('detail-content-visible');
+};
+
+scout.Outline.prototype._ensurePageLayout = function(page) {
+  // selected page now has content (menubar and form) -> needs a layout
+  // always create new htmlComp, otherwise we would have to remove them when $node or outline gets remvoed
+  page.htmlComp = new scout.HtmlComponent(page.$node, this.session);
+  page.htmlComp.setLayout(new scout.PageLayout(this, page));
+};
+
+scout.Outline.prototype._removeDetailContent = function() {
+  if (!this.detailContent) {
+    return;
+  }
+  this.detailContent.remove();
+  this.$data.removeClass('detail-content-visible');
+};
+
+scout.Outline.prototype._postRenderViewRange = function() {
+  scout.Outline.parent.prototype._postRenderViewRange.call(this);
+  this._renderDetailContent();
+  this._renderDetailMenuBarVisible();
+  this._renderNodeMenuBarVisible();
+};
+
+scout.Outline.prototype.setCompact = function(compact) {
+  this.compact = compact;
+  if (this.rendered) {
+    this._renderCompact();
+    this.invalidateLayoutTree();
+  }
+};
+
+scout.Outline.prototype.setEmbedDetailContent = function(embed) {
+  this.embedDetailContent = embed;
+  if (this.rendered) {
+    this._renderEmbedDetailContent();
+    this.invalidateLayoutTree();
+  }
+  this.updateDetailContent();
+};
+
+scout.Outline.prototype.setDetailContent = function(content) {
+  if (this.detailContent === content) {
+    return;
+  }
+  if (this.rendered) {
+    this._removeDetailContent();
+  }
+  this.detailContent = content;
+  if (this.rendered) {
+    this._renderDetailContent();
+  }
+  this.invalidateLayoutTree();
+};
+
+scout.Outline.prototype.updateDetailContent = function() {
+  if (!this.embedDetailContent) {
+    this.setDetailContent(null);
+    this.setDetailMenus([]);
+    return;
+  }
+
+  this.setDetailMenuBarVisible(false);
+  this.setNodeMenuBarVisible(false);
+  this.setDetailContent(this._computeDetailContent());
+  this.updateDetailMenus();
+
+  // Layout immediate to prevent 'laggy' form visualization,
+  // but not initially while desktop gets rendered because it will be done at the end anyway
+  if (this.rendered) {
+    this.validateLayoutTree();
+  }
+};
+
+scout.Outline.prototype._computeDetailContent = function() {
+  var selectedPage = this.selectedNodes[0];
+  if (!selectedPage) {
+    // Detail content is shown for the selected node only
+    return null;
+  }
+  if (selectedPage.nodeType === 'virtual') {
+    // If node is virtual it is not known yet whether there is a detail form or not -> wait until node gets resolved
+    return null;
+  }
+
+  // if there is a detail form, use this
+  if (selectedPage.detailForm && selectedPage.detailFormVisible && selectedPage.detailFormVisibleByUi) {
+    return selectedPage.detailForm;
+    // otherwise show the content of the table row
+    // but never if parent is a node page -> the table contains only one column with no essential information
+  } else if (selectedPage.row && selectedPage.parentNode.nodeType === 'table') {
+    return scout.create('TableRowDetail', {
+      parent: this,
+      table: selectedPage.parentNode.detailTable,
+      tableRow: selectedPage.row
+    });
+  }
+  return null;
+};
+
+/**
+ * Updates node and detail menubar.
+ * Node menubar: Contains the table controls and right aligned menus.
+ * Detail menubar: Contains the other menus.
+ *
+ * The menu items are gathered from various sources:
+ * If the selected page has a detailForm, the menus are taken from there. Otherwise the detail table and the parent detail table provide the menus.
+ * The detail table contributes the empty space menus and the parent detail the the single selection menus.
+ *
+ * The menus of the outline itself are not displayed. In fact the server won't deliver any.
+ * One reason is that no menus are displayed in regular mode, so when switching to compact mode no menus would be available.
+ * Another reason is that it would flicker because the menus are sent anew from the server every time a node gets selected because the menus are added to the outline and not to the node and are therefore not cached.
+ */
+scout.Outline.prototype.updateDetailMenus = function() {
+  if (!this.embedDetailContent) {
+    return;
+  }
+  var selectedPages = this.selectedNodes,
+    selectedPage = selectedPages[0],
+    menuItems = [],
+    tableControls = [],
+    nodeMenus = [],
+    detailTable,
+    detailMenus = [];
+
+  if (this.detailContent && this.detailContent instanceof scout.Form) {
+    // get menus from detail form
+    var rootGroupBox = this.detailContent.rootGroupBox;
+    menuItems = rootGroupBox.processMenus.concat(rootGroupBox.menus);
+    rootGroupBox.setMenuBarVisible(false);
+  } else if (selectedPage) {
+    // get empty space menus and table controls from detail table
+    if (selectedPage.detailTable) {
+      detailTable = selectedPage.detailTable;
+      menuItems = scout.menus.filter(detailTable.menus, ['Table.EmptySpace'], false, true);
+      tableControls = detailTable.tableControls;
+      this._attachDetailMenusListener(detailTable);
+    }
+    // get single selection menus from parent detail table
+    var parentPage = selectedPage.parentNode;
+    if (parentPage && parentPage.detailTable) {
+      detailTable = parentPage.detailTable;
+      menuItems = menuItems.concat(scout.menus.filter(detailTable.menus, ['Table.SingleSelection'], false, true));
+      this._attachDetailMenusListener(detailTable);
+    }
+  }
+
+  // Add table controls to nodeMenus
+  tableControls.forEach(function(tableControl) {
+    var menu = scout.create('TableControlAdapterMenu',
+      scout.TableControlAdapterMenu.adaptTableControlProperties(tableControl, {
+        parent: this,
+        tableControl: tableControl,
+        horizontalAlignment: 1
+      }));
+    nodeMenus.push(menu);
+  }, this);
+
+  // Add right aligned menus to node menus, other to detail menus
+  menuItems.forEach(function(menuItem) {
+    if (menuItem.horizontalAlignment === 1) {
+      nodeMenus.push(menuItem);
+    } else {
+      detailMenus.push(menuItem);
+    }
+  }, this);
+
+  this.setNodeMenus(nodeMenus);
+  this.setDetailMenus(detailMenus);
+};
+
+/**
+ * Attaches a listener to the given menu container (which is the detail table or the detail table of the parent node)
+ * in order to get dynamic menu changes and update the detailMenus on such a change event.
+ */
+scout.Outline.prototype._attachDetailMenusListener = function(menuContainer) {
+  if (!this._detailMenusChangeHandler) {
+    this._detailMenusChangeHandler = function(event) {
+      if (scout.arrays.containsAny(event.changedProperties, ['menus', 'tableControls'])) {
+        this.updateDetailMenus();
+      }
+    }.bind(this);
+  }
+  if (!this._detailMenusDestroyHandler) {
+    this._detailMenusDestroyHandler = function() {
+      menuContainer.off('propertyChange', this._detailMenusChangeHandler);
+    }.bind(this);
+  }
+
+  menuContainer.off('propertyChange', this._detailMenusChangeHandler);
+  menuContainer.on('propertyChange', this._detailMenusChangeHandler);
+  menuContainer.off('destroy', this._detailMenusDestroyHandler);
+  menuContainer.one('destroy', this._detailMenusDestroyHandler);
+
+  if (!this._detailMenusNodesSelectedHandler) {
+    // This nodes selection listener removes the property change listeners from the old menu containers (detail content) whenever a node gets selected
+    // UpdateDetailMenus is called afterwards and attaches the property change listeners to the new detail content
+    // This guarantees that no events are fired for non selected nodes
+    this._detailMenusNodesSelectedHandler = {
+      outline: this,
+      menuContainers: [],
+      addMenuContainer: function(container) {
+        if (this.menuContainers.indexOf(container) > -1) {
+          return;
+        }
+        this.menuContainers.push(container);
+      },
+      func: function(event) {
+        if (event.type !== 'nodesSelected') {
+          return;
+        }
+        this.menuContainers.forEach(function(container) {
+          container.off('propertyChange', this.outline._detailMenusChangeHandler);
+          container.off('destroy', this.outline._detailMenusDestroyHandler);
+        }, this);
+        this.menuContainers = [];
+      }
+    };
+    this.events.addListener(this._detailMenusNodesSelectedHandler);
+  }
+  this._detailMenusNodesSelectedHandler.addMenuContainer(menuContainer);
+};
+
+scout.Outline.prototype.setDetailMenus = function(detailMenus) {
+  this.detailMenuBar.setMenuItems(detailMenus);
+  this.setDetailMenuBarVisible(this.detailMenuBar.menuItems.length > 0);
+};
+
+scout.Outline.prototype._renderDetailMenuBarVisible = function() {
+  if (this.detailMenuBarVisible) {
+    this._renderDetailMenuBar();
+  } else {
+    this._removeDetailMenuBar();
+  }
+};
+
+scout.Outline.prototype._renderDetailMenuBar = function() {
+  if (this.detailMenuBar.rendered) {
+    return;
+  }
+  if (this.selectedNodes.length === 0) {
+    return;
+  }
+  var node = this.selectedNodes[0];
+  if (!node.rendered) {
+    return;
+  }
+
+  this.detailMenuBar.render(node.$node);
+  this.detailMenuBar.$container.addClass('detail-menubar');
+  if (this.detailContent && this.detailContent.rendered) {
+    // move before content (e.g. form)
+    this.detailMenuBar.$container.insertBefore(this.detailContent.$container);
+  }
+  this._ensurePageLayout(node);
+  this.invalidateLayoutTree();
+};
+
+scout.Outline.prototype._removeDetailMenuBar = function() {
+  if (!this.detailMenuBar.rendered) {
+    return;
+  }
+  this.detailMenuBar.remove();
+  this.invalidateLayoutTree();
+};
+
+scout.Outline.prototype.setDetailMenuBarVisible = function(visible) {
+  this.detailMenuBarVisible = visible;
+  if (this.rendered) {
+    this._renderDetailMenuBarVisible();
+  }
+};
+
+scout.Outline.prototype.setNodeMenus = function(nodeMenus) {
+  this.nodeMenuBar.setMenuItems(nodeMenus);
+  this.setNodeMenuBarVisible(this.nodeMenuBar.menuItems.length > 0);
+};
+
+scout.Outline.prototype._renderNodeMenuBarVisible = function() {
+  if (this.nodeMenuBarVisible) {
+    this._renderNodeMenuBar();
+  } else {
+    this._removeNodeMenuBar();
+  }
+};
+
+scout.Outline.prototype._renderNodeMenuBar = function() {
+  if (this.nodeMenuBar.rendered) {
+    return;
+  }
+  if (this.selectedNodes.length === 0) {
+    return;
+  }
+  var node = this.selectedNodes[0];
+  if (!node.rendered) {
+    return;
+  }
+
+  var $text = node.$node.children('.text');
+  this.nodeMenuBar.render(node.$node);
+  this.nodeMenuBar.$container.addClass('node-menubar');
+  this.nodeMenuBar.$container.insertAfter($text);
+  this.invalidateLayoutTree();
+};
+
+scout.Outline.prototype._removeNodeMenuBar = function() {
+  if (!this.nodeMenuBar.rendered) {
+    return;
+  }
+  this.nodeMenuBar.remove();
+  this.invalidateLayoutTree();
+};
+
+scout.Outline.prototype.setNodeMenuBarVisible = function(visible) {
+  this.nodeMenuBarVisible = visible;
+  if (this.rendered) {
+    this._renderNodeMenuBarVisible();
+  }
+};
+
 /**
  * === Method required for objects that act as 'displayParent' ===
  *
@@ -581,22 +870,22 @@
     var desktop = this.session.desktop;
     var elements = [];
     if (desktop.navigation) {
-      elements.push(desktop.navigation.$container); // navigation container; not available if application has no navigation.
+      elements.push(desktop.navigation.$body);
     }
-    if (desktop._outlineContent) {
-      elements.push(desktop._outlineContent.$container); // outline content; not available if application has no navigation.
+    if (desktop.bench) {
+      elements.push(desktop.bench.$container);
     }
     return elements;
   } else {
     var deferred = new scout.DeferredGlassPaneTarget();
     var renderedHandler = function(event) {
-      var desktop = event.eventOn.session.desktop;
+      var desktop = event.source.session.desktop;
       var elements = [];
       if (desktop.navigation) {
-        elements.push(desktop.navigation.$container); // navigation container; not available if application has no navigation.
+        elements.push(desktop.navigation.$body);
       }
-      if (desktop._outlineContent) {
-        elements.push(desktop._outlineContent.$container); // outline content; not available if application has no navigation.
+      if (desktop.bench) {
+        elements.push(desktop.bench.$container);
       }
       deferred.ready(elements);
     };
@@ -608,16 +897,101 @@
   }
 };
 
-scout.Outline.prototype._renderMenus = function() {
-  var menuItems = scout.menus.filter(this.menus, ['Tree.Header']);
-  this.titleMenuBar.updateItems(menuItems);
-};
-
 /**
  * === Method required for objects that act as 'displayParent' ===
  *
- * Returns 'true' if this Outline is currently accessible to the user.
+ * Returns true if this outline is active and not in background.
  */
 scout.Outline.prototype.inFront = function() {
-  return this.rendered && !this.inBackground;
+  return this.session.desktop.outline === this && !this.inBackground;
+};
+
+/**
+ * Called if outline acts as display parent.<p>
+ * Returns true if outline is active, even if it is not rendered (e.g. when navigation is invisible)
+ */
+scout.Outline.prototype.acceptDialog = function(dialog) {
+  return this.session.desktop.outline === this;
+};
+
+/**
+ * Called if outline acts as display parent.<p>
+ * Returns true if outline is active, even if it is not rendered (e.g. when navigation is invisible)
+ */
+scout.Outline.prototype.acceptView = function(view) {
+  return this.session.desktop.outline === this;
+};
+
+scout.Outline.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
+  if (this.titleMenuBar) {
+    // menuBar is not created yet when synMenus is called initially
+    this._updateTitleMenuBar();
+  }
+};
+
+scout.Outline.prototype._updateTitleMenuBar = function() {
+  var menuItems = scout.menus.filter(this.menus, ['Tree.Header']);
+  this.titleMenuBar.setMenuItems(menuItems);
+};
+
+scout.Outline.prototype._triggerPageChanged = function(page) {
+  this.trigger('pageChanged', {
+    page: page
+  });
+};
+
+/* event handling */
+
+scout.Outline.prototype._onDetailTableRowsFiltered = function(event) {
+  this.filter();
+};
+
+scout.Outline.prototype._onDetailTableRowInitialized = function(event) {
+  this._linkNodeWithRow(event.row);
+};
+
+scout.Outline.prototype._onDetailTableEvent = function(event) {
+  if (event.type === 'rowInitialized') {
+    this._onDetailTableRowInitialized(event);
+  } else if (event.type === 'rowsFiltered') {
+    this._onDetailTableRowsFiltered(event);
+  }
+};
+
+scout.Outline.prototype._onPageChanged = function(event) {
+  var node;
+  if (event.nodeId) {
+    node = this.nodesMap[event.nodeId];
+
+    node.detailFormVisible = event.detailFormVisible;
+    node.detailForm = this.session.getOrCreateModelAdapter(event.detailForm, this);
+    if (node.detailForm) {
+      this._initDetailForm(node);
+    }
+
+    node.detailTableVisible = event.detailTableVisible;
+    node.detailTable = this.session.getOrCreateModelAdapter(event.detailTable, this);
+    if (node.detailTable) {
+      this._initDetailTable(node);
+    }
+  } else {
+    this.defaultDetailForm = this.session.getOrCreateModelAdapter(event.detailForm, this);
+  }
+
+  var selectedPage = this.selectedNodes[0];
+  if (!node && !selectedPage || node === selectedPage) {
+    this.updateDetailContent();
+  }
+
+  this._triggerPageChanged(node);
+};
+
+scout.Outline.prototype.onModelAction = function(event) {
+  if (event.type === 'pageChanged') {
+    this._onPageChanged(event);
+  } else {
+    scout.Outline.parent.prototype.onModelAction.call(this, event);
+  }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineCollapseOrDrillUpKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineCollapseOrDrillUpKeyStroke.js
deleted file mode 100644
index 1c8b4c9..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineCollapseOrDrillUpKeyStroke.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.OutlineCollapseOrDrillUpKeyStroke = function(tree) {
-  scout.OutlineCollapseOrDrillUpKeyStroke.parent.call(this, tree);
-  this.which = [scout.keys.SUBTRACT];
-  this.renderingHints.text = '-';
-  this.renderingHints.$drawingArea = function($drawingArea, event) {
-    return (event._treeCurrentNode.expanded ? event._$treeCurrentNode : null);
-  }.bind(this);
-};
-scout.inherits(scout.OutlineCollapseOrDrillUpKeyStroke, scout.AbstractOutlineNavigationKeyStroke);
-
-scout.OutlineCollapseOrDrillUpKeyStroke.prototype._accept = function(event) {
-  var accepted = scout.TreeCollapseOrDrillUpKeyStroke.parent.prototype._accept.call(this, event);
-  return accepted && event._treeCurrentNode;
-};
-
-scout.OutlineCollapseOrDrillUpKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if (currentNode.expanded) {
-    this.field.collapseNode(currentNode);
-    return null;
-  } else if (currentNode.parentNode) {
-    return currentNode.parentNode;
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineExpandOrDrillDownKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineExpandOrDrillDownKeyStroke.js
deleted file mode 100644
index e49c343..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineExpandOrDrillDownKeyStroke.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.OutlineExpandOrDrillDownKeyStroke = function(tree) {
-  scout.OutlineExpandOrDrillDownKeyStroke.parent.call(this, tree);
-  this.which = [scout.keys.ADD];
-  this.renderingHints.text = '+';
-  this.renderingHints.$drawingArea = function($drawingArea, event) {
-    return (!event._treeCurrentNode.expanded ? event._$treeCurrentNode : null);
-  }.bind(this);
-};
-scout.inherits(scout.OutlineExpandOrDrillDownKeyStroke, scout.AbstractOutlineNavigationKeyStroke);
-
-scout.OutlineExpandOrDrillDownKeyStroke.prototype._accept = function(event) {
-  var accepted = scout.OutlineExpandOrDrillDownKeyStroke.parent.prototype._accept.call(this, event);
-  return accepted && event._treeCurrentNode;
-};
-
-scout.OutlineExpandOrDrillDownKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if (!currentNode.expanded && !currentNode.leaf) {
-    this.field.expandNode(currentNode, {
-      lazy: false // always show all nodes on node double click
-    });
-    return null;
-  } else if (currentNode.childNodes.length > 0) {
-    return currentNode.childNodes[0];
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineLayout.js
index d15244f..64fe61d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineLayout.js
@@ -14,6 +14,46 @@
 };
 scout.inherits(scout.OutlineLayout, scout.TreeLayout);
 
+scout.OutlineLayout.prototype._layout = function($container) {
+  var containerSize,
+    htmlContainer = this.outline.htmlComp;
+
+  scout.OutlineLayout.parent.prototype._layout.call(this, $container);
+
+  containerSize = htmlContainer.getAvailableSize()
+    .subtract(htmlContainer.getInsets());
+
+  if (this.outline.embedDetailContent) {
+    var selectedNode = this.outline.selectedNodes[0];
+    if (selectedNode && selectedNode.rendered) {
+      var pageHtmlComp = selectedNode.htmlComp;
+      // pageHtmlComp is null if there is no detail form and no detail menubar
+      if (pageHtmlComp) {
+        // Fix width so that prefSize returns the appropriate height (necessary for elements with text wrap)
+        pageHtmlComp.$comp.cssWidth(containerSize.width);
+
+        var prefSize = pageHtmlComp.getPreferredSize();
+        pageHtmlComp.setSize(new scout.Dimension(containerSize.width, prefSize.height));
+        selectedNode.height = prefSize.height + pageHtmlComp.getMargins().vertical();
+      }
+    }
+
+    // Remove width and height from non selected nodes (at this point we don't know the previously selected node anymore, so we need process all rendered)
+    this.outline.$nodes().each(function(i, elem) {
+      var $node = $(elem);
+      // check for style.height to prevent unnecessary updates, no need to update nodes without a fixed height
+      if ($node.isSelected() || !$node[0].style.height || $node[0].style.height === 'auto') {
+        return;
+      }
+
+      $node.css('height', 'auto')
+        .css('width', 'auto');
+      var node = $node.data('node');
+      node.height = $node.outerHeight(true);
+    });
+  }
+};
+
 scout.OutlineLayout.prototype._setDataHeight = function(heightOffset) {
   // Add title height to heightOffset
   if (this.outline.titleVisible) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationDownKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationDownKeyStroke.js
deleted file mode 100644
index b026775..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationDownKeyStroke.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.OutlineNavigationDownKeyStroke = function(tree) {
-  scout.OutlineNavigationDownKeyStroke.parent.call(this, tree);
-  this.which = [scout.keys.DOWN];
-  this.renderingHints.text = '↓';
-  this.renderingHints.$drawingArea = function($drawingArea, event) {
-    var $currentNode = event._$treeCurrentNode;
-    if ($currentNode.length === 0) {
-      return this.field.$nodes().first();
-    }
-    return $currentNode.nextAll('.tree-node:not(.hidden):first');
-  }.bind(this);
-};
-scout.inherits(scout.OutlineNavigationDownKeyStroke, scout.AbstractOutlineNavigationKeyStroke);
-
-scout.OutlineNavigationDownKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if ($currentNode.length === 0) {
-    return this.field.$nodes().first().data('node');
-  }
-  return $currentNode.nextAll('.tree-node:not(.hidden):first').data('node');
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationUpKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationUpKeyStroke.js
deleted file mode 100644
index aba6ad4..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigationUpKeyStroke.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.OutlineNavigationUpKeyStroke = function(tree) {
-  scout.OutlineNavigationUpKeyStroke.parent.call(this, tree);
-  this.which = [scout.keys.UP];
-  this.renderingHints.text = '↑';
-  this.renderingHints.$drawingArea = function($drawingArea, event) {
-    var $currentNode = event._$treeCurrentNode;
-    if ($currentNode.length === 0) {
-      return this.field.$nodes().last();
-    }
-    return $currentNode.prevAll('.tree-node:not(.hidden):first');
-  }.bind(this);
-};
-scout.inherits(scout.OutlineNavigationUpKeyStroke, scout.AbstractOutlineNavigationKeyStroke);
-
-scout.OutlineNavigationUpKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if ($currentNode.length === 0) {
-    return this.field.$nodes().last().data('node');
-  }
-  return $currentNode.prevAll('.tree-node:not(.hidden):first').data('node');
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineOverview.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineOverview.js
index 404f6c3..038eb93 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineOverview.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineOverview.js
@@ -52,7 +52,3 @@
   this.$container.detach();
   scout.OutlineOverview.parent.prototype._detach.call(this);
 };
-
-scout.OutlineOverview.prototype.onResize = function() {
-
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineViewButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineViewButton.js
index 11097a5..23812c3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineViewButton.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineViewButton.js
@@ -35,12 +35,19 @@
   }
 };
 
-scout.OutlineViewButton.prototype.onOutlineChanged = function(outline) {
-  var oldSelected = this.selected,
-    selected = this.outline === outline;
-  if (selected !== oldSelected) {
-    this.selected = selected;
-    this._renderSelected();
-    this._firePropertyChange('selected', oldSelected, selected);
+scout.OutlineViewButton.prototype.setSelected = function(selected) {
+  var oldSelected = this.selected;
+  if (oldSelected === selected) {
+    return;
   }
+  this.selected = selected;
+  if (this.rendered) {
+    this._renderSelected();
+  }
+  this._firePropertyChange('selected', oldSelected, selected);
+};
+
+scout.OutlineViewButton.prototype.onOutlineChanged = function(outline) {
+  var selected = outline && this.outline === outline;
+  this.setSelected(selected);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/PageLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/PageLayout.js
new file mode 100644
index 0000000..4f624ab
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/PageLayout.js
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.PageLayout = function(outline, page) {
+  scout.PageLayout.parent.call(this, outline);
+  this.outline = outline;
+  this.page = page;
+};
+scout.inherits(scout.PageLayout, scout.AbstractLayout);
+
+scout.PageLayout.prototype.layout = function($container) {
+  var containerSize, detailMenuBarSize, formTop,
+    htmlContainer = this.page.htmlComp,
+    $text = this.page.$node.children('.text'),
+    titleHeight = 0,
+    nodeMenuBar = this.outline.nodeMenuBar,
+    nodeMenuBarWidth = 0,
+    detailMenuBar = this.outline.detailMenuBar,
+    detailMenuBarHeight = 0;
+
+  containerSize = htmlContainer.getAvailableSize()
+    .subtract(htmlContainer.getInsets());
+
+  if (nodeMenuBar.visible) {
+    nodeMenuBarWidth = nodeMenuBar.htmlComp.getPreferredSize().width;
+    $text.cssWidth(containerSize.width - nodeMenuBarWidth);
+  }
+
+  if (detailMenuBar.visible) {
+    detailMenuBarHeight = detailMenuBar.htmlComp.getPreferredSize().height;
+    detailMenuBarSize = new scout.Dimension(containerSize.width, detailMenuBarHeight)
+      .subtract(detailMenuBar.htmlComp.getMargins());
+    detailMenuBar.htmlComp.setSize(detailMenuBarSize);
+  }
+
+  if (this.outline.detailContent) {
+    titleHeight = $text.outerHeight(true);
+    this.outline.detailContent.htmlComp.setSize(new scout.Dimension(containerSize.width, containerSize.height - titleHeight - detailMenuBarHeight));
+  }
+};
+
+scout.PageLayout.prototype.preferredLayoutSize = function($container) {
+  var prefSize, containerSize,
+    htmlContainer = this.page.htmlComp,
+    detailContentPrefSize = new scout.Dimension(),
+    $text = this.page.$node.children('.text'),
+    titlePrefHeight = 0,
+    detailMenuBar = this.outline.detailMenuBar,
+    detailMenuBarPrefSize = new scout.Dimension(),
+    nodeMenuBar = this.outline.nodeMenuBar,
+    nodeMenuBarWidth = 0;
+
+  containerSize = htmlContainer.getSize()
+    .subtract(htmlContainer.getInsets());
+
+  if (nodeMenuBar.visible) {
+    nodeMenuBarWidth = nodeMenuBar.htmlComp.getPreferredSize().width;
+  }
+
+  // needs a width to be able to calculate the pref height -> container width needs to be correct already
+  titlePrefHeight = scout.graphics.prefSize($text, true, {
+    widthHint: containerSize.width - nodeMenuBarWidth
+  }).height;
+
+  if (detailMenuBar.visible) {
+    detailMenuBarPrefSize = detailMenuBar.htmlComp.getPreferredSize();
+  }
+  if (this.outline.detailContent) {
+    // Table row detail may contain wrapped text as well, but since it uses the full width there is no need to give a width hint
+    detailContentPrefSize = this.outline.detailContent.htmlComp.getPreferredSize();
+  }
+
+  prefSize = new scout.Dimension(Math.max(detailContentPrefSize.width, detailMenuBarPrefSize.width), titlePrefHeight + detailMenuBarPrefSize.height + detailContentPrefSize.height);
+  prefSize = prefSize.add(htmlContainer.getInsets());
+  return prefSize;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/SearchOutline.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/SearchOutline.css
index cd6ba98..1fc1f21 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/SearchOutline.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/SearchOutline.css
@@ -61,3 +61,10 @@
     text-align: center;
   }
 }
+
+.compact.outline.breadcrumb > .search-outline-panel {
+  & > .search-outline-status {
+    padding-left: @compact-outline-node-padding-h;
+    text-align: left;
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineKeyStrokeContext.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineKeyStrokeContext.js
similarity index 70%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineKeyStrokeContext.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineKeyStrokeContext.js
index b449016..32020b8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineKeyStrokeContext.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineKeyStrokeContext.js
@@ -19,12 +19,12 @@
  * Returns true if this event is handled by this context, and if so sets the propagation flags accordingly.
  */
 scout.OutlineKeyStrokeContext.prototype.accept = function(event) {
-  return !this._outline.inBackground && !this.isFormToolOpened() && scout.OutlineKeyStrokeContext.parent.prototype.accept.call(this, event);
+  return !this._outline.inBackground && !this.isFormMenuOpen() && scout.OutlineKeyStrokeContext.parent.prototype.accept.call(this, event);
 };
 
-scout.OutlineKeyStrokeContext.prototype.isFormToolOpened = function() {
-  var popupButtons = this._outline.session.desktop.actions;
-  return popupButtons.some(function(button) {
-    return button.popup && button.popup.$container && button.popup.$container.isAttached();
+scout.OutlineKeyStrokeContext.prototype.isFormMenuOpen = function() {
+  var menus = this._outline.session.desktop.menus;
+  return menus.some(function(menu) {
+    return menu.popup && menu.popup.$container && menu.popup.$container.isAttached();
   }, this);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigateToTopKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineNavigateToTopKeyStroke.js
similarity index 82%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigateToTopKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineNavigateToTopKeyStroke.js
index 0ecf01f..a83e60f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/OutlineNavigateToTopKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/keystrokes/OutlineNavigateToTopKeyStroke.js
@@ -8,8 +8,8 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.OutlineNavigateToTopKeyStroke = function(tree) {
-  scout.OutlineNavigateToTopKeyStroke.parent.call(this, tree);
+scout.OutlineNavigateToTopKeyStroke = function(tree, modifierBitMask) {
+  scout.OutlineNavigateToTopKeyStroke.parent.call(this, tree, modifierBitMask);
   this.which = [scout.keys.HOME];
   this.renderingHints.hAlign = scout.hAlign.RIGHT;
 
@@ -17,8 +17,8 @@
     return this.field.$title || this.field.$data;
   }.bind(this);
 };
-scout.inherits(scout.OutlineNavigateToTopKeyStroke, scout.AbstractOutlineNavigationKeyStroke);
+scout.inherits(scout.OutlineNavigateToTopKeyStroke, scout.AbstractTreeNavigationKeyStroke);
 
-scout.OutlineNavigateToTopKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
+scout.OutlineNavigateToTopKeyStroke.prototype._handleInternal = function(currentNode) {
   this.field.navigateToTop();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateButton.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateButton.css
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateButton.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateButton.css
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/AbstractNavigateMenu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateButton.js
similarity index 72%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/AbstractNavigateMenu.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateButton.js
index 37ce375..84ec34a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/AbstractNavigateMenu.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateButton.js
@@ -13,9 +13,11 @@
  * When a navigation button is clicked, we process that click browser-side first and send an event to
  * the server which nodes have been selected. We do that for better user experience. In a first attempt
  * the whole navigation logic was on the server, which caused a lag and flickering in the UI.
+ *
+ * @abstract
  */
-scout.AbstractNavigateMenu = function() {
-  scout.AbstractNavigateMenu.parent.call(this);
+scout.NavigateButton = function() {
+  scout.NavigateButton.parent.call(this);
 
   this.node;
   this.outline;
@@ -30,19 +32,25 @@
    */
   this._additionalCssClass = '';
 };
-scout.inherits(scout.AbstractNavigateMenu, scout.Menu);
+scout.inherits(scout.NavigateButton, scout.Menu);
 
-scout.AbstractNavigateMenu.prototype._init = function(options) {
-  scout.AbstractNavigateMenu.parent.prototype._init.call(this, options);
+scout.NavigateButton.prototype._init = function(options) {
+  scout.NavigateButton.parent.prototype._init.call(this, options);
 
   this.node = options.node;
   this.outline = options.outline;
 };
 
+scout.NavigateButton.prototype.destroy = function() {
+  if (this.rendered) {
+    this.remove();
+  }
+};
+
 /**
  * @override
  */
-scout.AbstractNavigateMenu.prototype._render = function($parent) {
+scout.NavigateButton.prototype._render = function($parent) {
   if (this._isDetail()) {
     this._onClickFunc = this._setDetailVisible.bind(this);
   } else {
@@ -56,7 +64,7 @@
     this.iconId = this._defaultIconId;
   }
   this.enabled = this._buttonEnabled();
-  scout.AbstractNavigateMenu.parent.prototype._render.call(this, $parent);
+  scout.NavigateButton.parent.prototype._render.call(this, $parent);
   this.$container.addClass('navigate-button small');
   this.$container.addClass(this._additionalCssClass);
   this.outline.keyStrokeContext.registerKeyStroke(this);
@@ -65,23 +73,22 @@
 /**
  * @override Action.js
  */
-scout.AbstractNavigateMenu.prototype._remove = function() {
-  scout.AbstractNavigateMenu.parent.prototype._remove.call(this);
+scout.NavigateButton.prototype._remove = function() {
+  scout.NavigateButton.parent.prototype._remove.call(this);
   this.outline.keyStrokeContext.unregisterKeyStroke(this);
 };
 
-scout.AbstractNavigateMenu.prototype._setDetailVisible = function() {
+scout.NavigateButton.prototype._setDetailVisible = function() {
   var detailVisible = this._toggleDetail();
   $.log.debug('show detail-' + detailVisible ? 'form' : 'table');
-  this.node.detailFormVisibleByUi = detailVisible;
-  this.outline._updateOutlineNode(this.node, true);
+  this.outline.setDetailFormVisibleByUi(this.node, detailVisible);
 };
 
 /**
  * @override Menu.js
  */
-scout.AbstractNavigateMenu.prototype.doAction = function(event) {
-  if (!this.prepareDoAction(event)) {
+scout.NavigateButton.prototype.doAction = function() {
+  if (!this.prepareDoAction()) {
     return false;
   }
   this._onClickFunc();
@@ -91,7 +98,7 @@
 /**
  * Called when enabled state must be re-calculated and probably rendered.
  */
-scout.AbstractNavigateMenu.prototype.updateEnabled = function() {
+scout.NavigateButton.prototype.updateEnabled = function() {
   this.enabled = this._buttonEnabled();
   if (this.rendered) {
     this._renderEnabled();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateDownMenu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateDownButton.js
similarity index 66%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateDownMenu.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateDownButton.js
index 9f171e3..1455424 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateDownMenu.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateDownButton.js
@@ -8,31 +8,47 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.NavigateDownMenu = function(outline, node) {
-  scout.NavigateDownMenu.parent.call(this, outline, node);
+scout.NavigateDownButton = function() {
+  scout.NavigateDownButton.parent.call(this);
   this._defaultIconId = scout.icons.ANGLE_DOWN;
   this._defaultText = 'ui.Continue';
   this.iconId = this._defaultIconId;
   this.keyStroke = 'enter';
+  this._detailTableRowsSelectedHandler = this._onDetailTableRowsSelected.bind(this);
 };
-scout.inherits(scout.NavigateDownMenu, scout.AbstractNavigateMenu);
+scout.inherits(scout.NavigateDownButton, scout.NavigateButton);
 
-scout.NavigateDownMenu.prototype._render = function($parent) {
-  scout.NavigateDownMenu.parent.prototype._render.call(this, $parent);
+scout.NavigateDownButton.prototype._init = function(options) {
+  scout.NavigateDownButton.parent.prototype._init.call(this, options);
+
+  if (this.node.detailTable) {
+    this.node.detailTable.on('rowsSelected', this._detailTableRowsSelectedHandler);
+  }
+};
+
+scout.NavigateDownButton.prototype.destroy = function() {
+  if (this.node.detailTable) {
+    this.node.detailTable.off('rowsSelected', this._detailTableRowsSelectedHandler);
+  }
+  scout.NavigateDownButton.parent.prototype.destroy.call(this);
+};
+
+scout.NavigateDownButton.prototype._render = function($parent) {
+  scout.NavigateDownButton.parent.prototype._render.call(this, $parent);
   this.$container.addClass('down');
 };
 
-scout.NavigateDownMenu.prototype._isDetail = function() {
+scout.NavigateDownButton.prototype._isDetail = function() {
   // Button is in "detail mode" if there are both detail form and detail table visible and detail form is _not_ hidden.
   return !!(this.node.detailFormVisible && this.node.detailForm &&
     this.node.detailTableVisible && this.node.detailTable && this.node.detailFormVisibleByUi);
 };
 
-scout.NavigateDownMenu.prototype._toggleDetail = function() {
+scout.NavigateDownButton.prototype._toggleDetail = function() {
   return false;
 };
 
-scout.NavigateDownMenu.prototype._buttonEnabled = function() {
+scout.NavigateDownButton.prototype._buttonEnabled = function() {
   if (this._isDetail()) {
     return true;
   }
@@ -49,7 +65,7 @@
   }
 };
 
-scout.NavigateDownMenu.prototype._drill = function() {
+scout.NavigateDownButton.prototype._drill = function() {
   var drillNode;
 
   if (this.node.detailTable) {
@@ -77,7 +93,6 @@
 
     // Select the target node
     this.outline.selectNodes(drillNode); // this also expands the parent node, if required
-    this.outline.handleOutlineContent(true);
 
     // If the parent node is a table page node, expand the drillNode
     // --> Same logic as in OutlineMediator.mediateTableRowAction()
@@ -86,3 +101,7 @@
     }
   }
 };
+
+scout.NavigateDownButton.prototype._onDetailTableRowsSelected = function(event) {
+  this.updateEnabled();
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateUpMenu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateUpButton.js
similarity index 75%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateUpMenu.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateUpButton.js
index c5e76ae..5ce21dc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/NavigateUpMenu.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/navigation/NavigateUpButton.js
@@ -8,28 +8,28 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.NavigateUpMenu = function(options) {
-  scout.NavigateUpMenu.parent.call(this);
+scout.NavigateUpButton = function() {
+  scout.NavigateUpButton.parent.call(this);
   this._defaultIconId = scout.icons.ANGLE_UP;
   this._defaultText = 'ui.Up';
   this._additionalCssClass = 'small-gap';
   this.iconId = this._defaultIconId;
   this.keyStroke = 'backspace';
 };
-scout.inherits(scout.NavigateUpMenu, scout.AbstractNavigateMenu);
+scout.inherits(scout.NavigateUpButton, scout.NavigateButton);
 
-scout.NavigateUpMenu.prototype._render = function($parent) {
-  scout.NavigateUpMenu.parent.prototype._render.call(this, $parent);
+scout.NavigateUpButton.prototype._render = function($parent) {
+  scout.NavigateUpButton.parent.prototype._render.call(this, $parent);
   this.$container.addClass('up');
 };
 
-scout.NavigateUpMenu.prototype._isDetail = function() {
+scout.NavigateUpButton.prototype._isDetail = function() {
   // Button is in "detail mode" if there are both detail form and detail table visible and detail form _is_ hidden.
   return !!(this.node.detailFormVisible && this.node.detailForm &&
     this.node.detailTableVisible && this.node.detailTable && !this.node.detailFormVisibleByUi);
 };
 
-scout.NavigateUpMenu.prototype._toggleDetail = function() {
+scout.NavigateUpButton.prototype._toggleDetail = function() {
   return true;
 };
 
@@ -37,18 +37,17 @@
  * Returns true when current node has either a parentNode or if current node is a
  * top-level node without a parent and the outline has a default detail-form.
  */
-scout.NavigateUpMenu.prototype._buttonEnabled = function() {
+scout.NavigateUpButton.prototype._buttonEnabled = function() {
   var parentNode = this.node.parentNode;
   return !!parentNode || !!this.outline.defaultDetailForm || !!this.outline.outlineOverview;
 };
 
-scout.NavigateUpMenu.prototype._drill = function() {
+scout.NavigateUpButton.prototype._drill = function() {
   var parentNode = this.node.parentNode;
   if (parentNode) {
     $.log.debug('drill up to node ' + parentNode);
     this.outline.navigateUpInProgress = true;
     this.outline.selectNodes(parentNode);
-    this.outline.handleOutlineContent(true);
     this.outline.collapseNode(parentNode, {
       collapseChildNodes: true
     });
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerDesktopNotification.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerDesktopNotification.css
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerDesktopNotification.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerDesktopNotification.css
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerDesktopNotification.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerDesktopNotification.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerDesktopNotification.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerDesktopNotification.js
index c8d30f9..effd143 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerDesktopNotification.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerDesktopNotification.js
@@ -8,7 +8,7 @@
   scout.PopupBlockerDesktopNotification.parent.prototype._init.call(this, model);
   this.linkUrl = model.linkUrl;
   this.linkText = this.session.text('ui.OpenManually');
-  this.closeable = true;
+  this.closable = true;
   this.duration = scout.DesktopNotification.INFINITE;
   this.status = {
     message: this.session.text('ui.PopupBlockerDetected'),
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerHandler.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerHandler.js
similarity index 87%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerHandler.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerHandler.js
index 400bfbd..c89efee 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/PopupBlockerHandler.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/popupblocker/PopupBlockerHandler.js
@@ -12,23 +12,24 @@
   this.session = session;
 };
 
-scout.PopupBlockerHandler.prototype.openWindow = function(uri, target, windowSpecs) {
+scout.PopupBlockerHandler.prototype.openWindow = function(uri, windowName, windowSpecs) {
   var popup;
 
   windowSpecs = windowSpecs || 'location=no,toolbar=no,menubar=no,resizable=yes';
+  windowName = windowName || 'scout_' + new Date().getTime();
 
   if (scout.device.browser === scout.Device.Browser.INTERNET_EXPLORER) {
     // Workaround for IE: When in "protected mode", window.open() returns null for external URLs, even when
     // the popup was successfully opened! To check if a popup blocker is active, we first open an empty
     // popup with no URL, which will return null when the popup was blocked. If the popup was successful,
     // we change the location to the target URI.
-    popup = window.open('', target, windowSpecs);
+    popup = window.open('', windowName, windowSpecs);
     if (popup) {
       popup.window.location.href = uri;
     }
   } else {
     // Chrome returns undefined, FF null when popup is blocked
-    popup = window.open(uri, target, windowSpecs);
+    popup = window.open(uri, windowName, windowSpecs);
   }
   return popup;
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.css
new file mode 100644
index 0000000..eb746e6
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.css
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+@header-menu-textandicon-padding-right: 11px;
+
+.desktop-tool-box {
+  position: absolute;
+  top: 0;
+  white-space: nowrap;
+
+  &.compact {
+    padding-right: 5px;
+  }
+}
+
+.desktop-tool-box-item.menu-item {
+  position: relative;
+  height: @desktop-header-height - 1px;
+  color: @text-color;
+  #scout.font-text-plus();
+  border-left: 1px solid transparent;
+  border-right: 1px solid transparent;
+  margin-left: 20px;
+  margin-right: 20px;
+
+  &:hover {
+    color: @hover-color;
+
+    & > .font-icon {
+      color: @hover-color;
+    }
+  }
+
+  &:active {
+    color: @active-color;
+
+    & > .font-icon {
+      color: @active-color;
+    }
+  }
+
+  &.disabled {
+    color: @disabled-color;
+    cursor: default;
+
+    & > .font-icon {
+      color: @disabled-color;
+    }
+  }
+
+  &.compact {
+    margin-left: 10px;
+    margin-right: 10px;
+
+    & > .submenu-icon {
+      display: none;
+    }
+  }
+
+  & > .font-icon {
+    color: @icon-color;
+    font-size: 17px;
+  }
+
+  &.menu-textandicon > .icon {
+    padding-right: @header-menu-textandicon-padding-right;
+  }
+}
+
+/* header: tools popup */
+
+.desktop-tool-box-item.popup-head {
+  height: @desktop-header-height - 1px;
+  border-left: 1px solid @border-color;
+  border-right: 1px solid @border-color;
+  cursor: pointer;
+  /*padding: 16px 20px 0 20px;*/
+  box-shadow: none;
+  border-top: none;
+  /*line-height: normal;*/
+  //#scout.vertical-align-helper-before();
+  /* OVERRIDE .desktop-tool-box-item.menu-item */
+  margin-left: 0;
+  margin-right: 0;
+  position: absolute;
+
+  .popup.down > & {
+    /* above selector is too less specific */
+    padding-top: 0;
+  }
+
+  &.selected > .font-icon {
+    font-size: 17px;
+  }
+}
+
+/* key boxes */
+
+.desktop-tool-box-item.menu-item .key-box {
+  bottom: 4px;
+
+  &.disabled {
+    background-color: @disabled-color;
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.js
new file mode 100644
index 0000000..387141b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/toolbox/DesktopToolBox.js
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.DesktopToolBox = function(menuBar) {
+  scout.DesktopToolBox.parent.call(this);
+};
+scout.inherits(scout.DesktopToolBox, scout.MenuBox);
+
+scout.DesktopToolBox.prototype._init = function(options) {
+  options.customMenuCssClasses = options.customMenuCssClasses || '';
+  options.customMenuCssClasses += ' desktop-tool-box-item';
+  scout.DesktopToolBox.parent.prototype._init.call(this, options);
+};
+
+/**
+ * @override
+ */
+scout.DesktopToolBox.prototype._initMenu = function(menu) {
+  scout.DesktopToolBox.parent.prototype._initMenu.call(this, menu);
+  menu.popupOpeningDirectionX = 'left';
+};
+
+/**
+ * @override
+ */
+scout.DesktopToolBox.prototype._render = function($parent) {
+  scout.DesktopToolBox.parent.prototype._render.call(this, $parent);
+  this.$container.addClass('desktop-tool-box');
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.css
similarity index 94%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.css
index 46a7fdf..6a7b8db 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.css
@@ -10,12 +10,12 @@
  ******************************************************************************/
 .view-button-tab {
   display: inline-block;
-  height: @view-buttons-height;
+  height: @view-button-box-height;
   background-color: @view-button-tab-background-color;
   color: @view-button-tab-color;
   border-right: solid 1px @border-color;
   white-space: nowrap;
-  min-width: 60px;
+  min-width: 50px;
   position: relative;
   text-align: center;
   #scout.vertical-align-helper-before();
@@ -32,6 +32,12 @@
     }
   }
 
+  &:active {
+    &:not(.selected) > .font-icon {
+      color: @active-color;
+    }
+  }
+
   &.selected {
     background-color: @view-button-tab-active-background-color;
     color: @view-button-tab-active-color;
@@ -102,7 +108,7 @@
 
 .view-menu-item {
   padding: 0px 15px 0px 15px;
-  line-height: @desktop-taskbar-height - 1px;
+  line-height: @desktop-header-height - 1px;
   border-top: solid 1px @border-color;
   cursor: pointer;
   color: @text-color;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.js
similarity index 82%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.js
index 8cd8fc8..526c34e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewButton.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButton.js
@@ -10,7 +10,7 @@
  ******************************************************************************/
 scout.ViewButton = function() {
   scout.ViewButton.parent.call(this);
-  this._breadcrumbEnabled = false;
+  this.inBackground = false;
 };
 scout.inherits(scout.ViewButton, scout.Action);
 
@@ -22,6 +22,12 @@
   }
 };
 
+scout.ViewButton.prototype._renderProperties = function() {
+  scout.ViewButton.parent.prototype._renderProperties.call(this);
+
+  this._renderInBackground();
+};
+
 scout.ViewButton.prototype._isMenu = function() {
   return this.displayStyle === 'MENU';
 };
@@ -59,14 +65,26 @@
   }
 };
 
+scout.ViewButton.prototype._renderInBackground = function() {
+  this.$container.toggleClass('in-background', this.inBackground);
+};
+
 scout.ViewButton.prototype.last = function() {
   this.$container.addClass('last');
 };
 
-scout.ViewButton.prototype.setBreadcrumbEnabled = function(enabled) {
-  this._breadcrumbEnabled = enabled;
-  this._renderText();
-  this._renderSelected();
+scout.ViewButton.prototype.sendToBack = function() {
+  this.inBackground = true;
+  if (this.rendered) {
+    this._renderInBackground();
+  }
+};
+
+scout.ViewButton.prototype.bringToFront = function() {
+  this.inBackground = false;
+  if (this.rendered) {
+    this._renderInBackground();
+  }
 };
 
 scout.ViewButton.prototype._onMouseEvent = function(event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktopNavigation.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.css
similarity index 76%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktopNavigation.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.css
index e4eb6ba..f3f1b44 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/MobileDesktopNavigation.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.css
@@ -8,6 +8,11 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-.desktop-navigation {
-  width: 100%;
+.view-button-box {
+  display: inline-block;
+  vertical-align: top;
+  height: @view-button-box-height;
+  white-space: nowrap;
+  #scout.font-text-large();
+  overflow: hidden;
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.js
new file mode 100644
index 0000000..9413a9b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBox.js
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.ViewButtonBox = function() {
+  scout.ViewButtonBox.parent.call(this);
+  this.viewMenuTab;
+  this.viewTabs;
+  this._desktopOutlineChangedHandler = this._onDesktopOutlineChanged.bind(this);
+  this._viewButtonPropertyChangeHandler = this._onViewButtonPropertyChange.bind(this);
+};
+scout.inherits(scout.ViewButtonBox, scout.Widget);
+
+scout.ViewButtonBox.prototype._init = function(model) {
+  scout.ViewButtonBox.parent.prototype._init.call(this, model);
+  this.desktop = this.session.desktop;
+  this.viewButtons = model.viewButtons || [];
+};
+
+scout.ViewButtonBox.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('view-button-box');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.ViewButtonBoxLayout(this));
+  this.viewMenuTab = scout.create('ViewMenuTab', {parent: this,
+    viewMenus: this._viewButtons('MENU')
+  });
+  this.viewMenuTab.render(this.$container);
+
+  this.viewTabs = this._viewButtons('TAB');
+  this.viewTabs.forEach(function(viewTab, i) {
+    viewTab.setParent(this);
+    viewTab.render(this.$container);
+    if (i === this.viewTabs.length - 1) {
+      viewTab.last();
+    }
+  }, this);
+
+  this._onDesktopOutlineChanged();
+  this.viewButtons.forEach(function(viewButton) {
+    viewButton.on('propertyChange', this._viewButtonPropertyChangeHandler);
+  }, this);
+  this.desktop.on('outlineChanged', this._desktopOutlineChangedHandler);
+};
+
+scout.ViewButtonBox.prototype._remove = function() {
+  this.desktop.off('outlineChanged', this._desktopOutlineChangedHandler);
+  this.viewButtons.forEach(function(viewButton) {
+    viewButton.off('selected', this._viewButtonPropertyChangeHandler);
+  }, this);
+
+  scout.ViewButtonBox.parent.prototype._remove.call(this);
+};
+
+scout.ViewButtonBox.prototype._viewButtons = function(displayStyle) {
+  var viewButtons = [];
+  this.viewButtons.forEach(function(viewButton) {
+    if (displayStyle === undefined ||
+      displayStyle === viewButton.displayStyle) {
+      viewButtons.push(viewButton);
+    }
+  });
+  return viewButtons;
+};
+
+scout.ViewButtonBox.prototype.sendToBack = function() {
+  this.viewMenuTab.sendToBack();
+  this.viewTabs.forEach(function(button) {
+    button.sendToBack();
+  }, this);
+};
+
+scout.ViewButtonBox.prototype.bringToFront = function() {
+  this.viewMenuTab.bringToFront();
+  this.viewTabs.forEach(function(button) {
+    button.bringToFront();
+  }, this);
+};
+
+/**
+ * This method updates the state of the view-menu-tab and the selected state of outline-view-button-box.
+ * This method must also work in offline mode.
+ */
+scout.ViewButtonBox.prototype._onDesktopOutlineChanged = function(event) {
+  var outline = this.desktop.outline;
+  this._viewButtons().forEach(function(viewTab) {
+    if (viewTab instanceof scout.OutlineViewButton) {
+      viewTab.onOutlineChanged(outline);
+    }
+  });
+};
+
+scout.ViewButtonBox.prototype._onViewButtonSelected = function(event) {
+  // Deselect other togglable view buttons
+  this.viewButtons.forEach(function(viewButton) {
+    if (viewButton !== event.source && viewButton.isToggleAction()) {
+      viewButton.setSelected(false);
+    }
+  }, this);
+
+  // Inform viewMenu tab about new selection
+  this.viewMenuTab.onViewButtonSelected();
+};
+
+scout.ViewButtonBox.prototype._onViewButtonPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('selected') !== -1) {
+    this._onViewButtonSelected(event);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBoxLayout.js
new file mode 100644
index 0000000..157e50e
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewButtonBoxLayout.js
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.ViewButtonBoxLayout = function(viewButtonBox) {
+  scout.ViewButtonBoxLayout.parent.call(this);
+  this.viewButtonBox = viewButtonBox;
+};
+scout.inherits(scout.ViewButtonBoxLayout, scout.AbstractLayout);
+
+scout.ViewButtonBoxLayout.prototype.layout = function($container) {
+  var htmlComp = this.viewButtonBox.htmlComp,
+    containerBounds = htmlComp.getBounds(),
+    $visibleTabs = $container.children(':visible'),
+    tabCount = $visibleTabs.length,
+    tabWidth = (containerBounds.width / tabCount);
+
+  $visibleTabs.each(function() {
+    var $tab = $(this);
+    // only set width, use css height
+    $tab.cssWidth(tabWidth);
+  });
+};
+
+scout.ViewButtonBoxLayout.prototype.preferredLayoutSize = function($container) {
+  // View buttons have an absolute css height set -> useCssSize = true
+  return scout.graphics.prefSize($container, false, {
+    useCssSize: true
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuOpenKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuOpenKeyStroke.js
similarity index 87%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuOpenKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuOpenKeyStroke.js
index f9ac225..6720229 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuOpenKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuOpenKeyStroke.js
@@ -11,15 +11,15 @@
 /**
  * Keystroke to open the 'ViewMenuPopup' on 'F2'.
  */
-scout.ViewMenuOpenKeyStroke = function(desktopNavigation, keyStroke) {
+scout.ViewMenuOpenKeyStroke = function(viewMenuTab) {
   scout.ViewMenuOpenKeyStroke.parent.call(this);
-  this.field = desktopNavigation;
+  this.field = viewMenuTab;
 
   this.which = [scout.keys.F2];
   this.stopPropagation = true;
 
   this.renderingHints.$drawingArea = function($drawingArea, event) {
-    return this.field.viewMenuTab.$container;
+    return this.field.$container;
   }.bind(this);
 };
 scout.inherits(scout.ViewMenuOpenKeyStroke, scout.KeyStroke);
@@ -28,7 +28,7 @@
  * @override KeyStroke.js
  */
 scout.ViewMenuOpenKeyStroke.prototype.handle = function(event) {
-  this.field.doViewMenuAction(event);
+  this.field.togglePopup();
 };
 
 scout.ViewMenuOpenKeyStroke.prototype._postRenderKeyBox = function($drawingArea) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuPopup.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuPopup.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuPopup.js
index 3ff6ef5..fdcf515 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/ViewMenuPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuPopup.js
@@ -17,7 +17,6 @@
   this.$headBlueprint;
   this.viewMenus;
   this._naviBounds;
-  this._breadcrumbEnabled;
   this._tooltip;
 };
 scout.inherits(scout.ViewMenuPopup, scout.PopupWithHead);
@@ -30,7 +29,6 @@
   this.$headBlueprint = this.$tab;
   this.viewMenus = options.viewMenus;
   this._naviBounds = options.naviBounds;
-  this._breadcrumbEnabled = options.breadcrumbEnabled;
 };
 
 scout.ViewMenuPopup.MAX_MENU_WIDTH = 300;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js
new file mode 100644
index 0000000..ac0b224
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+/**
+ * Shows a list of view buttons with displayStyle=MENU
+ * and shows the title of the active view button, if the view button is one
+ * of the view buttons contained in the menu.
+ */
+scout.ViewMenuTab = function() {
+  scout.ViewMenuTab.parent.call(this);
+  this.$container;
+  this.$arrowIcon; // small "arrow down" icon at the right side of the icon
+
+  this.viewButton = null;
+  this.selected = false;
+  this.iconId;
+  this.inBackground = false;
+  this.visible = true;
+
+  this.defaultIconId = scout.icons.OUTLINE;
+  this._addEventSupport();
+  this._viewMenuPropertyChangeHandler = this._onViewMenuPropertyChange.bind(this);
+};
+scout.inherits(scout.ViewMenuTab, scout.Widget);
+
+scout.ViewMenuTab.prototype._init = function(model) {
+  scout.ViewMenuTab.parent.prototype._init.call(this, model);
+  this.viewMenus = model.viewMenus;
+  this.viewMenus.forEach(function(viewMenu) {
+    viewMenu.setParent(this);
+    viewMenu.on('propertyChange', this._viewMenuPropertyChangeHandler);
+  }, this);
+  this._update();
+  this.updateVisibility();
+};
+
+scout.ViewMenuTab.prototype._initKeyStrokeContext = function(keyStrokeContext) {
+  scout.ViewMenuTab.parent.prototype._initKeyStrokeContext.call(this, keyStrokeContext);
+
+  // Bound to desktop
+  this.desktopKeyStrokeContext = new scout.KeyStrokeContext();
+  this.desktopKeyStrokeContext.invokeAcceptInputOnActiveValueField = true;
+  this.desktopKeyStrokeContext.$bindTarget = this.session.desktop.$container;
+  this.desktopKeyStrokeContext.$scopeTarget = this.$container;
+  this.desktopKeyStrokeContext.registerKeyStroke([
+    new scout.ViewMenuOpenKeyStroke(this)
+  ]);
+};
+
+/**
+ * 1. look for a selected view-button
+ * 2. look for any view-button
+ * 3. if there is no view-button menu should not be visible
+ */
+scout.ViewMenuTab.prototype._update = function() {
+  var viewButton = this._findSelectedViewButton();
+  if (viewButton) {
+    this.selected = true;
+  } else {
+    viewButton = this.viewMenus[0];
+    this.selected = false;
+  }
+  this.viewButton = viewButton;
+
+  // Use iconId from outline view button (defaultIconId as fallback)
+  this.iconId = (this.outlineViewButton && this.outlineViewButton.iconId) || this.defaultIconId;
+};
+
+scout.ViewMenuTab.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('view-button-tab')
+    .unfocusable()
+    .on('mousedown', this.togglePopup.bind(this));
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+
+  this.$arrowIcon = this.$container
+    .appendSpan('arrow-icon')
+    .on('mousedown', this.togglePopup.bind(this));
+
+  this.session.keyStrokeManager.installKeyStrokeContext(this.desktopKeyStrokeContext);
+};
+
+scout.ViewMenuTab.prototype._remove = function() {
+  this.session.keyStrokeManager.uninstallKeyStrokeContext(this.desktopKeyStrokeContext);
+  scout.ViewMenuTab.parent.prototype._remove.call(this);
+};
+
+scout.ViewMenuTab.prototype._renderProperties = function() {
+  this._renderVisible();
+  this._renderIconId();
+  this._renderSelected();
+  this._renderInBackground();
+};
+
+scout.ViewMenuTab.prototype._renderVisible = function() {
+  this.$container.setVisible(this.visible);
+  this.invalidateLayoutTree();
+};
+
+scout.ViewMenuTab.prototype._renderSelected = function() {
+  this.$container.select(this.selected);
+  this._updateArrowIconVisibility();
+};
+
+scout.ViewMenuTab.prototype._renderIconId = function() {
+  this.$container.icon(this.iconId);
+};
+
+scout.ViewMenuTab.prototype._renderInBackground = function() {
+  this.$container.toggleClass('in-background', this.inBackground);
+};
+
+scout.ViewMenuTab.prototype._updateArrowIconVisibility = function() {
+  this.$arrowIcon.toggleClass('hidden', !this.selected || this.inBackground);
+};
+
+scout.ViewMenuTab.prototype._findSelectedViewButton = function() {
+  var viewMenu;
+  for (var i = 0; i < this.viewMenus.length; i++) {
+    viewMenu = this.viewMenus[i];
+    if (viewMenu.selected) {
+      return viewMenu;
+    }
+  }
+  return null;
+};
+
+/**
+ * Toggles the 'view menu popup', or brings the outline content to the front if in background.
+ */
+scout.ViewMenuTab.prototype.togglePopup = function() {
+  if (this.selected) {
+    if (this.inBackground) {
+      this.session.desktop.bringOutlineToFront(this.viewButton.outline);
+    } else {
+      // Open or close the popup.
+      if (this.popup) {
+        this._closePopup();
+      } else {
+        this._openPopup();
+      }
+      return false; // menu won't open if we didn't abort the mousedown-event
+    }
+  } else {
+    this.viewButton.doAction();
+  }
+};
+
+scout.ViewMenuTab.prototype._openPopup = function() {
+  if (this.popup) {
+    // already open
+    return;
+  }
+  var naviBounds = scout.graphics.bounds(this.$container.parent(), true);
+  this.popup = scout.create('ViewMenuPopup', {
+    parent: this,
+    $tab: this.$container,
+    viewMenus: this.viewMenus,
+    naviBounds: naviBounds
+  });
+  // The class needs to be added to the container before the popup gets opened so that the modified style may be copied to the head.
+  this.$container.addClass('popup-open');
+  this.popup.headText = this.text;
+  this.popup.open();
+  this.popup.on('remove', function(event) {
+    this.$container.removeClass('popup-open');
+    this.popup = null;
+  }.bind(this));
+};
+
+scout.ViewMenuTab.prototype._closePopup = function() {
+  if (this.popup) {
+    this.popup.close();
+  }
+};
+
+scout.ViewMenuTab.prototype.setSelected = function(selected) {
+  if (selected === this.selected) {
+    return;
+  }
+  this._setProperty('selected', selected);
+  if (this.rendered) {
+    this._renderSelected();
+  }
+};
+
+scout.ViewMenuTab.prototype.setIconId = function(iconId) {
+  if (iconId === this.iconId) {
+    return;
+  }
+  this._setProperty('iconId', iconId);
+  if (this.rendered) {
+    this._renderIconId();
+  }
+};
+
+scout.ViewMenuTab.prototype.setVisible = function(visible) {
+  if (this.visible === visible) {
+    return;
+  }
+  this._setProperty('visible', visible);
+  if (this.rendered) {
+    this._renderVisible();
+  }
+};
+
+scout.ViewMenuTab.prototype.updateVisibility = function() {
+  this.setVisible(this.viewMenus.some(function(viewMenu) {
+    return viewMenu.visible;
+  }));
+};
+
+scout.ViewMenuTab.prototype.sendToBack = function() {
+  this.inBackground = true;
+  this._renderInBackground();
+  this._renderSelected();
+  this._closePopup();
+};
+
+scout.ViewMenuTab.prototype.bringToFront = function() {
+  this.inBackground = false;
+  this._renderInBackground();
+  this._renderSelected();
+};
+
+scout.ViewMenuTab.prototype._onViewMenuPropertyChange = function(event) {
+  if (event.changedProperties.indexOf('visible') !== -1) {
+    this.updateVisibility();
+  }
+};
+
+scout.ViewMenuTab.prototype.onViewButtonSelected = function() {
+  var viewButton = this._findSelectedViewButton();
+  if (viewButton) {
+    // only change if a new viewMenu was selected, otherwise keep old viewButton in order to reselect it when the viewMenu gets selected again
+    this.viewButton = viewButton;
+    // Use iconId from selected view button or defaultIconId as fallback
+    this.setIconId(this.viewButton.iconId || this.defaultIconId);
+    this.setSelected(true);
+  } else {
+    this.setSelected(false);
+  }
+  this._closePopup();
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.css
index dbb5972..97715c9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.css
@@ -100,7 +100,7 @@
   }
 
   &.shown {
-    #scout.animation-name(fade-slidein-top);
+    #scout.animation-name(fade-short-drop);
     #scout.animation-duration(0.5s);
   }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.js
index f3c2ba9..a55c892 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooser.js
@@ -94,7 +94,6 @@
         } finally {
           // "onAjaxAlways"
           this.session.setBusy(false);
-          this.session.layoutValidator.validate();
         }
       }.bind(this));
     this.$fileInputField
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooserController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooserController.js
index e2578bd..ec65cc2 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooserController.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/filechooser/FileChooserController.js
@@ -21,8 +21,7 @@
 /**
  * Adds the given file chooser to this controller and renders it.
  */
-scout.FileChooserController.prototype.registerAndRender = function(fileChooserAdapterId) {
-  var fileChooser = this.session.getOrCreateModelAdapter(fileChooserAdapterId, this.displayParent);
+scout.FileChooserController.prototype.registerAndRender = function(fileChooser) {
   fileChooser._setProperty('displayParent', this.displayParent);
   this.displayParent.fileChoosers.push(fileChooser);
   this._render(fileChooser);
@@ -31,8 +30,7 @@
 /**
  * Removes the given file chooser from this controller and DOM. However, the file chooser's adapter is not destroyed. That only happens once the file chooser is closed.
  */
-scout.FileChooserController.prototype.unregisterAndRemove = function(fileChooserAdapterId) {
-  var fileChooser = this.session.getModelAdapter(fileChooserAdapterId);
+scout.FileChooserController.prototype.unregisterAndRemove = function(fileChooser) {
   if (fileChooser) {
     scout.arrays.remove(this.displayParent.fileChoosers, fileChooser);
     this._remove(fileChooser);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/FocusContext.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/FocusContext.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusContext.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/FocusManager.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusManager.js
similarity index 98%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/FocusManager.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusManager.js
index 71420b2..77b4f5e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/FocusManager.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/FocusManager.js
@@ -187,7 +187,7 @@
  * @return true if focus was gained, or false otherwise.
  */
 scout.FocusManager.prototype.requestFocus = function(element, filter) {
-  element = element instanceof jQuery ? element[0] : element;
+  element = element instanceof $ ? element[0] : element;
 
   var activeContext = this._findActiveContext();
   if (activeContext) {
@@ -218,7 +218,7 @@
       continue;
     }
     // Check if the element (or one of its parents) does not want to be the first focusable element
-    // FIXME awe, bsh: replace this concept with Form#renderInitialFocusEnabled: currently we cannot set
+    // FIXME awe, bsh: (focus) replace this concept with Form#renderInitialFocusEnabled: currently we cannot set
     // that property on the model (only by JS). Add a model-property so we can do this on the model.
     // May be useful for ticket-form too, since that form currently focuses a random link in the
     // history table.
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/focusRule.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/focusRule.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/focusRule.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/focusRule.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/focusUtils.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/focusUtils.js
similarity index 89%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/focusUtils.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/focusUtils.js
index 6c2b3bb..57c6cda 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/focusUtils.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/focus/focusUtils.js
@@ -15,6 +15,7 @@
 
   /**
    * @return whether the given element is focusable by mouse.
+   * @memberOf scout.focusUtils
    */
   isFocusableByMouse: function(element) {
     var $element = $(element);
@@ -53,6 +54,12 @@
     var $el = $element;
     while ($el.css('user-select') === 'auto') {
       $el = $el.parent();
+      // Fix for Firefox: parent of BODY element is HtmlDocument. When calling $el.css on the HtmlDocument
+      // Firefox throws an error that ownerDocument is undefined. Thus we don't go higher than BODY element
+      // and assume body is never selectable.
+      if ($el.is('body')) {
+        return false;
+      }
     }
     if ($el.css('user-select') === 'none') {
       return false;
@@ -81,7 +88,7 @@
       return false;
     }
     var activeElement;
-    if (element instanceof jQuery) {
+    if (element instanceof $) {
       activeElement = element.activeElement(true);
       element = element[0];
     } else {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.css
index a341bab..871f754 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.css
@@ -15,7 +15,7 @@
   background-color: @form-background-color;
 }
 
-.view {
+.view:not(.detail-form) {
   & > .root-group-box > .main-menubar {
     #scout.main-menubar-light;
   }
@@ -68,21 +68,9 @@
     }
   }
 
-  & > .closable {
+  & > .closer {
     position: absolute;
     right: 5px;
     margin: 8px;
-    #scout.font-icon();
-    font-size: 17px;
-    cursor: pointer;
-    color: @icon-light-color;
-
-    &::before {
-      content: @icon-remove;
-    }
-
-    &:hover {
-      color: @hover-color;
-    }
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.js
index 40c6772..26d5c68 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/Form.js
@@ -74,14 +74,17 @@
     .addClass(this.isDialog() ? 'dialog' : 'form')
     .data('model', this);
 
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.pixelBasedSizing = false;
   if (this.isDialog()) {
     layout = new scout.DialogLayout(this);
+    this.htmlComp.validateRoot = true;
     $handle = this.$container.appendDiv('drag-handle');
     this.$container.makeDraggable($handle, $.throttle(this.onMove.bind(this), 1000 / 60)); // 60fps
 
     if (this.closable) {
       this.$container
-        .appendDiv('closable')
+        .appendDiv('closer')
         .on('click', this.close.bind(this));
     }
     var $myWindow = this.$container.window();
@@ -92,10 +95,10 @@
       }.bind(this),
 
       resize: function(event, ui) {
-        var autoSizeOld = this.htmlComp._layout.autoSize;
-        this.htmlComp._layout.autoSize = false;
+        var autoSizeOld = this.htmlComp.layout.autoSize;
+        this.htmlComp.layout.autoSize = false;
         this.htmlComp.revalidateLayout();
-        this.htmlComp._layout.autoSize = autoSizeOld;
+        this.htmlComp.layout.autoSize = autoSizeOld;
         // jquery ui resize event bubbles up to the window -> never propagate
         return false;
       }.bind(this)
@@ -105,9 +108,7 @@
     layout = new scout.FormLayout(this);
   }
 
-  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
   this.htmlComp.setLayout(layout);
-  this.htmlComp.pixelBasedSizing = false;
   this.rootGroupBox.render(this.$container);
 
   if (this._locked) {
@@ -124,7 +125,7 @@
 };
 
 scout.Form.prototype._postRender = function() {
-  this._trigger('rendered');
+  this.trigger('rendered');
   this._installFocusContext();
 
   if (this.renderInitialFocusEnabled) {
@@ -221,14 +222,6 @@
   return false;
 };
 
-scout.Form.prototype.onResize = function() {
-  $.log.trace('(Form#onResize) window was resized -> layout Form container');
-  var htmlComp = scout.HtmlComponent.get(this.$container);
-  var $parent = this.$container.parent();
-  var parentSize = new scout.Dimension($parent.width(), $parent.height());
-  htmlComp.setSize(parentSize);
-};
-
 scout.Form.prototype.onMove = function(newOffset) {
   this.trigger('move', newOffset);
 };
@@ -238,6 +231,10 @@
 };
 
 scout.Form.prototype._remove = function() {
+  this.formController.remove();
+  this.messageBoxController.remove();
+  this.fileChooserController.remove();
+
   // FIXME awe: call acceptInput() when form is removed
   // test-case: SimpleWidgets outline, detail-forms, switch between nodes
   this._glassPaneRenderer.removeGlassPanes();
@@ -257,24 +254,6 @@
   this._updateTitle();
 };
 
-scout.Form.prototype._onRequestFocus = function(formFieldId) {
-  var formField = this.session.getOrCreateModelAdapter(formFieldId, this);
-  if (formField) {
-    // FIXME awe, nbu, dwi: hier darf focus nicht direkt aufgerufen werden. Es muss geprüft werden ob
-    // der focuscontext überhaupt "aktivierbar" ist, auch die modalität muss hier berücksichtigt werden
-    // je nach dem kann es sein, dass das field gar nicht den fokus kriegt.
-    formField.$field.focus();
-  }
-};
-
-scout.Form.prototype.onModelAction = function(event) {
-  if (event.type === 'requestFocus') {
-    this._onRequestFocus(event.formField);
-  } else {
-    scout.Form.parent.prototype.onModelAction.call(this, event);
-  }
-};
-
 /**
  * Method invoked when:
  *  - this is a 'detailForm' and the outline content is displayed;
@@ -287,15 +266,13 @@
 
   // If the parent was resized while this view was detached, the view has a wrong size.
   if (this.isView()) {
-    var htmlComp = scout.HtmlComponent.get(this.$container);
-    var htmlParent = htmlComp.getParent();
-    htmlComp.setSize(htmlParent.getSize());
+    this.invalidateLayoutTree(false);
   }
 
   this.session.detachHelper.afterAttach(this.$container);
 
   // form is attached even if children are not yet
-  if ((this.isView() || this.isDialog()) && this.session.desktop._outlineContent !== this) {
+  if ((this.isView() || this.isDialog()) && !this.detailForm) {
     //notify model this form is active
     this.session.desktop._setFormActivated(this);
   }
@@ -361,10 +338,10 @@
   if (this.$container) {
     return [this.$container];
   } else {
-    var renderedHandler = function(event) {
-      deferred.ready([event.eventOn.$container]);
-    };
     var deferred = new scout.DeferredGlassPaneTarget();
+    var renderedHandler = function(event) {
+      deferred.ready([event.source.$container]);
+    };
     this.one('rendered', renderedHandler);
     this.one('destroy', function() {
       this.off('rendered', renderedHandler);
@@ -381,3 +358,24 @@
 scout.Form.prototype.inFront = function() {
   return this.rendered && this.attached;
 };
+
+scout.Form.prototype.requestFocus = function(formField) {
+  if (!formField) {
+    return;
+  }
+
+  formField.focus();
+};
+
+scout.Form.prototype._onRequestFocus = function(formFieldId) {
+  var formField = this.session.getOrCreateModelAdapter(formFieldId, this);
+  this.requestFocus(formField);
+};
+
+scout.Form.prototype.onModelAction = function(event) {
+  if (event.type === 'requestFocus') {
+    this._onRequestFocus(event.formField);
+  } else {
+    scout.Form.parent.prototype.onModelAction.call(this, event);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormController.js
index 094f2d6..b16447b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormController.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormController.js
@@ -23,8 +23,7 @@
  * position is only used if form is a view. this position determines at which position the tab is placed.
  * if select view is set the view rendered in _renderView is also selected.
  */
-scout.FormController.prototype.registerAndRender = function(formAdapterId, position, selectView) {
-  var form = this.session.getOrCreateModelAdapter(formAdapterId, this.displayParent);
+scout.FormController.prototype.registerAndRender = function(form, position, selectView) {
   form._setProperty('displayParent', this.displayParent);
   if (form.isPopupWindow()) {
     this._renderPopupWindow(form);
@@ -42,8 +41,7 @@
 /**
  * Removes the given view or dialog from this controller and DOM. However, the form's adapter is not destroyed. That only happens once the Form is closed.
  */
-scout.FormController.prototype.unregisterAndRemove = function(formAdapterId) {
-  var form = this.session.getModelAdapter(formAdapterId);
+scout.FormController.prototype.unregisterAndRemove = function(form) {
   if (!form) {
     return;
   }
@@ -71,16 +69,27 @@
   }.bind(this));
   this.displayParent.views.forEach(function(view, position) {
     view._setProperty('displayParent', this.displayParent);
-    this._renderView(view, false, position);
+    this._renderView(view, false, position, false);
+  }.bind(this));
+};
+
+/**
+ * Removes all dialogs and views registered with this controller.
+ */
+scout.FormController.prototype.remove = function() {
+  this.displayParent.dialogs.forEach(function(dialog) {
+    this._removeDialog(dialog, false);
+  }.bind(this));
+  this.displayParent.views.forEach(function(view, position) {
+    this._removeView(view, false, position);
   }.bind(this));
 };
 
 /**
  * Activates the given view or dialog.
  */
-scout.FormController.prototype.activateForm = function(formAdapterId) {
-  var form = this.session.getOrCreateModelAdapter(formAdapterId, this.displayParent);
-  //if form is not rendered it could not be activated.
+scout.FormController.prototype.activateForm = function(form) {
+  // if form is not rendered it could not be activated.
   if (!form.rendered) {
     return;
   }
@@ -92,6 +101,15 @@
   }
 };
 
+scout.FormController.prototype.acceptView = function(view, register, position, selectView) {
+  // Only render view if 'displayParent' is rendered yet; if not, the view will be rendered once 'displayParent' is rendered.
+  if (!this.displayParent.rendered) {
+    return false;
+  }
+
+  return true;
+};
+
 scout.FormController.prototype._renderView = function(view, register, position, selectView) {
   if (register) {
     if (position !== undefined) {
@@ -101,56 +119,71 @@
     }
   }
 
-  // Only render view if 'displayParent' is rendered yet; if not, the view will be rendered once 'displayParent' is rendered.
-  // Except when Desktop is in initial rendering-> the tab has to be rendered to exist in overview
-  if (!this.displayParent.rendered && !this.session.desktop.initialFormRendering) {
+  // Display parent may implement acceptView, if not implemented -> use default
+  if (this.displayParent.acceptView) {
+    if (!this.displayParent.acceptView(view)) {
+      return;
+    }
+  } else if (!this.acceptView(view)) {
     return;
   }
+
   // Prevent "Already rendered" errors / FIXME bsh, dwi: Remove this hack! Fix in on model if possible. See #162954.
   if (view.rendered) {
-    return;
+    return false;
   }
-
-  var viewTabsController = this.session.desktop.viewTabsController;
-
-  // Create the view-tab.
-  var viewTab = viewTabsController.createAndRenderViewTab(view, this.displayParent.views.indexOf(view));
-  if (selectView) {
-    viewTabsController.selectViewTab(viewTab);
+  if (this.session.desktop.displayStyle === scout.Desktop.DisplayStyle.COMPACT && !this.session.desktop.bench) {
+    // Show bench and hide navigation if this is the first view to be shown
+    this.session.desktop.switchToBench();
   }
+  this.session.desktop.bench.addView(view, selectView);
+};
+
+scout.FormController.prototype.acceptDialog = function(dialog) {
+  // Only render dialog if 'displayParent' is rendered yet; if not, the dialog will be rendered once 'displayParent' is rendered.
+  if (!this.displayParent.rendered) {
+    return false;
+  }
+  return true;
 };
 
 scout.FormController.prototype._renderDialog = function(dialog, register) {
+  var desktop = this.session.desktop;
   if (register) {
     this.displayParent.dialogs.push(dialog);
   }
-  if (this.displayParent instanceof scout.Form) {
-    dialog.on('remove', function() {
-      if (this.displayParent.dialogs.length > 0) {
-        this.session.desktop._setFormActivated(this.displayParent.dialogs[this.displayParent.dialogs.length - 1]);
-      } else if (this.displayParent.parent instanceof scout.Outline) {
-        // if displayParent is a page
-        this.session.desktop._setOutlineActivated();
-      } else {
-        this.session.desktop._setFormActivated(this.displayParent);
-      }
-    }.bind(this));
+
+  // Display parent may implement acceptDialog, if not implemented -> use default
+  if (this.displayParent.acceptDialog) {
+    if (!this.displayParent.acceptDialog(dialog)) {
+      return;
+    }
+  } else if (!this.acceptDialog(dialog)) {
+    return;
   }
 
-  // Only render dialog if 'displayParent' is rendered yet; if not, the dialog will be rendered once 'displayParent' is rendered.
-  if (!this.displayParent.rendered) {
-    return;
-  }
   // Prevent "Already rendered" errors / FIXME bsh, dwi: Remove this hack! Fix in on model if possible. See #162954.
   if (dialog.rendered) {
-    return;
+    return false;
   }
 
+  dialog.on('remove', function() {
+    if (this.displayParent.dialogs.length > 0) {
+      desktop._setFormActivated(this.displayParent.dialogs[this.displayParent.dialogs.length - 1]);
+    } else if (this.displayParent instanceof scout.Form && !this.displayParent.detailForm) {
+      // activate display parent, but not if it is the detail form
+      desktop._setFormActivated(this.displayParent);
+    } else {
+      desktop._setOutlineActivated();
+    }
+  }.bind(this));
+
   if (dialog.isPopupWindow()) {
     this._renderPopupWindow(dialog);
   } else {
-    dialog.render(this.session.desktop.$container);
+    dialog.render(desktop.$container);
     this._layoutDialog(dialog);
+    desktop._setFormActivated(dialog);
 
     // Only display the dialog if its 'displayParent' is visible to the user.
     if (!this.displayParent.inFront()) {
@@ -159,25 +192,29 @@
   }
 };
 
-scout.FormController.prototype._removeView = function(view) {
-  scout.arrays.remove(this.displayParent.views, view);
+scout.FormController.prototype._removeView = function(view, unregister) {
+  unregister = scout.nvl(unregister, true);
+  if (unregister) {
+    scout.arrays.remove(this.displayParent.views, view);
+  }
+  // in COMPACT case views are already removed.
   if (view.rendered) {
-    view.remove();
+    this.session.desktop.bench.removeView(view);
   }
 };
 
-scout.FormController.prototype._removeDialog = function(dialog) {
-  scout.arrays.remove(this.displayParent.dialogs, dialog);
+scout.FormController.prototype._removeDialog = function(dialog, unregister) {
+  unregister = scout.nvl(unregister, true);
+  if (unregister) {
+    scout.arrays.remove(this.displayParent.dialogs, dialog);
+  }
   if (dialog.rendered) {
     dialog.remove();
   }
 };
 
 scout.FormController.prototype._activateView = function(view) {
-  var viewTabsController = this.session.desktop.viewTabsController;
-
-  var viewTab = viewTabsController.viewTab(view);
-  viewTabsController.selectViewTab(viewTab);
+  this.session.desktop.bench.activateView(view);
 };
 
 scout.FormController.prototype._activateDialog = function(dialog) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenu.js
new file mode 100644
index 0000000..5ff67e8
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenu.js
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.FormMenu = function() {
+  scout.FormMenu.parent.call(this);
+  this._addAdapterProperties('form');
+};
+scout.inherits(scout.FormMenu, scout.Menu);
+
+scout.FormMenu.PopupStyle = {
+  DEFAULT: 'default',
+  MOBILE: 'mobile'
+};
+
+scout.FormMenu.prototype._init = function(model) {
+  scout.FormMenu.parent.prototype._init.call(this, model);
+
+  if (!this.popupStyle) {
+    if (this.session.userAgent.deviceType === scout.Device.Type.MOBILE) {
+      this.popupStyle = scout.FormMenu.PopupStyle.MOBILE;
+    } else {
+      this.popupStyle = scout.FormMenu.PopupStyle.DEFAULT;
+    }
+  }
+};
+
+scout.FormMenu.prototype._renderForm = function() {
+  if (!this.rendered) {
+    // Don't execute initially since _renderSelected will be executed
+    return;
+  }
+  this._renderSelected();
+};
+
+/**
+ * @override
+ */
+scout.FormMenu.prototype._renderText = function() {
+  scout.FormMenu.parent.prototype._renderText.call(this);
+  if (this.rendered && this.popup && this.popup instanceof scout.FormMenuPopup) {
+    this.popup.rerenderHead();
+    this.popup.position();
+  }
+};
+
+/**
+ * @override
+ */
+scout.FormMenu.prototype.cloneAdapter = function(modelOverride) {
+  modelOverride = modelOverride || {};
+  // If the FormMenu is put into a context menu it will be cloned.
+  // Cloning a form is not possible because it may non clonable components (Table, TabBox, etc.) -> exclude
+  // Luckily, it is not necessary to clone it since the form is never shown multiple times at once -> Just use the same instance
+  modelOverride.form = this.form;
+  return scout.FormMenu.parent.prototype.cloneAdapter.call(this, modelOverride);
+};
+
+/**
+ * @override
+ */
+scout.FormMenu.prototype._createPopup = function() {
+  // Menu bar should always be on the bottom
+  this.form.rootGroupBox.menuBar.bottom();
+
+  if (this.popupStyle === scout.FormMenu.PopupStyle.MOBILE) {
+    return scout.create('MobilePopup', {
+      parent: this.session.desktop, // use desktop to make _handleSelectedInEllipsis work (if parent is this and this were not rendered, popup.entryPoint would not work)
+      widget: this.form,
+      title: this.form.title
+    });
+  }
+
+  return scout.create('FormMenuPopup', {
+    parent: this,
+    formMenu: this,
+    openingDirectionX: this.popupOpeningDirectionX,
+    openingDirectionY: this.popupOpeningDirectionY
+  });
+};
+
+/**
+ * @override
+ */
+scout.FormMenu.prototype._doActionTogglesPopup = function() {
+  return !!this.form;
+};
+
+scout.FormMenu.prototype._handleSelectedInEllipsis = function() {
+  if (this.popupStyle !== scout.FormMenu.PopupStyle.MOBILE) {
+    scout.FormMenu.parent.prototype._handleSelectedInEllipsis.call(this);
+    return;
+  }
+  if (!this._doActionTogglesPopup()) {
+    return;
+  }
+  // The mobile popup is not atached to a header -> no need to open the parent menu, just show the poupup
+  if (this.selected) {
+    this._openPopup();
+  } else {
+    this._closePopup();
+  }
+};
+
+/**
+ * @override
+ */
+scout.FormMenu.prototype._createActionKeyStroke = function() {
+  return new scout.FormMenuActionKeyStroke(this);
+};
+
+/**
+ * FormMenuActionKeyStroke
+ */
+scout.FormMenuActionKeyStroke = function(action) {
+  scout.FormMenuActionKeyStroke.parent.call(this, action);
+};
+scout.inherits(scout.FormMenuActionKeyStroke, scout.ActionKeyStroke);
+
+scout.FormMenuActionKeyStroke.prototype.handle = function(event) {
+  this.field.toggle();
+};
+
+scout.FormMenuActionKeyStroke.prototype._postRenderKeyBox = function($drawingArea) {
+  if (this.field.iconId) {
+    var wIcon = $drawingArea.find('.icon').width();
+    var wKeybox = $drawingArea.find('.key-box').outerWidth();
+    var containerPadding = Number($drawingArea.css('padding-left').replace('px', ''));
+    var leftKeyBox = wIcon / 2 - wKeybox / 2 + containerPadding;
+    $drawingArea.find('.key-box').css('left', leftKeyBox + 'px');
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.css
similarity index 66%
copy from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css
copy to org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.css
index eaad555..bbb2a7c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.css
@@ -8,11 +8,16 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-.outline.breadcrumb > .tree-data {
-
-  & > .tree-node > .form {
-    /* reset alignment */
-    text-align: initial;
+.form-menu-popup {
+  & > .popup-head {
+    background-color: @form-background-color;
   }
 
+  & > .popup-body > .form > .root-group-box > .main-menubar {
+    background-color: @form-menu-popup-main-menubar-background-color;
+  }
+
+  & > .popup-deco {
+    background-color: @form-background-color;
+  }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.js
new file mode 100644
index 0000000..f062bbd
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopup.js
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.FormMenuPopup = function() {
+  scout.FormMenuPopup.parent.call(this);
+};
+scout.inherits(scout.FormMenuPopup, scout.PopupWithHead);
+
+scout.FormMenuPopup.prototype._init = function(options) {
+  this.formMenu = options.formMenu;
+  options.initialFocus = this.formMenu.form._initialFocusElement.bind(this.formMenu.form);
+  scout.FormMenuPopup.parent.prototype._init.call(this, options);
+
+  this.$formMenu = this.formMenu.$container;
+  this.$headBlueprint = this.$formMenu;
+  this.form = this.formMenu.form;
+};
+
+scout.FormMenuPopup.prototype._createLayout = function() {
+  return new scout.FormMenuPopupLayout(this);
+};
+
+scout.FormMenuPopup.prototype._render = function($parent) {
+  scout.FormMenuPopup.parent.prototype._render.call(this, $parent);
+  this.$container.addClass('form-menu-popup');
+
+  this.form.renderInitialFocusEnabled = false;
+  this.form.render(this.$body);
+  this.form.htmlComp.pixelBasedSizing = true;
+  this.form.setParent(this);
+};
+
+scout.FormMenuPopup.prototype._renderHead = function() {
+  scout.FormMenuPopup.parent.prototype._renderHead.call(this);
+  if (this.formMenu._customCssClasses) {
+    this._copyCssClassToHead(this.formMenu._customCssClasses);
+  }
+  this._copyCssClassToHead('unfocusable');
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopupLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopupLayout.js
similarity index 77%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopupLayout.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopupLayout.js
index 81b7e81..504f47c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopupLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormMenuPopupLayout.js
@@ -8,17 +8,17 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.FormToolPopupLayout = function(popup) {
-  scout.FormToolPopupLayout.parent.call(this, popup);
+scout.FormMenuPopupLayout = function(popup) {
+  scout.FormMenuPopupLayout.parent.call(this, popup);
   this.popup = popup;
 };
-scout.inherits(scout.FormToolPopupLayout, scout.PopupWithHeadLayout);
+scout.inherits(scout.FormMenuPopupLayout, scout.PopupWithHeadLayout);
 
-scout.FormToolPopupLayout.prototype.layout = function($container) {
+scout.FormMenuPopupLayout.prototype.layout = function($container) {
   var popupSize,
     htmlForm = this.popup.form.htmlComp;
 
-  scout.FormToolPopupLayout.parent.prototype.layout.call(this, $container);
+  scout.FormMenuPopupLayout.parent.prototype.layout.call(this, $container);
 
   popupSize = scout.graphics.getSize(this.popup.$body);
 
@@ -27,7 +27,7 @@
   htmlForm.setSize(popupSize);
 };
 
-scout.FormToolPopupLayout.prototype.preferredLayoutSize = function($container) {
+scout.FormMenuPopupLayout.prototype.preferredLayoutSize = function($container) {
   var htmlComp = this.popup.htmlComp,
     htmlForm = this.popup.form.htmlComp,
     prefSize;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolButton.js
deleted file mode 100644
index 425661a..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolButton.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.FormToolButton = function() {
-  scout.FormToolButton.parent.call(this);
-  this._addAdapterProperties('form');
-};
-scout.inherits(scout.FormToolButton, scout.Menu);
-
-scout.FormToolButton.prototype._renderForm = function() {
-  if (!this.rendered) {
-    // Don't execute initially since _renderSelected will be executed
-    return;
-  }
-  this._renderSelected();
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._renderText = function() {
-  scout.FormToolButton.parent.prototype._renderText.call(this);
-  if (this.rendered && this.popup) {
-    this.popup.rerenderHead();
-    this.popup.position();
-  }
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._renderCssClass = function() {
-  scout.FormToolButton.parent.prototype._renderCssClass.call(this);
-  if (this.rendered && this.popup && this.popup instanceof scout.FormToolPopup) {
-    this.popup.rerenderHead();
-    this.popup.position();
-  }
-};
-
-
-/**
- *
- * @override
- * form of a formToolbutton can be set to null and is set to a real form by model
- * so we have to update and clone it after it set.
- */
-scout.FormToolButton.prototype.cloneAdapter = function(modelOverride) {
-  var cloneAdapter = scout.FormToolButton.parent.prototype.cloneAdapter.call(this);
-  cloneAdapter.formChangeListener = this._handleOriginalFormChange.bind(cloneAdapter);
-  this.on('propertyChange', cloneAdapter.formChangeListener);
-  cloneAdapter.visible=false;
-  return cloneAdapter;
-};
-
-scout.FormToolButton.prototype._handleOriginalFormChange = function(event){
-  if(event.newProperties.form){
-    this.form =  this.session.getModelAdapter(event.newProperties.form).cloneAdapter({
-      parent: this
-    });
-  } else if (event.newProperties.form === null){
-    this.form = null;
-  }
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._remove = function() {
-  if(this.cloneOf){
-    this.cloneOf.off('propertyChange', this.formChangeListener);
-  }
-  scout.FormToolButton.parent.prototype._remove.call(this);
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._createPopup = function() {
-  return scout.create('FormToolPopup', {
-    parent: this,
-    formToolButton: this,
-    openingDirectionX: this.popupOpeningDirectionX,
-    openingDirectionY: this.popupOpeningDirectionY
-  });
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._doActionTogglesPopup = function() {
-  return !!this.form;
-};
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._doAction = function(event) {
-  //clones in submenus and contextmenues do not execute any action
-  if(this.formToolButton.form.cloneOf){
-    return false;
-  }
-  scout.FormToolButton.parent.prototype._doAction.call(this,event);
-};
-
-
-/**
- * @override
- */
-scout.FormToolButton.prototype._createActionKeyStroke = function() {
-  return new scout.FormToolButtonActionKeyStroke(this);
-};
-
-/**
- * FormToolButtonActionKeyStroke
- */
-scout.FormToolButtonActionKeyStroke = function(action) {
-  scout.FormToolButtonActionKeyStroke.parent.call(this, action);
-};
-scout.inherits(scout.FormToolButtonActionKeyStroke, scout.ActionKeyStroke);
-
-scout.FormToolButtonActionKeyStroke.prototype.handle = function(event) {
-  this.field.toggle(event);
-};
-
-scout.FormToolButtonActionKeyStroke.prototype._postRenderKeyBox = function($drawingArea) {
-  if (this.field.iconId) {
-    var wIcon = $drawingArea.find('.icon').width();
-    var wKeybox = $drawingArea.find('.key-box').outerWidth();
-    var containerPadding = Number($drawingArea.css('padding-left').replace('px', ''));
-    var leftKeyBox = wIcon / 2 - wKeybox / 2 + containerPadding;
-    $drawingArea.find('.key-box').css('left', leftKeyBox + 'px');
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.css
deleted file mode 100644
index b99f14f..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-.form-tool-popup > .popup-body > .form > .root-group-box > .main-menubar {
-  background-color: @form-tool-popup-main-menubar-background-color;
-}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.js
deleted file mode 100644
index c1ffa5c..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/FormToolPopup.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.FormToolPopup = function() {
-  scout.FormToolPopup.parent.call(this);
-};
-scout.inherits(scout.FormToolPopup, scout.PopupWithHead);
-
-scout.FormToolPopup.prototype._init = function(options) {
-  this.formToolButton = options.formToolButton;
-  options.initialFocus = this.formToolButton.form._initialFocusElement.bind(this.formToolButton.form);
-  scout.FormToolPopup.parent.prototype._init.call(this, options);
-
-  this.$formToolButton = this.formToolButton.$container;
-  this.$headBlueprint = this.$formToolButton;
-  this.form = this.formToolButton.form;
-  this.form.rootGroupBox.menuBar.bottom();
-};
-
-scout.FormToolPopup.prototype._createLayout = function() {
-  return new scout.FormToolPopupLayout(this);
-};
-
-scout.FormToolPopup.prototype._render = function($parent) {
-  scout.FormToolPopup.parent.prototype._render.call(this, $parent);
-  this.$container.addClass('form-tool-popup');
-
-  this.form.renderInitialFocusEnabled = false;
-  this.form.render(this.$body);
-  this.form.htmlComp.pixelBasedSizing = true;
-  this.form.setParent(this);
-};
-
-scout.FormToolPopup.prototype._renderHead = function() {
-  scout.FormToolPopup.parent.prototype._renderHead.call(this);
-  if (this.formToolButton._customCssClasses) {
-    this._copyCssClassToHead(this.formToolButton._customCssClasses);
-  }
-  if (this.formToolButton.cssClass) {
-    this._copyCssClassToHead(this.formToolButton.cssClass);
-  }
-  this._copyCssClassToHead('unfocusable');
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/DefaultFieldLoadingSupport.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/DefaultFieldLoadingSupport.js
index 0529ca5..16bb43d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/DefaultFieldLoadingSupport.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/DefaultFieldLoadingSupport.js
@@ -8,9 +8,25 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.DefaultFieldLoadingSupport = function(field, loadingIndicatorDelay) {
-  this.field = field;
-  this.loadingIndicatorDelay = scout.nvl(loadingIndicatorDelay, 250); // ms
+
+
+/**
+ * @param options The following properties are supported:
+ *  [field] mandatory
+ *  [containerProperty] optional, if not set: '$container' is used. This property points to the JQuery element that
+ *      should be hidden when the field is in loading state. We cannot reference the property in the Ctor of this
+ *      class, because the property is not set until the render() method runs.
+ *  [loadingIndicatorDelay] optional, if not set: 250 ms
+ */
+scout.DefaultFieldLoadingSupport = function(options) {
+  if (!options.field) {
+    throw new Error('Option \'field\' not set');
+  }
+  this.field = options.field;
+  this.$container = options.$container || function() {
+    return this.field.$container;
+  }.bind(this);
+  this.loadingIndicatorDelay = scout.nvl(options.loadingIndicatorDelay, 250); // ms
 
   this._loadingIndicatorTimeoutId;
 };
@@ -29,9 +45,9 @@
     var renderLoading = function() {
       if (this.field.rendered) {
         // Hide field content
-        this.field.$container.addClass('loading');
+        this.$container().addClass('loading');
         // Create loading indicator
-        this._$loadingIndicator = this.field.$container.appendDiv('loading-indicator');
+        this._$loadingIndicator = this.$container().appendDiv('loading-indicator');
       }
     }.bind(this);
 
@@ -49,7 +65,7 @@
       this._$loadingIndicator = null;
       if (this.field.rendered) {
         // Show field's content (layout if necessary)
-        this.field.$container.removeClass('loading');
+        this.$container().removeClass('loading');
         this.field.invalidateLayoutTree();
       }
     }.bind(this));
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.css
index 9261ad9..2f69474 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.css
@@ -96,28 +96,7 @@
     }
 
     & > .loading-indicator {
-      @loading-animation-size: 30px;
-      display: inline-block;
-      position: absolute;
-      top: 50%;
-      left: 50%;
-      margin-top: -(@loading-animation-size / 2);
-      margin-left: -(@loading-animation-size / 2);
-      #scout.animation(fadeIn 0.15s);
-
-      &::before {
-        #scout.animation(rotation 0.9s linear infinite);
-        content: '';
-        display: inline-block;
-        vertical-align: middle;
-        border-radius: 50%;
-        border: 2px solid rgba(0, 0, 0, 0);
-        border-top-color: @border-color;
-        border-left-color: @border-color;
-        border-bottom-color: @border-color;
-        width: @loading-animation-size;
-        height: @loading-animation-size;
-      }
+      #scout.loading-indicator();
     }
   }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
index 43f2a9b..01ceb6b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
@@ -35,9 +35,7 @@
   this._addAdapterProperties(['keyStrokes', 'menus']);
   this.refFieldId;
   this.mode = scout.FormField.MODE_DEFAULT;
-  this._keyStrokeSupport = new scout.KeyStrokeSupport(this);
   this.loadingSupport; // Object to handle the 'loading' property (different for tile fields)
-  this.statusPosition = scout.FormField.STATUS_POSITION_DEFAULT; // (currently?) an UI-only property
 
   /**
    * Set this property to true when the form-field should stay enabled in offline case.
@@ -106,16 +104,17 @@
   this._renderErrorStatus();
   this._renderMenus();
   this._renderLabel();
-  this._renderLabelVisible(this.labelVisible);
-  this._renderStatusVisible(this.statusVisible);
-  this._renderCssClass(this.cssClass);
-  this._renderFont(this.font);
-  this._renderForegroundColor(this.foregroundColor);
-  this._renderBackgroundColor(this.backgroundColor);
-  this._renderLabelFont(this.labelFont);
-  this._renderLabelForegroundColor(this.labelForegroundColor);
-  this._renderLabelBackgroundColor(this.labelBackgroundColor);
-  this._renderGridData(this.gridData);
+  this._renderLabelVisible();
+  this._renderStatusVisible();
+  this._renderStatusPosition();
+  this._renderCssClass();
+  this._renderFont();
+  this._renderForegroundColor();
+  this._renderBackgroundColor();
+  this._renderLabelFont();
+  this._renderLabelForegroundColor();
+  this._renderLabelBackgroundColor();
+  this._renderGridData();
   this._renderLoading();
 };
 
@@ -204,12 +203,14 @@
   }
 };
 
-scout.FormField.prototype._renderLabelVisible = function(visible) {
+scout.FormField.prototype._renderLabelVisible = function() {
+  var visible = this.labelVisible;
   this._renderChildVisible(this.$label, visible);
   this.$container.toggleClass('label-hidden', !visible);
 };
 
-scout.FormField.prototype._renderStatusVisible = function(statusVisible) {
+scout.FormField.prototype._renderStatusVisible = function() {
+  var statusVisible = this.statusVisible;
   this._renderChildVisible(this.$status, this._computeStatusVisible());
   // Pseudo status is only for layouting purpose, therefore tooltip, errorStatus etc. must not influence its visibility -> not necessary to use _computeStatusVisible
   this._renderChildVisible(this.$pseudoStatus, statusVisible);
@@ -220,6 +221,10 @@
   }
 };
 
+scout.FormField.prototype._renderStatusPosition = function() {
+  this.invalidateLayoutTree();
+};
+
 /**
  * Visibility of the status not only depends on this.statusVisible but on other attributes as well, computed by _computeStatusVisible.
  * Call this method if any of the conditions change to recompute the status visibility.
@@ -236,8 +241,8 @@
  */
 scout.FormField.prototype._computeStatusVisible = function() {
   var statusVisible = this.statusVisible,
-    hasStatus = !!(this.errorStatus),
-    hasTooltip = this.tooltipText;
+    hasStatus = !!this.errorStatus,
+    hasTooltip = !!this.tooltipText;
 
   return !this.suppressStatus && (statusVisible || hasStatus || hasTooltip || (this._hasMenus() && this.menusVisible));
 };
@@ -268,6 +273,7 @@
 };
 
 scout.FormField.prototype._renderCssClass = function(cssClass, oldCssClass) {
+  cssClass = cssClass || this.cssClass;
   this.$container.removeClass(oldCssClass);
   this.$container.addClass(cssClass);
 };
@@ -296,7 +302,7 @@
   scout.styles.legacyStyle(this, this.$label, 'label');
 };
 
-scout.FormField.prototype._renderGridData = function(gridData) {
+scout.FormField.prototype._renderGridData = function() {
   // NOP
 };
 
@@ -336,12 +342,14 @@
   this.$container.toggleClass('has-menus', this._hasMenus() && this.menusVisible);
 };
 
-scout.FormField.prototype._syncKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
-  this._keyStrokeSupport.syncKeyStrokes(newKeyStrokes, oldKeyStrokes);
+scout.FormField.prototype._syncKeyStrokes = function(keyStrokes, oldKeyStrokes) {
+  this.updateKeyStrokes(keyStrokes, oldKeyStrokes);
+  this.keyStrokes = keyStrokes;
 };
 
-scout.FormField.prototype._syncMenus = function(newMenus, oldMenus) {
-  this._keyStrokeSupport.syncMenus(newMenus, oldMenus);
+scout.FormField.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
 };
 
 scout.FormField.prototype._syncErrorStatus = function(errorStatus) {
@@ -387,12 +395,25 @@
   }
 };
 
+scout.FormField.prototype.focus = function() {
+  if (this.$field) {
+    this.session.focusManager.requestFocus(this.$field[0]);
+  } else {
+    var element =  this.session.focusManager.findFirstFocusableElement(this.$container);
+    this.session.focusManager.requestFocus(element);
+  }
+};
+
 scout.FormField.prototype._onStatusMousedown = function(event) {
+  // showing menus is more important than showing tooltips
   if (this.menusVisible && this._hasMenus()) {
     var func = function func(event) {
       var menus = this._getCurrentMenus();
-      // showing menus is more important than showing tooltips
-      if (!this.contextPopup || !this.contextPopup.rendered) {
+      // Toggle menu
+      if (this.contextPopup && this.contextPopup.rendered) {
+        this.contextPopup.close();
+        this.contextPopup = null;
+      } else {
         if (!menus.some(function(menuItem) {
             return menuItem.visible;
           })) {
@@ -400,11 +421,12 @@
         }
         this.contextPopup = scout.create('ContextMenuPopup', {
           parent: this,
+          $anchor: this.$status,
           menuItems: menus,
           cloneMenuItems: false,
-          $anchor: this.$status
+          closeOnAnchorMousedown: false
         });
-        this.contextPopup.open(undefined, event);
+        this.contextPopup.open();
       }
     }.bind(this);
 
@@ -581,6 +603,11 @@
   this.$mandatory = this.$container.appendSpan('mandatory-indicator');
 };
 
+scout.FormField.prototype.removeMandatoryIndicator = function() {
+  this.$mandatory.remove();
+  this.$mandatory = null;
+};
+
 /**
  * Adds a SPAN element with class 'icon' the the given optional $parent.
  * When $parent is not set, the element is added to this.$container.
@@ -662,10 +689,9 @@
 scout.FormField.prototype.prepareForCellEdit = function(opts) {
   opts = opts || {};
 
-  //remove mandatory and status indicators (popup should 'fill' the whole cell)
+  // remove mandatory and status indicators (popup should 'fill' the whole cell)
   if (this.$mandatory) {
-    this.$mandatory.remove();
-    this.$mandatory = null;
+    this.removeMandatoryIndicator();
   }
   if (this.$status) {
     this.$status.remove();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
index c0aa302..111836a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormFieldLayout.js
@@ -64,7 +64,8 @@
       scout.graphics.setBounds(formField.$label, top, left, labelWidth, this.rowHeight);
       left += labelWidth;
     } else if (formField.labelPosition === scout.FormField.LABEL_POSITION_TOP) {
-      top += formField.$label.outerHeight(true);
+      formField.$label.cssHeight(this.rowHeight);
+      top += this.rowHeight;
       labelHasFieldWidth = true;
     }
   }
@@ -82,7 +83,7 @@
     if (formField.statusPosition === scout.FormField.STATUS_POSITION_TOP && labelHasFieldWidth) {
       var statusHeight = scout.graphics.prefSize(formField.$status).height;
       // Vertically center status with label
-      var statusTop = containerPadding.top + (formField.$label.height() / 2) - (statusHeight / 2);
+      var statusTop = containerPadding.top + formField.$label.cssPaddingTop() + (formField.$label.height() / 2) - (statusHeight / 2);
       formField.$status
         .cssTop(statusTop)
         .cssRight(right + formField.$label.cssMarginRight())
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/ValueField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/ValueField.js
index da391a5..bd82a65 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/ValueField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/ValueField.js
@@ -19,11 +19,11 @@
 
 scout.ValueField.prototype._renderProperties = function() {
   scout.ValueField.parent.prototype._renderProperties.call(this);
-  this._renderDisplayText(this.displayText);
+  this._renderDisplayText();
 };
 
-scout.ValueField.prototype._renderDisplayText = function(displayText) {
-  this.$field.val(displayText);
+scout.ValueField.prototype._renderDisplayText = function() {
+  this.$field.val(this.displayText);
 };
 
 scout.ValueField.prototype._renderCurrentMenuTypes = function() {
@@ -104,6 +104,20 @@
   this.trigger('displayTextChanged', event);
 };
 
+/**
+ * Not used by acceptInput by purpose, because display text doesn't have to be rendered again.
+ * May be used to just modify the display text without validation
+ */
+scout.ValueField.prototype.setDisplayText = function(displayText) {
+  if (this.displayText === displayText) {
+    return;
+  }
+  this.displayText = displayText;
+  if (this.rendered) {
+    this._renderDisplayText();
+  }
+};
+
 scout.ValueField.prototype.addField = function($field) {
   scout.ValueField.parent.prototype.addField.call(this, $field);
   this.$field.data('valuefield', this);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/browserfield/BrowserField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/browserfield/BrowserField.js
index 86e2ff5..282d13e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/browserfield/BrowserField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/browserfield/BrowserField.js
@@ -11,7 +11,7 @@
 scout.BrowserField = function() {
   scout.BrowserField.parent.call(this);
   this._postMessageListener;
-  this.loadingSupport = new scout.DefaultFieldLoadingSupport(this);
+  this.loadingSupport = new scout.DefaultFieldLoadingSupport({field: this});
 };
 scout.inherits(scout.BrowserField, scout.ValueField);
 
@@ -36,7 +36,7 @@
 
 scout.BrowserField.prototype._renderIframeProperties = function() {
   this._renderLocation();
-  this._renderScrollBarsEnabled();
+  this._renderScrollBarEnabled();
   this._renderSandboxEnabled(); // includes _renderSandboxPermissions()
 };
 
@@ -45,13 +45,13 @@
   this.$field.attr('src', this.location);
 };
 
-scout.BrowserField.prototype._renderScrollBarsEnabled = function() {
-  this.$field.toggleClass('no-scrolling', !this.scrollBarsEnabled);
+scout.BrowserField.prototype._renderScrollBarEnabled = function() {
+  this.$field.toggleClass('no-scrolling', !this.scrollBarEnabled);
   // According to http://stackoverflow.com/a/18470016, setting 'overflow: hidden' via
   // CSS should be enough. However, if the inner page sets 'overflow' to another value,
   // scroll bars are shown again. Therefore, we add the legacy 'scrolling=no' attribute,
   // which is deprecated in HTML5, but seems to do the trick.
-  if (this.scrollBarsEnabled) {
+  if (this.scrollBarEnabled) {
     this.$field.removeAttr('scrolling');
   } else {
     this.$field.attr('scrolling', 'no');
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/Button.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/Button.js
index 9449d99..70171a9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/Button.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/Button.js
@@ -121,12 +121,18 @@
   this.$submenuIcon = null;
 };
 
+scout.Button.prototype._renderForegroundColor = function() {
+  scout.Button.parent.prototype._renderForegroundColor.call(this);
+  // Color button label as well, otherwise the color would not be visible because button label has already a color set using css
+  this.$buttonLabel.css('color', scout.styles.modelToCssColor(this.foregroundColor));
+};
+
 /**
  * @returns {Boolean}
  *          <code>true</code> if the action has been performed or <code>false</code> if it
  *          has not been performed (e.g. when the button is not enabled).
  */
-scout.Button.prototype.doAction = function(event) {
+scout.Button.prototype.doAction = function() {
   if (!this.enabled || !this.visible) {
     return false;
   }
@@ -134,33 +140,34 @@
   if (this.displayStyle === scout.Button.DisplayStyle.TOGGLE) {
     this.setSelected(!this.selected);
   } else if (this.menus.length > 0) {
-    this.togglePopup(event);
+    this.togglePopup();
   } else {
     this._send('clicked');
   }
   return true;
 };
 
-scout.Button.prototype.togglePopup = function(event) {
+scout.Button.prototype.togglePopup = function() {
   if (this.popup) {
     this.popup.close();
   } else {
-    this.popup = this._openPopup(event);
+    this.popup = this._openPopup();
     this.popup.on('remove', function(event) {
       this.popup = null;
     }.bind(this));
   }
 };
 
-scout.Button.prototype._openPopup = function(event) {
+scout.Button.prototype._openPopup = function() {
   // FIXME bsh: Improve this
   var popup = scout.create('ContextMenuPopup', {
     parent: this,
     menuItems: this.menus,
     cloneMenuItems: false,
+    closeOnAnchorMousedown: false,
     $anchor: this.$field
   });
-  popup.open(null, event);
+  popup.open();
   return popup;
 };
 scout.Button.prototype._doActionTogglesSubMenu = function() {
@@ -254,7 +261,7 @@
   function updateButtonLayoutAfterImageLoaded(success) {
     $icon.removeClass('loading');
     $icon.toggleClass('broken', !success);
-    this.htmlComp.revalidateLayoutTree();
+    this.htmlComp.invalidateLayoutTree();
   }
 };
 
@@ -265,6 +272,6 @@
 
 scout.Button.prototype._onClick = function(event) {
   if (this.enabled) {
-    this.doAction(event);
+    this.doAction();
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/ButtonKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/ButtonKeyStroke.js
index 81270ae..41a7dc8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/ButtonKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/button/ButtonKeyStroke.js
@@ -34,5 +34,5 @@
  * @override KeyStroke.js
  */
 scout.ButtonKeyStroke.prototype.handle = function(event) {
-  this.field.doAction(event);
+  this.field.doAction();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.css
index 497885a..ecf5d1f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.css
@@ -11,7 +11,7 @@
 @check-box-size: 18px;
 
 .check-box-field > .field {
-  padding: @borderless-field-padding-y 0px @borderless-field-padding-y 25px;
+  padding: @borderless-field-padding-y 0px @borderless-field-padding-y @check-box-size;
   outline: none;
 
   & > .check-box,
@@ -26,7 +26,11 @@
   }
 
   & > .label {
+    padding-left: 7px;
     #scout.overflow-ellipsis-nowrap();
+    /* only the label should be clickable, not the whole field */
+    display: inline-block;
+    max-width: 100%;
   }
 
   &.disabled > .label {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.js
index 5df1cce..a121148 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/checkbox/CheckBoxField.js
@@ -52,11 +52,11 @@
 };
 
 scout.CheckBoxField.prototype.acceptInput = function(whileTyping, forceSend) {
-  //nop;
+  //nop
 };
 
-scout.CheckBoxField.prototype._renderDisplayText = function(displayText) {
-  //nop;
+scout.CheckBoxField.prototype._renderDisplayText = function() {
+  //nop
 };
 
 scout.CheckBoxField.prototype._onMouseDown = function(event) {
@@ -111,9 +111,9 @@
  * @override
  */
 scout.CheckBoxField.prototype._renderLabel = function() {
-  if (this.$checkBoxLabel) {
-    this.$checkBoxLabel.textOrNbsp(scout.strings.removeAmpersand(this.label), 'empty');
-  }
+  this.$checkBoxLabel.textOrNbsp(scout.strings.removeAmpersand(this.label), 'empty');
+  // Make sure the empty label is as height as the other labels, especially important for top labels
+  this.$label.html('&nbsp;');
 };
 
 scout.CheckBoxField.prototype._renderGridData = function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/clipboardfield/ClipboardField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/clipboardfield/ClipboardField.js
index d5e3b9c..41c81e3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/clipboardfield/ClipboardField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/clipboardfield/ClipboardField.js
@@ -70,7 +70,8 @@
   });
 };
 
-scout.ClipboardField.prototype._renderDisplayText = function(displayText) {
+scout.ClipboardField.prototype._renderDisplayText = function() {
+  var displayText = this.displayText;
   if (scout.strings.hasText(displayText)) {
     this.$field.html(scout.strings.nl2br(displayText, true));
     scout.scrollbars.install(this.$field, {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/datefield/DateField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/datefield/DateField.js
index ec78a5c..3a1e705 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/datefield/DateField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/datefield/DateField.js
@@ -31,8 +31,10 @@
   this._modelErrorStatus = null;
 
   this._popup;
-  this._datePickerDateSelectedHandler;
+  this._datePickerDateSelectHandler;
   this._popupCloseHandler;
+  this.oldDisplayText = '';
+  this.timestamp = null;
 };
 scout.inherits(scout.DateField, scout.ValueField);
 
@@ -47,6 +49,12 @@
   scout.DateField.parent.prototype._init.call(this, model);
   scout.fields.initTouch(this, model);
   this._popup = model.popup;
+  this._syncDateFormatPattern(this.dateFormatPattern);
+  this._syncTimeFormatPattern(this.timeFormatPattern);
+  this._syncTimestamp(this.timestamp);
+  this._syncAutoTimestamp(this.autoTimestamp);
+  this._syncDisplayText(this.displayText);
+  this._syncAllowedDates(this.allowedDates);
 };
 
 scout.DateField.prototype.addPopup = function() {
@@ -55,14 +63,26 @@
     this._popup = scout.create(popupType, {
       parent: this,
       $anchor: this.$field,
-      field: this
+      boundToAnchor: !this.touch,
+      closeOnAnchorMousedown: false,
+      field: this,
+      allowedDates: this.allowedDates
     });
   }
 };
 
 scout.DateField.prototype._syncErrorStatus = function(errorStatus) {
+  var invalidTime, invalidDate;
+  if (this.errorStatus) {
+    invalidTime = this.errorStatus.invalidTime;
+    invalidDate = this.errorStatus.invalidDate;
+  }
   scout.DateField.parent.prototype._syncErrorStatus.call(this, errorStatus);
   this._modelErrorStatus = this.errorStatus;
+  if (this.errorStatus) {
+    this.errorStatus.invalidTime = invalidTime;
+    this.errorStatus.invalidDate = invalidDate;
+  }
 };
 
 scout.DateField.prototype._render = function($parent) {
@@ -99,7 +119,9 @@
   this.$timeFieldIcon = null;
   this._$predictDateField = null;
   this._$predictTimeField = null;
-  if (this._popup) {
+  // popup may not be reused because $anchor would point to a removed field
+  // Don't set to null in case of embedded mode to make sure not another popup gets created by the field itself when touch popup get rendered!
+  if (this._popup && !this.embedded) {
     this._popup = null;
   }
 };
@@ -169,7 +191,7 @@
  */
 scout.DateField.prototype._renderPlaceholder = function() {
   scout.DateField.parent.prototype._renderPlaceholder.call(this,
-      this._fieldForPlaceholder());
+    this._fieldForPlaceholder());
 };
 
 /**
@@ -177,7 +199,7 @@
  */
 scout.DateField.prototype._removePlaceholder = function() {
   scout.DateField.parent.prototype._removePlaceholder.call(this,
-      this._fieldForPlaceholder());
+    this._fieldForPlaceholder());
 };
 
 scout.DateField.prototype._fieldForPlaceholder = function() {
@@ -189,19 +211,22 @@
   return null;
 };
 
-scout.DateField.prototype._renderDateFormatPattern = function() {
+scout.DateField.prototype._syncDateFormatPattern = function(dateFormatPattern) {
+  this.dateFormatPattern = dateFormatPattern;
   this.isolatedDateFormat = new scout.DateFormat(this.session.locale, this.dateFormatPattern);
+};
+
+scout.DateField.prototype._renderDateFormatPattern = function() {
   this.getDatePicker().dateFormat = this.isolatedDateFormat;
-  if (this.rendered) {
-    this._renderTimestamp();
-  }
+};
+
+scout.DateField.prototype._syncTimeFormatPattern = function(timeFormatPattern) {
+  this.timeFormatPattern = timeFormatPattern;
+  this.isolatedTimeFormat = new scout.DateFormat(this.session.locale, this.timeFormatPattern);
 };
 
 scout.DateField.prototype._renderTimeFormatPattern = function() {
-  this.isolatedTimeFormat = new scout.DateFormat(this.session.locale, this.timeFormatPattern);
-  if (this.rendered) {
-    this._renderTimestamp();
-  }
+  // nop
 };
 
 /**
@@ -219,19 +244,74 @@
 };
 
 /**
- * @override
+ * @override ValueField.js
  */
 scout.DateField.prototype._renderDisplayText = function() {
-  //nop -> handled in _renderTimestamp
+  if (this.hasDate) {
+    this._renderDateDisplayText();
+  }
+  if (this.hasTime) {
+    this._renderTimeDisplayText();
+  }
+  this._removePredictionFields();
+};
+
+scout.DateField.prototype._renderDateDisplayText = function() {
+  scout.fields.valOrText(this, this.$dateField, this.dateDisplayText);
+};
+
+scout.DateField.prototype._renderTimeDisplayText = function() {
+  scout.fields.valOrText(this, this.$timeField, this.timeDisplayText);
+};
+
+scout.DateField.prototype._syncDisplayText = function(displayText) {
+  var dateText = '',
+    timeText = '',
+    parts;
+
+  this.oldDisplayText = this.displayText;
+  this.displayText = displayText;
+
+  if (scout.strings.hasText(this.displayText)) {
+    parts = this.displayText.split('\n');
+    dateText = parts[0];
+    timeText = parts[1];
+  }
+  this.dateDisplayText = dateText;
+  this.timeDisplayText = timeText;
+};
+
+scout.DateField.prototype._syncTimestamp = function(timestamp) {
+  // TODO CGU [6.1] no need to keep two timestamp properties, only hold date based type. Convert to back to string when sending. Also rename to value instead of timestamp
+  this.timestampAsDate = scout.dates.parseJsonDate(timestamp);
+};
+
+scout.DateField.prototype._syncAutoTimestamp = function(autoTimestamp) {
+  this.autoTimestampAsDate = scout.dates.parseJsonDate(autoTimestamp);
+};
+
+scout.DateField.prototype._syncAllowedDates = function(allowedDates) {
+  if (Array.isArray(allowedDates)) {
+    var convAllowedDates = [];
+    allowedDates.forEach(function(dateString) {
+      convAllowedDates.push(scout.dates.parseJsonDate(dateString));
+    });
+    this.allowedDates = convAllowedDates;
+  } else {
+    this.allowedDates = null;
+  }
 };
 
 scout.DateField.prototype._renderTimestamp = function() {
-  this.timestampAsDate = scout.dates.parseJsonDate(this.timestamp);
-  this.renderDate(this.timestampAsDate);
+  // nop
 };
 
 scout.DateField.prototype._renderAutoTimestamp = function() {
-  this.autoTimestampAsDate = scout.dates.parseJsonDate(this.autoTimestamp);
+  // nop
+};
+
+scout.DateField.prototype._renderAllowedDates = function() {
+  this.getDatePicker().allowedDates = this.allowedDates;
 };
 
 /**
@@ -253,11 +333,6 @@
       this._$predictDateField.removeClass(scout.Status.cssClasses);
       this._$predictDateField.toggleClass(statusClass, hasStatus);
     }
-    // Put invalid input in the field, if the current input differs
-    // (don't do it always, this would alter the cursor position)
-    if (!this._isDateValid() && this.$dateField.val() !== this.errorStatus.invalidDateText) {
-      this._setDateDisplayText(this.errorStatus.invalidDateText);
-    }
   }
 
   // Do the same for the time field
@@ -268,9 +343,6 @@
       this._$predictTimeField.removeClass(scout.Status.cssClasses);
       this._$predictTimeField.toggleClass(statusClass, hasStatus);
     }
-    if (!this._isTimeValid() && this.$timeField.val() !== this.errorStatus.invalidTimeText) {
-      this._setTimeDisplayText(this.errorStatus.invalidTimeText);
-    }
   }
 
   if (this.hasDate && this._popup.isOpen()) {
@@ -535,14 +607,12 @@
   }
 
   if (event.which === scout.keys.ENTER) {
-    if (this._$predictTimeField) {
+    // Timefield is shown in touch popup, so we need to make sure time gets accepted and popup closed, even if the regular time field itself has no popup
+    if (this._popup.isOpen() || this._$predictDateField) {
       // Accept the current prediction (if available)
       this._tempTimeDate = null;
       this._acceptDateTimePrediction(false, true); // accept time part
-      // in embedded mode, we want to close the whole popup when user presses enter and time field is focused
-      if (this.embedded) {
-        this._closeDatePicker();
-      }
+      this._closeDatePicker();
       $.suppressEvent(event);
     }
     return;
@@ -624,12 +694,12 @@
   }
 };
 
-scout.DateField.prototype._onDatePickerDateSelected = function(event) {
+scout.DateField.prototype._onDatePickerDateSelect = function(event) {
   this._setDateValid(true);
   this._setTimeValid(true);
   this.renderDate(event.date);
   if (!event.shifting) {
-    // close popup and write to model
+    this._sendDisplayTextIfChanged();
     this.updateTimestamp(this._newTimestampAsDate(event.date, this.timestampAsDate));
     // closeDatePicker is set to false when date-field is in touch-mode
     // since popup will be closed by the embedded date-field
@@ -663,7 +733,7 @@
 
 /**
  * Formats the given date (or this.timestampAsDate) using the specified formats and writes
- * the resulting string to the $dateField and $timeField, respectively. Prediction field
+ * the resulting string to the $dateField and $timeField, respectively. Prediction fields
  * are removed.
  */
 scout.DateField.prototype.renderDate = function(date) {
@@ -689,22 +759,26 @@
 };
 
 scout.DateField.prototype._setDateDisplayText = function(displayText) {
-  scout.fields.valOrText(this, this.$dateField, displayText);
+  this.dateDisplayText = displayText;
   this._updateDisplayTextProperty();
+  if (this.rendered) {
+    this._renderDateDisplayText();
+  }
 };
 
 scout.DateField.prototype._setTimeDisplayText = function(displayText) {
-  scout.fields.valOrText(this, this.$timeField, displayText);
+  this.timeDisplayText = displayText;
   this._updateDisplayTextProperty();
+  if (this.rendered) {
+    this._renderTimeDisplayText();
+  }
 };
 
-/**
- * Note: this.displayText is only used in the UI (BasicField.js) and is not synchronized with the server.
- */
 scout.DateField.prototype._updateDisplayTextProperty = function() {
-  var dateText = this.$dateField ? this.$dateField.val() : '',
-    timeText = this.$timeField ? this.$timeField.val() : '';
-  this.displayText = scout.strings.join(' ', dateText, timeText);
+  var dateText = this.dateDisplayText || '',
+    timeText = this.timeDisplayText || '';
+
+  this.displayText = scout.strings.join('\n', dateText, timeText);
 };
 
 /**
@@ -744,13 +818,6 @@
 };
 
 /**
- * @Override BasicField.js
- */
-scout.DateField.prototype._onDisplayTextModified = function() {
-  // TODO [5.2] bsh: What to do? Maybe change on server that this method is never called.
-};
-
-/**
  * Returns null if both arguments are not set. Otherwise, this.timestampAsDate or the current date
  * is used as basis and the given arguments are applied to that date. The result is returned.
  */
@@ -776,7 +843,33 @@
  * - the current date/time
  */
 scout.DateField.prototype._referenceDate = function() {
-  return this.autoTimestampAsDate || scout.dates.trunc(new Date());
+  var referenceDate = this.autoTimestampAsDate || scout.dates.trunc(new Date());
+  if (this.allowedDates) {
+    referenceDate = this._findAllowedReferenceDate(referenceDate);
+  }
+  return referenceDate;
+};
+
+/**
+ * Find nearest allowed date which is equals or greater than the current referenceDate.
+ */
+scout.DateField.prototype._findAllowedReferenceDate = function(referenceDate) {
+  var i, allowedDate;
+  // 1st: try to find a date which is equals or greater than the referenceDate (today)
+  for (i = 0; i < this.allowedDates.length; i++) {
+    allowedDate = this.allowedDates[i];
+    if (scout.dates.compare(allowedDate, referenceDate) >= 0) {
+      return allowedDate;
+    }
+  }
+  // 2nd: try to find an allowed date in the past
+  for (i = this.allowedDates.length - 1; i >= 0; i--) {
+    allowedDate = this.allowedDates[i];
+    if (scout.dates.compare(allowedDate, referenceDate) <= 0) {
+      return allowedDate;
+    }
+  }
+  return referenceDate;
 };
 
 scout.DateField.prototype.updateTimestamp = function(timestampAsDate, syncToServer) {
@@ -784,26 +877,28 @@
   if (timestamp !== this.timestamp || this.errorStatus) {
     this.timestamp = timestamp;
     this.timestampAsDate = timestampAsDate;
-    if (scout.nvl(syncToServer, true)) {
-      this._syncToServer();
+
+    if (!this._hasUiErrorStatus()) {
+      this.trigger('timestampChanged', {
+        timestamp: this.timestamp
+      });
+      if (scout.nvl(syncToServer, true)) {
+        this._send('timestampChanged', {
+          timestamp: this.timestamp
+        });
+      }
     }
   }
 };
 
-scout.DateField.prototype._syncToServer = function() {
-  if (this._hasUiErrorStatus()) {
-    this._send('parsingError', {
-      invalidDisplayText: this.errorStatus.invalidDisplayText,
-      invalidDateText: this.errorStatus.invalidDateText,
-      invalidTimeText: this.errorStatus.invalidTimeText
-    });
-  } else {
-    var event = {
-      timestamp: this.timestamp
-    };
-    this._send('timestampChanged', event);
-    // FIXME AWE: (filter) improv. trigger/send in date-field , sendAndTrigger method
-    this.trigger('timestampChanged', event);
+scout.DateField.prototype._sendParsingError = function() {
+  this._send('parsingError');
+};
+
+scout.DateField.prototype._sendDisplayTextIfChanged = function() {
+  if (this.oldDisplayText !== this.displayText) {
+    this._sendDisplayTextChanged(this.displayText);
+    this.oldDisplayText = this.displayText;
   }
 };
 
@@ -824,15 +919,8 @@
   // Add popup close handler
   if (!this._popupCloseHandler) {
     this._popupCloseHandler = function() {
-      if (this.touch) {
-        this._onDatePickerDateSelected({
-          date: this._popup._field.timestampAsDate,
-          closeDatePicker: false
-        });
-      } else {
-        this.getDatePicker().off('dateSelect', this._datePickerDateSelectedHandler);
-        this._datePickerDateSelectedHandler = null;
-      }
+      this.getDatePicker().off('dateSelect', this._datePickerDateSelectHandler);
+      this._datePickerDateSelectHandler = null;
       this._popup.off('close', this._popupCloseHandler);
       this._popupCloseHandler = null;
     }.bind(this);
@@ -840,18 +928,13 @@
   }
 
   // Add date-picker dateSelect handler
-  // In touch mode only the date-field in the popup (=embedded) should register a listener
-  // but not the 'touch' date-field. The touch-field is updated when the popup is closed.
-  // In desktop-mode the date-field must register the listener.
-  if (!this.touch) {
-    this._attachDatePickerDateSelectedHandler();
-  }
+  this._attachDatePickerDateSelectHandler();
 };
 
-scout.DateField.prototype._attachDatePickerDateSelectedHandler = function() {
-  if (!this._datePickerDateSelectedHandler) {
-    this._datePickerDateSelectedHandler = this._onDatePickerDateSelected.bind(this);
-    this.getDatePicker().on('dateSelect', this._datePickerDateSelectedHandler);
+scout.DateField.prototype._attachDatePickerDateSelectHandler = function() {
+  if (!this._datePickerDateSelectHandler) {
+    this._datePickerDateSelectHandler = this._onDatePickerDateSelect.bind(this);
+    this.getDatePicker().on('dateSelect', this._datePickerDateSelectHandler);
   }
 };
 
@@ -862,7 +945,9 @@
 };
 
 scout.DateField.prototype._acceptDateTimePrediction = function(acceptDate, acceptTime) {
-  var dateText, timeText, datePrediction, timePrediction;
+  var datePrediction, timePrediction,
+    dateText = '',
+    timeText = '';
 
   var success = true;
   if (acceptDate) {
@@ -871,6 +956,7 @@
     if (!datePrediction) {
       success = false;
     }
+    this._setDateDisplayText(dateText);
   }
   if (acceptTime) {
     timeText = (this._$predictTimeField ? this._$predictTimeField.val() : this.$timeField.val());
@@ -878,9 +964,13 @@
     if (!timePrediction) {
       success = false;
     }
+    this._setTimeDisplayText(timeText);
   }
   this._removePredictionFields();
 
+  // Send display text before timestamp, otherwise server would create a display text by its own and send it back
+  this._sendDisplayTextIfChanged();
+
   if (success) {
     // parse success -> send new timestamp to server
     var newTimestamp = null;
@@ -892,7 +982,7 @@
     this.renderDate(this.timestampAsDate);
   } else {
     // parse error -> send error to server
-    this._syncToServer();
+    this._sendParsingError();
   }
 };
 
@@ -908,7 +998,7 @@
     var now = new Date();
     var daysToAdd = Number(m[1] + (m[2] || '0'));
     now.setDate(now.getDate() + daysToAdd);
-    this._setDateValid(true, inputText);
+    this._setDateValid(true);
     return {
       date: now,
       text: inputText
@@ -917,13 +1007,13 @@
 
   var analyzeInfo = this.isolatedDateFormat.analyze(inputText, this._referenceDate());
   if (analyzeInfo.error) {
-    this._setDateValid(false, inputText);
+    this._setDateValid(false);
     return null;
   }
 
   // No predicted date? -> return empty string (may happen if inputText is empty)
   if (!analyzeInfo.predictedDate) {
-    this._setDateValid(true, '');
+    this._setDateValid(true);
     return {
       date: null,
       text: ''
@@ -941,7 +1031,7 @@
     predictedDateFormatted = inputText + m[1];
   }
 
-  this._setDateValid(true, predictedDateFormatted);
+  this._setDateValid(true);
   return {
     date: predictedDate,
     text: predictedDateFormatted
@@ -956,13 +1046,13 @@
 
   var analyzeInfo = this.isolatedTimeFormat.analyze(inputText, this._referenceDate());
   if (analyzeInfo.error) {
-    this._setTimeValid(false, inputText);
+    this._setTimeValid(false);
     return null;
   }
 
   // No predicted date? -> return empty string (may happen if inputText is empty)
   if (!analyzeInfo.predictedDate) {
-    this._setTimeValid(true, '');
+    this._setTimeValid(true);
     return {
       date: null,
       text: ''
@@ -980,24 +1070,22 @@
     predictedTimeFormatted = inputText + m[1];
   }
 
-  this._setTimeValid(true, predictedTimeFormatted);
+  this._setTimeValid(true);
   return {
     date: predictedDate,
     text: predictedTimeFormatted
   };
 };
 
-scout.DateField.prototype._setDateValid = function(valid, dateText) {
+scout.DateField.prototype._errorStatus = function(valid) {
   var errorStatus = this.errorStatus;
   if (valid) {
     // Set to valid
     if (errorStatus) {
-      errorStatus.invalidDateText = null;
       // If no other UI error remains, revert to errorStatus from model
       if (!this._hasUiErrorStatus()) {
         errorStatus = this._modelErrorStatus;
       }
-      this.setErrorStatus(errorStatus);
     }
   } else {
     // Set to invalid (this is always a UI error)
@@ -1007,65 +1095,50 @@
         severity: scout.Status.Severity.ERROR
       });
     }
-    errorStatus.invalidDateText = dateText;
-    errorStatus.invalidDisplayText = scout.strings.join(' ',
-      dateText,
-      this.$timeField && this.$timeField.val());
-    this.setErrorStatus(errorStatus);
   }
-  this.setErrorStatus(errorStatus);
-  // The layout might have been invalidated by setErrorStatus() when showing/hiding the status icon
-  // automatically. Because this is a UI only operation, we have to trigger validation manually.
-  this.validateLayout();
+  return errorStatus;
 };
 
-scout.DateField.prototype._setTimeValid = function(valid, timeText) {
-  var errorStatus = this.errorStatus;
-  if (valid) {
-    // Set to valid
-    if (errorStatus) {
-      errorStatus.invalidTimeText = null;
-      // If no other UI error remains, revert to errorStatus from model
-      if (!this._hasUiErrorStatus()) {
-        errorStatus = this._modelErrorStatus;
-      }
-      this.setErrorStatus(errorStatus);
+/**
+ * This method updates the UI parts (date, time) of the error status. When both UI parts are valid,
+ * we use the error status from the model, which can be null (= no errors).
+ */
+scout.DateField.prototype._setErrorStatusPart = function(property, valid) {
+  var errorStatus = this._errorStatus(valid);
+  if (errorStatus) {
+    errorStatus[property] = !valid;
+    if (!errorStatus.invalidDate && !errorStatus.invalidTime) {
+      errorStatus = this._modelErrorStatus;
     }
-  } else {
-    // Set to invalid (this is always a UI error)
-    if (!this._hasUiErrorStatus()) {
-      errorStatus = new scout.Status({
-        message: this.session.text('ui.InvalidDateFormat'),
-        severity: scout.Status.Severity.ERROR
-      });
-    }
-    errorStatus.invalidTimeText = timeText;
-    errorStatus.invalidDisplayText = scout.strings.join(' ',
-      this.$dateField && this.$dateField.val(),
-      timeText);
-    this.setErrorStatus(errorStatus);
   }
-  // The layout might have been invalidated by setErrorStatus() when showing/hiding the status icon
-  // automatically. Because this is a UI only operation, we have to trigger validation manually.
-  this.validateLayout();
+  this.setErrorStatus(errorStatus);
+};
+
+scout.DateField.prototype._setDateValid = function(valid) {
+  this._setErrorStatusPart('invalidDate', valid);
+};
+
+scout.DateField.prototype._setTimeValid = function(valid) {
+  this._setErrorStatusPart('invalidTime', valid);
+};
+
+scout.DateField.prototype._isErrorStatusPartValid = function(property) {
+  if (this.errorStatus && this.errorStatus[property]) {
+    return false;
+  }
+  return true;
 };
 
 scout.DateField.prototype._isDateValid = function() {
-  if (this.errorStatus && this.errorStatus.invalidDateText) {
-    return false;
-  }
-  return true;
+  return this._isErrorStatusPartValid('invalidDate');
 };
 
 scout.DateField.prototype._isTimeValid = function() {
-  if (this.errorStatus && this.errorStatus.invalidTimeText) {
-    return false;
-  }
-  return true;
+  return this._isErrorStatusPartValid('invalidTime');
 };
 
 scout.DateField.prototype._hasUiErrorStatus = function() {
-  return !!(this.errorStatus && (this.errorStatus.invalidDateText || this.errorStatus.invalidTimeText));
+  return !!(this.errorStatus && (this.errorStatus.invalidDate || this.errorStatus.invalidTime));
 };
 
 /**
@@ -1121,3 +1194,38 @@
   this._popup.ensureOpen();
   this.getDatePicker().shiftSelectedDate(years, months, days);
 };
+
+
+// TODO awe, cgu: (value-field): we should refactor this setTimestamp / formatTimestamp
+// as soon as we have implemented parse/format/validation logic on ValueField.js. This
+// should work like the Java client (AbstractValueField) does.
+scout.DateField.prototype.setTimestamp = function(timestamp) {
+  if (this.timestamp === timestamp) {
+    return;
+  }
+  this._setProperty('timestamp', timestamp);
+  this.timestampAsDate = scout.dates.parseJsonDate(timestamp);
+  this.formatTimestamp(this.timestampAsDate);
+  if (this.rendered) {
+    this._renderDisplayText();
+  }
+};
+
+scout.DateField.prototype.formatTimestamp = function(timestamp) {
+  var
+    dateText = '',
+    timeText = '';
+
+  if (timestamp) {
+    if (this.hasDate) {
+      dateText = this.isolatedDateFormat.format(timestamp);
+    }
+    if (this.hasTime) {
+      timeText = this.isolatedTimeFormat.format(timestamp);
+    }
+  }
+
+  this.dateDisplayText = dateText;
+  this.timeDisplayText = timeText;
+  this._updateDisplayTextProperty();
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.css
index 1a60893..0621323 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.css
@@ -49,7 +49,6 @@
   margin-top: @group-margin-top;
   margin-left: @mandatory-indicator-width;
   border-bottom: 3px solid @group-box-title-border-color;
-  padding: @group-title-padding-y 0;
   #scout.overflow-ellipsis-nowrap();
 
   .group-box.collapsed:not(.with-line) > & {
@@ -96,9 +95,37 @@
     }
   }
 
-  & > span {
+  & > .label {
     #scout.font-text-normal(@font-weight-bold);
+    display: inline-block;
+    vertical-align: middle;
     color: @title-color;
+    padding: @group-title-padding-y 0;
+    #scout.overflow-ellipsis();
+  }
+
+  & > .status {
+    margin-left: @field-status-margin-left;
+    padding: 4px 0;
+    display: inline-block;
+    vertical-align: middle;
+    #scout.status();
+  }
+
+  .group-box.has-tooltip > & > .status {
+    #scout.tooltip-status();
+  }
+
+  .group-box.has-info > & > .status {
+    #scout.info-status();
+  }
+
+  .group-box.has-warning > & > .status {
+    #scout.warning-status();
+  }
+
+  .group-box.has-error > & > .status {
+    #scout.error-status();
   }
 
   &.expandable {
@@ -107,7 +134,7 @@
   }
 
   /* Move title span to right when control is rendered */
-  & > .group-box-control ~ span {
+  & > .group-box-control ~ .label {
     padding-left: @group-box-control-size + 5px;
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.js
index 229a6a9..a11f0b8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBox.js
@@ -12,20 +12,23 @@
   scout.GroupBox.parent.call(this);
   this.fields = [];
   this.menus = [];
+  this.menuBarVisible = true;
   this.staticMenus = [];
   this._addAdapterProperties(['fields', 'menus']);
   this.$body;
-  this._$groupBoxTitle;
+  this.$title;
 
   this.controls = [];
   this.systemButtons = [];
   this.customButtons = [];
   this.processButtons = [];
+  this.processMenus = [];
 };
 scout.inherits(scout.GroupBox, scout.CompositeField);
 
 scout.GroupBox.prototype._init = function(model) {
   scout.GroupBox.parent.prototype._init.call(this, model);
+  this._prepareFields();
   this.menuBar = scout.create('MenuBar', {
     parent: this,
     menuOrder: new scout.GroupBoxMenuItemsOrder()
@@ -33,6 +36,7 @@
   if (this.mainBox) {
     this.menuBar.large();
   }
+  this._updateMenuBar();
 };
 
 /**
@@ -45,6 +49,35 @@
 };
 
 /**
+ * @override FormField.js
+ */
+scout.GroupBox.prototype._syncKeyStrokes = function(keyStrokes, oldKeyStrokes) {
+  keyStrokes = scout.arrays.ensure(keyStrokes);
+
+  var groupBoxRenderingHints = {
+    render: function() {
+      return true;
+    },
+    offset: 0,
+    hAlign: scout.hAlign.RIGHT,
+    $drawingArea: function($drawingArea, event) {
+      if (this.labelVisible) {
+        return this.$title;
+      } else {
+        return this.$body;
+      }
+    }.bind(this)
+  };
+
+  keyStrokes
+    .forEach(function(keyStroke) {
+      keyStroke.actionKeyStroke.renderingHints = $.extend({}, keyStroke.actionKeyStroke.renderingHints, groupBoxRenderingHints);
+    }, this);
+
+  scout.GroupBox.parent.prototype._syncKeyStrokes.call(this, keyStrokes, oldKeyStrokes);
+};
+
+/**
  * Returns a $container used as a bind target for the key-stroke context of the group-box.
  * By default this function returns the container of the form, or when group-box is has no
  * form as a parent the container of the group-box.
@@ -59,7 +92,7 @@
 };
 
 scout.GroupBox.prototype._render = function($parent) {
-  var htmlBody, i,
+  var htmlBody,
     env = scout.HtmlEnvironment;
 
   this.addContainer($parent, this.mainBox ? 'root-group-box' : 'group-box', this._createLayout());
@@ -67,14 +100,9 @@
     this.htmlComp.layoutData = null;
   }
 
-  this._$groupBoxTitle = this.$container.appendDiv('group-box-title');
+  this.$title = this.$container.appendDiv('group-box-title');
   this.addLabel();
   this.addStatus();
-  if (this.menuBar.position === 'top') {
-    this.menuBar.render(this.$container);
-    // move after title
-    this.menuBar.$container.appendTo(this.$container);
-  }
   this.$body = this.$container.appendDiv('group-box-body');
   htmlBody = new scout.HtmlComponent(this.$body, this.session);
   htmlBody.setLayout(new scout.LogicalGridLayout(env.formColumnGap, env.formRowGap));
@@ -84,26 +112,26 @@
       axis: 'y'
     });
   }
-  this._prepareFields();
+
   this.controls.forEach(function(control) {
     control.render(this.$body);
   }, this);
-  // FIXME awe: andere lösung finden für das hier
-  // only render when 2nd argument is undefined or matches this.position
-  //  if (whenPosition !== undefined && this.position !== whenPosition) {
-  //    return;
-  //  }
-  if (this.menuBar.position === 'bottom') {
-    this.menuBar.render(this.$container);
+};
+
+scout.GroupBox.prototype._remove = function() {
+  scout.GroupBox.parent.prototype._remove.call(this);
+  if (this.scrollable) {
+    scout.scrollbars.uninstall(this.$body);
   }
 };
 
 scout.GroupBox.prototype._renderProperties = function() {
   scout.GroupBox.parent.prototype._renderProperties.call(this);
 
-  this._renderBorderVisible(this.borderVisible);
-  this._renderExpandable(this.expandable);
-  this._renderExpanded(this.expanded);
+  this._renderBorderVisible();
+  this._renderExpandable();
+  this._renderExpanded();
+  this._renderMenuBarVisible();
 };
 
 scout.GroupBox.prototype._createLayout = function() {
@@ -114,30 +142,33 @@
   if (this.$label) {
     return;
   }
-  this.$label = this._$groupBoxTitle.appendSpan();
+  this.$label = this.$title.appendSpan('label');
 };
 
 scout.GroupBox.prototype._renderLabel = function() {
   this.$label.textOrNbsp(this.label);
 };
 
-scout.GroupBox.prototype._remove = function() {
-  scout.GroupBox.parent.prototype._remove.call(this);
-  if (this.menuBar) {
-    this.menuBar.remove();
+scout.GroupBox.prototype._renderStatusPosition = function() {
+  if (this.statusPosition === scout.FormField.STATUS_POSITION_TOP) {
+    // move into title
+    this.$status.appendTo(this.$title);
+  } else {
+    this.$status.appendTo(this.$container);
   }
-  if (this.scrollable) {
-    scout.scrollbars.uninstall(this.$body);
-  }
+  this.invalidateLayoutTree();
 };
 
 scout.GroupBox.prototype._prepareFields = function() {
+  this.unregisterKeyStrokes(this.processButtons);
+
   this.controls = [];
   this.systemButtons = [];
   this.customButtons = [];
   this.processButtons = [];
+  this.processMenus = [];
 
-  var i, field, res;
+  var i, field;
   for (i = 0; i < this.fields.length; i++) {
     field = this.fields[i];
     if (field instanceof scout.Button) {
@@ -164,6 +195,17 @@
       this.controls.push(field);
     }
   }
+
+  // Create menu for each process button
+  this.processButtons.forEach(function(button) {
+    var menu = scout.create('ButtonAdapterMenu',
+      scout.ButtonAdapterMenu.adaptButtonProperties(button, {
+        parent: this,
+        button: button
+      }));
+    this.processMenus.push(menu);
+  }, this);
+  this.registerKeyStrokes(this.processMenus);
 };
 
 scout.GroupBox.prototype._registerButtonKeyStrokes = function(button) {
@@ -189,7 +231,8 @@
   return this.controls;
 };
 
-scout.GroupBox.prototype._renderBorderVisible = function(borderVisible) {
+scout.GroupBox.prototype._renderBorderVisible = function() {
+  var borderVisible = this.borderVisible;
   if (this.borderDecoration === 'auto') {
     borderVisible = this._computeBorderVisible(borderVisible);
   }
@@ -199,9 +242,33 @@
   }
 };
 
-//Don't include in renderProperties, it is not necessary to execute it initially because renderBorderVisible is executed already
+// Don't include in renderProperties, it is not necessary to execute it initially because renderBorderVisible is executed already
 scout.GroupBox.prototype._renderBorderDecoration = function() {
-  this._renderBorderVisible(this.borderVisible);
+  this._renderBorderVisible();
+};
+
+scout.GroupBox.prototype.setMenuBarVisible = function(visible) {
+  this.menuBarVisible = visible;
+  if (this.rendered) {
+    this._renderMenuBarVisible();
+  }
+};
+
+scout.GroupBox.prototype._renderMenuBarVisible = function() {
+  if (this.menuBarVisible) {
+    this._renderMenuBar();
+  } else {
+    this.menuBar.remove();
+  }
+  this.invalidateLayoutTree();
+};
+
+scout.GroupBox.prototype._renderMenuBar = function() {
+  this.menuBar.render(this.$container);
+  if (this.menuBar.position === 'top') {
+    // move after title
+    this.menuBar.$container.insertAfter(this.$title);
+  }
 };
 
 /**
@@ -222,28 +289,30 @@
   return borderVisible;
 };
 
-scout.GroupBox.prototype._renderExpandable = function(expandable) {
-  var $control = this._$groupBoxTitle.children('.group-box-control');
+scout.GroupBox.prototype._renderExpandable = function() {
+  var expandable = this.expandable;
+  var $control = this.$title.children('.group-box-control');
 
   if (expandable) {
     if ($control.length === 0) {
       // Create control if necessary
       $control = this.$container.makeDiv('group-box-control')
-        .on('click', this._onGroupBoxControlClick.bind(this))
-        .prependTo(this._$groupBoxTitle);
+        .on('click', this._onControlClick.bind(this))
+        .prependTo(this.$title);
     }
-    this._$groupBoxTitle
+    this.$title
       .addClass('expandable')
-      .on('click.group-box-control', this._onGroupBoxControlClick.bind(this));
+      .on('click.group-box-control', this._onControlClick.bind(this));
   } else {
     $control.remove();
-    this._$groupBoxTitle
+    this.$title
       .removeClass('expandable')
       .off('.group-box-control');
   }
 };
 
-scout.GroupBox.prototype._renderExpanded = function(expanded) {
+scout.GroupBox.prototype._renderExpanded = function() {
+  var expanded = this.expanded;
   this.$container.toggleClass('collapsed', !expanded);
   if (this.borderDecoration === 'line') {
     this.$container.toggleClass('with-line', !expanded);
@@ -274,57 +343,83 @@
 };
 
 /**
- * @override
+ * @override FormField.js
  */
-scout.GroupBox.prototype._renderLabelVisible = function(visible) {
-  this._$groupBoxTitle.setVisible(visible && this.label && !this.mainBox);
+scout.GroupBox.prototype._renderLabelVisible = function(labelVisible) {
+  this.$title.setVisible(this._computeTitleVisible(labelVisible));
+  this._updateStatusVisible();
+};
+
+scout.GroupBox.prototype._computeTitleVisible = function(labelVisible) {
+  labelVisible = scout.nvl(labelVisible, this.labelVisible);
+  return !!(labelVisible && this.label && !this.mainBox);
+};
+
+/**
+ * @override FormField.js
+ */
+scout.GroupBox.prototype._updateStatusVisible = function() {
+  this._renderStatusVisible();
+};
+
+/**
+ * @override FormField.js
+ *
+ * Only show the group box status if title is visible.
+ */
+scout.GroupBox.prototype._computeStatusVisible = function() {
+  return scout.GroupBox.parent.prototype._computeStatusVisible.call(this) && this._computeTitleVisible();
+};
+
+scout.GroupBox.prototype._syncMenus = function(menus, oldMenus) {
+  scout.GroupBox.parent.prototype._syncMenus.call(this, menus, oldMenus);
+
+  if (this.menuBar) {
+    // updateMenuBar is required because menuBar is not created yet when synMenus is called initially
+    this._updateMenuBar();
+  }
+};
+
+scout.GroupBox.prototype._updateMenuBar = function() {
+  var menus = this.staticMenus
+    .concat(this.processMenus)
+    .concat(this.menus);
+
+  this.menuBar.setMenuItems(menus);
 };
 
 scout.GroupBox.prototype._renderMenus = function() {
-  var menu,
-    menus = this.menus,
-    menuItems = this.staticMenus.concat(menus);
-
-  // create a menu-adapter for each process button
-  this.processButtons.forEach(function(button) {
-    menu = scout.create('ButtonAdapterMenu',
-      scout.ButtonAdapterMenu.adaptButtonProperties(button, {
-        parent: this,
-        button: button
-      }));
-    menuItems.push(menu);
-  }, this);
-
-  // register keystrokes on root group-box
-  menuItems.forEach(function(menuItem) {
-    this.keyStrokeContext.registerKeyStroke(menuItem);
-    this._registerButtonKeyStrokes(menuItem);
-  }, this);
-
-  this.menuBar.updateItems(menuItems);
+  // NOP
 };
 
-scout.GroupBox.prototype._removeMenus = function(menus) {
-  menus.forEach(function(menu) {
-    menu.remove();
-  });
+scout.GroupBox.prototype._removeMenus = function() {
+  // menubar takes care about removal
 };
 
-scout.GroupBox.prototype._onGroupBoxControlClick = function(event) {
+scout.GroupBox.prototype.setStaticMenus = function(staticMenus) {
+  this.staticMenus = staticMenus;
+  this._updateMenuBar();
+};
+
+scout.GroupBox.prototype._onControlClick = function(event) {
   if (this.expandable) {
-    this.setGroupBoxExpanded(!this.expanded);
+    this.setExpanded(!this.expanded);
   }
   $.suppressEvent(event); // otherwise, the event would be triggered twice sometimes (by group-box-control and group-box-title)
 };
 
-scout.GroupBox.prototype.setGroupBoxExpanded = function(expanded) {
+scout.GroupBox.prototype.setExpanded = function(expanded) {
   if (this.expanded !== expanded) {
     this.expanded = expanded;
-    this._send('expanded', {
-      expanded: expanded
-    });
+    this._sendExpanded();
   }
   if (this.rendered) {
-    this._renderExpanded(expanded);
+    this._renderExpanded();
   }
 };
+
+scout.GroupBox.prototype._sendExpanded = function() {
+  this._send('expanded', {
+    expanded: this.expanded
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
index 5f29ed9..48a0049 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
@@ -21,10 +21,13 @@
 scout.GroupBoxLayout.prototype.layout = function($container) {
   var titleMarginX, menuBarSize, gbBodySize,
     statusWidth = 0,
+    statusPosition = this._groupBox.statusPosition,
+    labelMarginX = 0,
     htmlContainer = this._groupBox.htmlComp,
     htmlGbBody = this._htmlGbBody(),
     htmlMenuBar = this._htmlMenuBar(),
-    $groupBoxTitle = this._groupBox._$groupBoxTitle,
+    $groupBoxTitle = this._groupBox.$title,
+    $label = this._groupBox.$label,
     $status = this._groupBox.$status,
     containerSize = htmlContainer.getAvailableSize()
     .subtract(htmlContainer.getInsets());
@@ -50,8 +53,13 @@
   gbBodySize.height -= menuBarSize.height;
 
   if (statusWidth > 0) {
-    titleMarginX = $groupBoxTitle.cssMarginX() + statusWidth;
-    $groupBoxTitle.css('width', 'calc(100% - ' + titleMarginX + 'px');
+    if (statusPosition === scout.FormField.STATUS_POSITION_TOP) {
+      labelMarginX = $label.cssMarginX() + statusWidth;
+      $label.css('width', 'calc(100% - ' + labelMarginX + 'px');
+    } else {
+      titleMarginX = $groupBoxTitle.cssMarginX() + statusWidth;
+      $groupBoxTitle.css('width', 'calc(100% - ' + titleMarginX + 'px');
+    }
   }
 
   // When max. content width should be enforced, add a padding to the group box body
@@ -85,16 +93,20 @@
     }),
     top = containerPadding.top,
     right = containerPadding.right,
-    $groupBoxTitle = this._groupBox._$groupBoxTitle,
+    $groupBoxTitle = this._groupBox.$title,
     titleInnerHeight = $groupBoxTitle.innerHeight(),
     $status = this._groupBox.$status,
-    statusMargins = scout.graphics.getMargins($status);
+    statusMargins = scout.graphics.getMargins($status),
+    statusPosition = this._groupBox.statusPosition;
 
-  $status.cssWidth(this._statusWidth)
-    .cssTop(top + $groupBoxTitle.cssMarginTop())
-    .cssRight(right)
-    .cssHeight(titleInnerHeight - statusMargins.vertical())
-    .cssLineHeight(titleInnerHeight - statusMargins.vertical());
+  $status.cssWidth(this._statusWidth);
+  if (statusPosition === scout.FormField.STATUS_POSITION_DEFAULT) {
+    $status
+      .cssTop(top + $groupBoxTitle.cssMarginTop())
+      .cssRight(right)
+      .cssHeight(titleInnerHeight - statusMargins.vertical())
+      .cssLineHeight(titleInnerHeight - statusMargins.vertical());
+  }
 };
 
 scout.GroupBoxLayout.prototype.preferredLayoutSize = function($container) {
@@ -109,7 +121,7 @@
 
     htmlMenuBar = this._htmlMenuBar();
     if (htmlMenuBar) {
-      prefSize.height += htmlMenuBar.getPreferredSize(true).height;
+      prefSize.height += htmlMenuBar.getPreferredSize().height;
       //in this case there is no padding. add some padding to width.
       if (!this._groupBox.borderVisible) {
         prefSize.height += this._groupBox.menuBar.position === 'top' ? 14 : 16;
@@ -133,7 +145,7 @@
 };
 
 scout.GroupBoxLayout.prototype._titleHeight = function() {
-  return scout.graphics.prefSize(this._groupBox._$groupBoxTitle, true).height;
+  return scout.graphics.prefSize(this._groupBox.$title, true).height;
 };
 
 scout.GroupBoxLayout.prototype._menuBarSize = function(htmlMenuBar, containerSize, statusWidth) {
@@ -149,7 +161,7 @@
  * Return menu-bar when it exists and it is visible.
  */
 scout.GroupBoxLayout.prototype._htmlMenuBar = function() {
-  if (this._groupBox.menuBar) {
+  if (this._groupBox.menuBar && this._groupBox.menuBarVisible) {
     var htmlMenuBar = scout.HtmlComponent.get(this._groupBox.menuBar.$container);
     if (htmlMenuBar.isVisible()) {
       return htmlMenuBar;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxMenuItemsOrder.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxMenuItemsOrder.js
index 0a7af0a..c48aef4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxMenuItemsOrder.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxMenuItemsOrder.js
@@ -17,7 +17,7 @@
     rightMenus = [];
 
   items.forEach(function(item) {
-    if (scout.menus.isButton(item)) {
+    if (item.isButton()) {
       var horizontalAlignment = item.horizontalAlignment;
       if (horizontalAlignment === undefined) {
         // Real buttons have no property 'horizontalAlignment' but a corresponding field on the gridData
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/htmlfield/HtmlField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/htmlfield/HtmlField.js
index d7c080b..c074a2d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/htmlfield/HtmlField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/htmlfield/HtmlField.js
@@ -33,8 +33,8 @@
 scout.HtmlField.prototype._renderProperties = function() {
   scout.HtmlField.parent.prototype._renderProperties.call(this);
 
-  this._renderScrollBarsEnabled();
-  this._renderScrollToPosition(this.scrollToPosition);
+  this._renderScrollBarEnabled();
+  this._renderScrollToAnchor(this.scrollToAnchor);
 };
 
 /**
@@ -53,7 +53,7 @@
 
   // this method replaces the content, the scroll bars get lost -> render again (only necessary if already rendered, otherwise it is done by renderProperties)
   if (this.rendered) {
-    this._renderScrollBarsEnabled(this.scrollBarsEnabled);
+    this._renderScrollBarEnabled(this.scrollBarEnabled);
   }
 
   this.invalidateLayoutTree();
@@ -64,8 +64,8 @@
   scout.HtmlField.parent.prototype._remove.call(this);
 };
 
-scout.HtmlField.prototype._renderScrollBarsEnabled = function() {
-  if (this.scrollBarsEnabled) {
+scout.HtmlField.prototype._renderScrollBarEnabled = function() {
+  if (this.scrollBarEnabled) {
     scout.scrollbars.install(this.$field, {
       parent: this
     });
@@ -76,13 +76,13 @@
 
 // Not called in _renderProperties() because this is not really a property (more like an event)
 scout.HtmlField.prototype._renderScrollToEnd = function() {
-  if (this.scrollBarsEnabled) {
+  if (this.scrollBarEnabled) {
     scout.scrollbars.scrollToBottom(this.$fieldContainer);
   }
 };
 
-scout.HtmlField.prototype._renderScrollToPosition = function(anchor) {
-  if (this.scrollBarsEnabled && anchor && this.$field.find(anchor)) {
+scout.HtmlField.prototype._renderScrollToAnchor = function(anchor) {
+  if (this.scrollBarEnabled && anchor && this.$field.find(anchor)) {
     var anchorElem = this.$field.find('#'.concat(anchor));
     if (anchorElem && anchorElem.length > 0) {
       scout.scrollbars.scrollTo(this.$fieldContainer, anchorElem);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/imagefield/ImageField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/imagefield/ImageField.js
index d747b99..fcc3c11 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/imagefield/ImageField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/imagefield/ImageField.js
@@ -30,7 +30,6 @@
   scout.ImageField.parent.prototype._renderProperties.call(this);
   this._renderImageUrl();
   this._renderAutoFit();
-  this._renderMenus();
   this._renderScrollBarEnabled();
   this._renderDropType();
 };
@@ -89,11 +88,11 @@
 scout.ImageField.prototype._onImageLoad = function(event) {
   this.$field.removeClass('broken');
   scout.scrollbars.update(this.$fieldContainer);
-  this.revalidateLayoutTree();
+  this.invalidateLayoutTree();
 };
 
 scout.ImageField.prototype._onImageError = function(event) {
   this.$field.addClass('empty broken');
   scout.scrollbars.update(this.$fieldContainer);
-  this.revalidateLayoutTree();
+  this.invalidateLayoutTree();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js
index 39fa85b..205a833 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js
@@ -65,7 +65,7 @@
 scout.NumberField.prototype.setDisplayText = function(value) {
   this.displayText = scout.objects.isNumber(value) ? value.toString() : '';
   if (this.rendered) {
-    this._renderDisplayText(this.displayText);
+    this._renderDisplayText();
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/placeholder/PlaceholderField.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/placeholder/PlaceholderField.css
deleted file mode 100644
index c795c3f..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/placeholder/PlaceholderField.css
+++ /dev/null
@@ -1,10 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButton.js
index cb99430..c5dda17 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButton.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButton.js
@@ -10,6 +10,8 @@
  ******************************************************************************/
 scout.RadioButton = function() {
   scout.RadioButton.parent.call(this);
+
+  this.focusWhenSelected;
 };
 scout.inherits(scout.RadioButton, scout.Button);
 
@@ -23,6 +25,11 @@
   ]);
 };
 
+scout.RadioButton.prototype._init = function(model) {
+  scout.RadioButton.parent.prototype._init.call(this, model);
+  this.focusWhenSelected = scout.nvl(model.focusWhenSelected, scout.device.supportsFocusEmptyBeforeDiv);
+};
+
 scout.RadioButton.prototype._render = function($parent) {
   this.addContainer($parent, 'radio-button', new scout.ButtonLayout(this));
   this.addField($parent.makeDiv()
@@ -42,7 +49,7 @@
 
 scout.RadioButton.prototype._mouseDown = function(event) {
   this.select();
-  if (scout.device.supportsFocusEmptyBeforeDiv) {
+  if (this.focusWhenSelected) {
     this.session.focusManager.requestFocus(this.$field);
     event.preventDefault();
   }
@@ -67,7 +74,6 @@
   this._sendProperty('selected');
   if (this.rendered) {
     this._renderSelected();
-    this.$field.focus();
   }
 };
 
@@ -102,3 +108,8 @@
 scout.RadioButton.prototype._renderSelected = function() {
   this.$field.toggleClass('checked', this.selected);
 };
+
+scout.RadioButton.prototype._renderForegroundColor = function() {
+  // Don't call renderForeground of Button.js, $butonLabel does not exist for radio buttons
+  scout.FormField.prototype._renderForegroundColor.call(this);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButtonGroup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButtonGroup.js
index 327e33b..6630dc3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButtonGroup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/radiobutton/RadioButtonGroup.js
@@ -101,3 +101,8 @@
     }
   }, this);
 };
+
+scout.RadioButtonGroup.prototype.addButton = function(radioButton) {
+  this.formFields.push(radioButton);
+  this.radioButtons.push(radioButton);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/sequencebox/SequenceBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/sequencebox/SequenceBox.js
index ed486a5..72f3833 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/sequencebox/SequenceBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/sequencebox/SequenceBox.js
@@ -33,8 +33,7 @@
 };
 
 scout.SequenceBox.prototype._onFieldPropertyChange = function(event) {
-  var field = event.source,
-    visibiltyChanged = (event.changedProperties.indexOf('visible') !== -1);
+  var visibiltyChanged = (event.changedProperties.indexOf('visible') !== -1);
   if (scout.arrays.containsAny(event.changedProperties, ['errorStatus', 'tooltipText', 'visible', 'menus', 'menusVisible'])) {
     this._handleStatus(visibiltyChanged);
   }
@@ -74,9 +73,7 @@
 };
 
 scout.SequenceBox.prototype._getLastVisibleField = function() {
-  var lastVisibleField, visibleFields;
-
-  visibleFields = this.fields.filter(function(field) {
+  var visibleFields = this.fields.filter(function(field) {
     return field.visible;
   });
   if (visibleFields.length === 0) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/slider/SliderField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/slider/SliderField.js
new file mode 100644
index 0000000..6ca6a1a
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/slider/SliderField.js
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SliderField = function() {
+  scout.SliderField.parent.call(this);
+  this.slider;
+};
+scout.inherits(scout.SliderField, scout.ValueField);
+
+scout.SliderField.prototype._init = function(model) {
+  scout.SliderField.parent.prototype._init.call(this, model);
+  var sliderOptions = $.extend({parent: this}, model);
+  this.slider = scout.create('Slider', sliderOptions);
+};
+
+scout.SliderField.prototype._render = function($parent) {
+  this.addContainer($parent, 'slider-field');
+  this.addLabel();
+  this.addMandatoryIndicator();
+  this._renderSlider();
+};
+
+scout.SliderField.prototype._renderSlider = function() {
+  this.slider.render(this.$container);
+  this.addField(this.slider.$container);
+};
+
+scout.SliderField.prototype.setValue = function(value) {
+  this.slider.setValue(value);
+};
+
+scout.SliderField.prototype.getValue = function() {
+  return this.slider.value;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooser.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooser.js
index 2bab5ea..20070a9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooser.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooser.js
@@ -12,36 +12,50 @@
   scout.ProposalChooser.parent.call(this);
   this._addAdapterProperties(['model']);
   this.$container;
-  this._$status;
-  this._$activeFilter;
+  this.$status;
+  this.$activeFilter;
   this.htmlComp;
+
+  this._updateStatusTimeout;
 };
 scout.inherits(scout.ProposalChooser, scout.ModelAdapter);
 
+/**
+ * @see IContentAssistField#getActiveFilterLabels() - should have the same order.
+ */
+scout.ProposalChooser.ACTIVE_FILTER_VALUES = ['UNDEFINED', 'FALSE', 'TRUE'];
+
 scout.ProposalChooser.prototype._render = function($parent) {
   this.$container = $parent.appendDiv('proposal-chooser');
   this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
   this.htmlComp.setLayout(new scout.ProposalChooserLayout(this));
   this.model.render(this.$container);
   if (this.model instanceof scout.Tree) {
-    //disable focus on field container
+    // disable focus on field container
     this.model._onNodeControlMouseDownDoFocus = function() {};
   }
 
-  this._$status = this.$container.appendDiv('status');
+  // status
+  this.$status = this.$container
+    .appendDiv('status')
+    .setVisible(false);
 
-  // support for activeFilter
+  // active filter
   if (this.activeFilter) {
-    this._$activeFilter = this.$container.appendDiv('active-filter');
-    var group = scout.create('RadioButtonGroup', {
-      parent: this
+    this.activeFilterGroup = scout.create('RadioButtonGroup', {
+      parent: this,
+      labelVisible: false,
+      statusVisible: false
     });
 
-    this._appendOption(group, 'UNDEFINED', this.session.text('ui.All'), true);
-    this._appendOption(group, 'TRUE', this.session.text('ui.Active'), false);
-    this._appendOption(group, 'FALSE', this.session.text('ui.Inactive'), false);
+    // add radio buttons
+    scout.ProposalChooser.ACTIVE_FILTER_VALUES.forEach(function(value, index) {
+      this._renderButton(value, index);
+    }, this);
 
-    group.render(this._$activeFilter);
+    this.activeFilterGroup.render(this.$container);
+    this.activeFilterGroup.$container.addClass('active-filter');
+    this.activeFilterGroup.removeMandatoryIndicator();
   }
 };
 
@@ -62,46 +76,84 @@
 
 scout.ProposalChooser.prototype._renderStatus = function() {
   this._updateStatus();
-  this.htmlComp.revalidateLayout();
 };
 
 scout.ProposalChooser.prototype._renderStatusVisible = function() {
   this._updateStatus();
-  this.htmlComp.revalidateLayout();
+};
+
+scout.ProposalChooser.prototype._computeStatusVisible = function() {
+  return !!(this.statusVisible && this.status);
 };
 
 scout.ProposalChooser.prototype._updateStatus = function() {
-  $.log.debug('_updateStatus status=' + this.status + ' statusVisible=' + this.statusVisible);
-  this._$status.setVisible(this.statusVisible && this.status);
+  // Note: the UI has a special way to deal with the status. When the UI is rendered
+  // we do NOT render an OK status, even when it is set on the model. The status
+  // "Search proposals..." is set to severity OK. That status is only displayed, when
+  // it is still there after 250 ms. Usually a smart-field lookup is fast, so the user
+  // never sees the status message. However: it would be better if the status on the
+  // (Java-)model would implement the behavior described above, but
+  // this would require a timer thread, so it is easier to implement that in the UI.
+  // Status with other severities than OK are displayed immediately.
+  clearTimeout(this._updateStatusTimeout);
+  if (scout.objects.optProperty(this.status, 'severity') === scout.Status.Severity.OK) {
+    // compute statusVisible 250 ms later (status can change in the meantime)
+    this._updateStatusTimeout = setTimeout(
+        this._updateStatusImpl.bind(this), 250);
+  } else {
+    this._updateStatusImpl();
+  }
+};
+
+scout.ProposalChooser.prototype._updateStatusImpl = function() {
+  var
+    oldVisible = this.$status.isVisible(),
+    oldMessage = this.$status.text(),
+    visible = this._computeStatusVisible();
+
+  if (oldVisible === visible &&
+      oldMessage === scout.objects.optProperty(this.status, 'message')) {
+    return;
+  }
+
+  $.log.debug('_updateStatus statusVisible=' + visible);
+  this.$status.setVisible(visible);
   if (this.status) {
     this._setStatusMessage(this.status.message);
   } else {
-    this._$status.text('');
+    this.$status.text('');
   }
+  this.htmlComp.invalidateLayoutTree();
 };
 
 /**
  * Replaces an ellipsis (...) at the end of the message-text with a CSS animation.
  */
 scout.ProposalChooser.prototype._setStatusMessage = function(message) {
-  scout.Status.animateStatusMessage(this._$status, message);
+  scout.Status.animateStatusMessage(this.$status, message);
 };
 
-scout.ProposalChooser.prototype._appendOption = function(group, value, text, selected) {
+scout.ProposalChooser.prototype._renderButton = function(value, index) {
   var radio = scout.create('RadioButton', {
-      parent: group,
-      label: text,
-      radioValue: value,
-      selected: selected
-    }),
-    that = this;
-  radio._mouseDown = function(event) {
-    this.select();
-  };
-  radio._send = function() {
-    that._onActiveFilterChanged(this.radioValue);
-  };
-  group.formFields.push(radio);
+      parent: this.activeFilterGroup,
+      label: this.activeFilterLabels[index],
+      radioValue: scout.ProposalChooser.ACTIVE_FILTER_VALUES[index],
+      selected: this.activeFilter === value,
+      focusWhenSelected: false,
+      gridData: {
+        x: index,
+        y: 1,
+        useUiWidth: true
+      }
+    });
+
+  radio.on('propertyChange', function(event) {
+    if (event.changedProperties.indexOf('selected') !== -1 && event.newProperties.selected === true) {
+      this._onActiveFilterChanged(event.source.radioValue);
+    }
+  }.bind(this));
+
+  this.activeFilterGroup.addButton(radio);
 };
 
 scout.ProposalChooser.prototype._onActiveFilterChanged = function(radioValue) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooserLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooserLayout.js
index c72e831..4f435ab 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooserLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/ProposalChooserLayout.js
@@ -105,27 +105,34 @@
 };
 
 scout.ProposalChooserLayout.prototype.layout = function($container) {
-  var htmlContainer = scout.HtmlComponent.get($container),
-    htmlModel = scout.HtmlComponent.get($container.children(this._typeHandler.cssSelector)),
+  var filterPrefSize,
+    htmlContainer = scout.HtmlComponent.get($container),
+    htmlComp = scout.HtmlComponent.get($container.children(this._typeHandler.cssSelector)),
     size = htmlContainer.getSize().subtract(htmlContainer.getInsets()),
-    $status = $container.children('.status:visible'),
-    $activeFilter = $container.children('.active-filter:visible');
+    $status = this._proposalChooser.$status,
+    hasStatus = $status && $status.isVisible(),
+    filter = this._proposalChooser.activeFilterGroup;
 
-  if ($status.length) {
+  if (hasStatus) {
     size.height -= scout.graphics.getSize($status).height;
   }
-  if ($activeFilter.length) {
-    size.height -= scout.graphics.getSize($activeFilter).height;
+  if (filter) {
+    filterPrefSize = filter.htmlComp.getPreferredSize();
+    size.height -= filterPrefSize.height;
   }
 
   // when status or active-filter is available we must explicitly set the
   // height of the model (table or tree) in pixel. Otherwise we'd rely on
   // the CSS height which is set to 100%.
-  if ($status.length || $activeFilter.length) {
-    htmlModel.pixelBasedSizing = true;
+  if (hasStatus || filter) {
+    htmlComp.pixelBasedSizing = true;
   }
 
-  htmlModel.setSize(size);
+  htmlComp.setSize(size);
+
+  if (filter) {
+    filter.htmlComp.setSize(new scout.Dimension(size.width, filterPrefSize.height));
+  }
 };
 
 /**
@@ -134,10 +141,10 @@
  * and doesn't try to find the preferred size by algorithm.
  */
 scout.ProposalChooserLayout.prototype.preferredLayoutSize = function($container) {
-  var oldDisplay, prefSize, modelSize, statusSize, activeFilterSize,
-    htmlContainer = this._proposalChooser.htmlComp,
-    $status = this._proposalChooser._$status,
-    $activeFilter = this._proposalChooser._$activeFilter;
+  var oldDisplay, prefSize, modelSize, statusSize, activeFilterSize, filterPrefSize,
+    htmlComp = this._proposalChooser.htmlComp,
+    $status = this._proposalChooser.$status,
+    filter = this._proposalChooser.activeFilterGroup;
 
   this._typeHandler.prepare($container, this);
 
@@ -157,19 +164,18 @@
   if ($status && $status.isVisible()) {
     oldDisplay = $status.css('display');
     $status.css('display', 'inline-block');
-    statusSize = scout.graphics.prefSize($status, true, true);
+    statusSize = scout.graphics.prefSize($status, true, {
+      useCssSize: true
+    });
     $status.css('display', oldDisplay);
     prefSize = new scout.Dimension(Math.max(prefSize.width, statusSize.width), prefSize.height + statusSize.height);
   }
 
-  if ($activeFilter && $activeFilter.isVisible()) {
-    oldDisplay = $activeFilter.css('display');
-    $activeFilter.css('display', 'inline-block');
-    activeFilterSize = scout.graphics.prefSize($activeFilter, true, true);
-    $activeFilter.css('display', oldDisplay);
-    prefSize = new scout.Dimension(Math.max(prefSize.width, activeFilterSize.width), prefSize.height + activeFilterSize.height);
+  if (filter) {
+    filterPrefSize = filter.htmlComp.getPreferredSize();
+    prefSize = new scout.Dimension(Math.max(prefSize.width, filterPrefSize.width), prefSize.height + filterPrefSize.height);
   }
 
   $container.toggleClass('empty', modelSize.height === 0);
-  return prefSize.add(htmlContainer.getInsets());
+  return prefSize.add(htmlComp.getInsets());
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.css
index 8952808..1a93190 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.css
@@ -132,7 +132,11 @@
         background-color: @item-selection-background-color;
         border-color: @item-selection-border-color;
       }
+    }
+  }
 
+  &:not(.touch) > .table {
+    & > .table-data > .table-row {
       &.selected.last {
         /* Change color of last element to avoid double-border effect */
         border-bottom-color: @item-selection-background-color;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.js
index 52d1be1..920e203 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartField.js
@@ -10,8 +10,6 @@
  ******************************************************************************/
 // FIXME awe: (smart-field) Do not open popup when Ctrl or Alt key is pressed (e.g. Ctrl + 1)
 
-// FIXME awe: (smart-field) Lupe-Icon durch Loading-Icon austauschen während Laden von SmartField
-
 /**
  * Three smart-field modes:
  *
@@ -35,9 +33,13 @@
   /**
    * This property is used to prevent unnecessary requests to the server.
    */
-  this._oldSearchText;
+  this._oldDisplayText;
   this._popup;
   this._requestedProposal = false;
+  /**
+   * This property is used to prevent multiple acceptProposal request to the server (blur, aboutToBlur, acceptInput from Action).
+   */
+  this._acceptedInput = false;
   this._tabPrevented = null;
   this._pendingProposalTyped = null;
   this._navigating = false;
@@ -66,6 +68,8 @@
     this._popup = scout.create(popupType, {
       parent: this,
       $anchor: this.$field,
+      boundToAnchor: !this.touch,
+      closeOnAnchorMousedown: false,
       field: this
     });
   }
@@ -97,7 +101,9 @@
 
 scout.SmartField.prototype._remove = function() {
   scout.SmartField.parent.prototype._remove.call(this);
-  if (this._popup) {
+  // popup may not be reused because $anchor would point to a removed field
+  // Don't set to null in case of embedded mode to make sure not another popup gets created by the field itself when touch popup get rendered
+  if (this._popup && !this.embedded) {
     this._popup = null;
   }
 };
@@ -117,15 +123,24 @@
 };
 
 scout.SmartField.prototype._syncDisplayText = function(displayText) {
-  this._oldSearchText = displayText;
+  this._oldDisplayText = displayText;
   this.displayText = displayText;
 };
 
 /**
  * @override ValueField.js
  */
-scout.SmartField.prototype._renderDisplayText = function(displayText) {
-  scout.fields.valOrText(this, this.$field, displayText);
+scout.SmartField.prototype._renderDisplayText = function() {
+  scout.fields.valOrText(this, this.$field, this.displayText);
+};
+
+scout.SmartField.prototype._readDisplayText = function() {
+  // in case of touch mode a 'div' is rendered and not an 'input' -> use text not val
+  return scout.fields.valOrText(this, this.$field);
+};
+
+scout.SmartField.prototype._readSearchText = function() {
+  return this._readDisplayText();
 };
 
 /**
@@ -135,8 +150,14 @@
  */
 scout.SmartField.prototype._syncProposalChooser = function(proposalChooser) {
   $.log.debug('(SmartField#_syncProposalChooser) set _requestedProposal to false');
-  this.proposalChooser = proposalChooser;
   this._requestedProposal = false;
+  if (this.embedded) {
+    // Never hold the proposal chooser in embedded mode, original smart field takes care of it
+    // This makes sure proposal chooser does not get rendered twice.
+    // Prevent rendering as well, original smart field will render it into the popup
+    return false;
+  }
+  this.proposalChooser = proposalChooser;
 };
 
 /**
@@ -144,7 +165,7 @@
  */
 scout.SmartField.prototype._renderProposalChooser = function() {
   $.log.debug('(SmartField#_renderProposalChooser) proposalChooser=' + this.proposalChooser + ' touch=' + this.touch);
-  if (!this.proposalChooser || this.touch) {
+  if (!this.proposalChooser) {
     return;
   }
   this._renderPopup();
@@ -156,9 +177,6 @@
  */
 scout.SmartField.prototype._removeProposalChooser = function() {
   $.log.trace('(SmartField#_removeProposalChooser) proposalChooser=' + this.proposalChooser);
-  if (this.touch) {
-    return;
-  }
   this._closeProposal(false);
 };
 
@@ -175,22 +193,14 @@
 
 scout.SmartField.prototype._onClick = function(event) {
   if (scout.fields.handleOnClick(this)) {
-    if (this.touch) {
-      this._popup.open();
-    } else {
-      this._openProposal(true);
-    }
+    this._openProposal(true);
   }
 };
 
 scout.SmartField.prototype._onIconClick = function(event) {
   if (scout.fields.handleOnClick(this)) {
-    if (this.touch) {
-      this._popup.open();
-    } else {
-      scout.SmartField.parent.prototype._onIconClick.call(this, event);
-      this._openProposal(true);
-    }
+    scout.SmartField.parent.prototype._onIconClick.call(this, event);
+    this._openProposal(true);
   }
 };
 
@@ -292,7 +302,7 @@
 
   // The typed character is not available until the keyUp event happens
   // That's why we must deal with that event here (and not in keyDown)
-  // We don't use _searchText() here because we always want the text the
+  // We don't use _displayText() here because we always want the text the
   // user has typed.
   if (this._popup.rendered) {
     this._proposalTyped();
@@ -302,29 +312,33 @@
 };
 
 scout.SmartField.prototype._onFocus = function(e) {
-  this._oldSearchText = this._readSearchText();
+  this._oldDisplayText = this._readDisplayText();
+  this._acceptedInput = false;
 };
 
 scout.SmartField.prototype._proposalTyped = function() {
-  var searchText = this._readDisplayText();
-  $.log.trace('(SmartField#_proposalTyped) searchText=' + searchText + ' displayText=' + this.displayText);
-  if (searchText === this.displayText) {
+  var displayText = this._readSearchText();
+  $.log.trace('(SmartField#_proposalTyped) displayText=' + displayText + ' currentDisplayText=' + this.displayText);
+  if (displayText === this.displayText) {
     return;
   }
-  this.displayText = searchText;
+  this.displayText = displayText;
 
   // debounce send
   var id, func;
   this._clearPendingProposalTyped();
 
   func = function() {
-    $.log.debug('(SmartField#_proposalTyped) send searchText=' + searchText);
+    $.log.debug('(SmartField#_proposalTyped) send displayText=' + displayText);
     this._send('proposalTyped', {
-      searchText: searchText
+      displayText: displayText
     });
   }.bind(this);
   id = setTimeout(func, this.DEBOUNCE_DELAY);
-  this._pendingProposalTyped = {func: func, id: id};
+  this._pendingProposalTyped = {
+    func: func,
+    id: id
+  };
 };
 
 /**
@@ -341,6 +355,8 @@
   this._requestedProposal = false;
 
   if (this.embedded) {
+    // Do not accept input while popup is open
+    // Done button of ios virtual keyboard triggers blur -> don't close the popup when pressing done, popup is closed when pressing enter.
     return;
   }
 
@@ -354,7 +370,7 @@
   if (this._tabPrevented) {
     this._tabPrevented = null;
   } else {
-    this._acceptProposal(true);
+    this.acceptInput();
   }
 };
 
@@ -367,7 +383,7 @@
 
 /**
  * This method is called when the user presses the TAB or ENTER key in the UI, or when _onFieldBlur()
- * or acceptInput(). In case the field is a proposal-field we must send the current searchText
+ * or acceptInput(). In case the field is a proposal-field we must send the current displayText
  * to the server, even when the popup is not opened (this happens when the user types something which
  * is not in the list of proposals). We must accept the user defined text in that case.
  */
@@ -377,10 +393,11 @@
   this._clearPendingProposalTyped();
 
   forceClose = scout.nvl(forceClose, false);
-  var proposalChooserOpen = !!this.proposalChooser,
-    searchText = this._readSearchText();
+  // embedded smartfield does not hold a reference to the chooser, but if it is shown touch popup is open and therefore the chooser as well
+  var proposalChooserOpen = !!this.proposalChooser || this.embedded,
+    displayText = this._readSearchText();
 
-  $.log.debug('(SmartField#_acceptProposal) searchText=' + searchText + ' proposalChooserOpen=' + proposalChooserOpen + ' forceClose=' + forceClose);
+  $.log.debug('(SmartField#_acceptProposal) displayText=' + displayText + ' proposalChooserOpen=' + proposalChooserOpen + ' forceClose=' + forceClose);
   if (proposalChooserOpen) {
     // Always send accept proposal, when proposal chooser is opened,
     // Because user wants to choose the selected proposal from the
@@ -393,20 +410,28 @@
     // UI Server has not enough information to find out what happened
     // and would accept a proposal, since on the model there's still
     // a selected proposal (ticket #168652).
-    var textDeleted = scout.strings.empty(searchText) && scout.strings.hasText(this._oldSearchText);
+    var textDeleted = scout.strings.empty(displayText) && scout.strings.hasText(this._oldDisplayText);
     if (textDeleted && !this._navigating) {
-      this._sendDeleteProposal(searchText);
+      this._sendDeleteProposal(displayText);
+      this._triggerDeleteProposal(displayText);
     } else {
-      this._sendAcceptProposal(searchText, true, forceClose);
+      this._sendAcceptProposal(displayText, true, forceClose);
+      this._triggerAcceptProposal(displayText);
+    }
+
+    if (this.embedded) {
+      // Always close popup when user presses 'Enter' on virtual keyboard if touch popup is open
+      this._closeProposal();
     }
   } else {
     // When proposal chooser is closed, only send accept proposal
     // when search text has changed. Prevents unnecessary requests
     // to the server when the user tabs over the smart-field.
-    if (searchText === this._oldSearchText) {
+    if (displayText === this._oldDisplayText) {
       return;
     }
-    this._sendAcceptProposal(searchText, false, forceClose);
+    this._sendAcceptProposal(displayText, false, forceClose);
+    this._triggerAcceptProposal(displayText);
   }
 
   this.session.listen().done(function() {
@@ -417,34 +442,33 @@
   }.bind(this));
 };
 
-/**
- * Override this method to return the search-text for this smart-field.
- * The implementation is different for single- and multi-line smart-fields.
- */
-scout.SmartField.prototype._readSearchText = function() {
-  return this._readDisplayText();
+scout.SmartField.prototype._triggerDeleteProposal = function(displayText) {
+  this.trigger('deleteProposal', {
+    displayText: displayText
+  });
 };
 
-scout.SmartField.prototype._updateSeachText = function(searchText) {
-  this.displayText = searchText;
-  this._oldSearchText = searchText;
-};
-
-scout.SmartField.prototype._sendDeleteProposal = function(searchText) {
-  this._updateSeachText(searchText);
+scout.SmartField.prototype._sendDeleteProposal = function(displayText) {
+  this._syncDisplayText(displayText);
   this._send('deleteProposal');
 };
 
-scout.SmartField.prototype._sendAcceptProposal = function(searchText, chooser, forceClose) {
-  this._updateSeachText(searchText);
+scout.SmartField.prototype._triggerAcceptProposal = function(displayText) {
+  this.trigger('acceptProposal', {
+    displayText: displayText
+  });
+};
+
+scout.SmartField.prototype._sendAcceptProposal = function(displayText, chooser, forceClose) {
+  this._syncDisplayText(displayText);
   this._send('acceptProposal', {
-    searchText: searchText,
+    displayText: displayText,
     chooser: chooser,
     forceClose: forceClose
   });
 };
 
-// FIXME awe, dwi: check if we can find next tabbable in the current focus-context (FocusManager)
+// FIXME awe, dwi: (focus) check if we can find next tabbable in the current focus-context (FocusManager)
 scout.SmartField.prototype._focusNextTabbable = function() {
   var $tabElements = this.entryPoint().find(':tabbable');
   var direction = this._tabPrevented.directionBack ? -1 : 1;
@@ -484,21 +508,20 @@
  * has not changed.
  */
 scout.SmartField.prototype._openProposal = function(browseAll) {
-  var displayText = this._readDisplayText(),
-    searchText = this._readDisplayText(),
+  var displayText = this._readSearchText(),
     selectCurrentValue = browseAll;
   this.displayText = displayText;
-  if(this.errorStatus){
-    selectCurrentValue=false;
+  if (this.errorStatus) {
+    selectCurrentValue = false;
   }
 
   if (this._requestedProposal) {
     $.log.trace('(SmartField#_openProposal) already requested proposal -> do nothing');
   } else {
     this._requestedProposal = true;
-    $.log.debug('(SmartField#_openProposal) send openProposal. searchText=' + searchText + ' selectCurrentValue=' + selectCurrentValue);
+    $.log.debug('(SmartField#_openProposal) send openProposal. displayText=' + displayText + ' selectCurrentValue=' + selectCurrentValue);
     this._send('openProposal', {
-      searchText: searchText,
+      displayText: displayText,
       selectCurrentValue: selectCurrentValue,
       browseAll: browseAll
     });
@@ -510,14 +533,20 @@
     return;
   }
   this._popup.open();
+  if (this.touch) {
+    this._acceptedInput = false;
+    // Error message is shown on touch popup as well, don't show twice
+    this._hideStatusMessage();
+  }
 };
 
 /**
  * @override ValueField.js
  */
 scout.SmartField.prototype.acceptInput = function(whileTyping) {
-  if (this.mode !== scout.FormField.MODE_CELLEDITOR && !this.embedded) {
+  if (this.mode !== scout.FormField.MODE_CELLEDITOR && !this._acceptedInput) {
     this._acceptProposal(true);
+    this._acceptedInput = true;
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldButton.js
deleted file mode 100644
index 41556dc..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldButton.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.SmartFieldButton = function() {
-  scout.SmartFieldButton.parent.call(this);
-
-  this._popup;
-  this._smartField;
-};
-scout.inherits(scout.SmartFieldButton, scout.ValueField);
-
-/**
- * @override Widget.js
- */
-scout.SmartFieldButton.prototype._createKeyStrokeContext = function() {
-  return new scout.InputFieldKeyStrokeContext();
-};
-
-scout.SmartFieldButton.prototype._render = function($parent) {
-  var cssClass = this.proposal ? 'proposal-field' : 'smart-field';
-  this.addContainer($parent, cssClass);
-  this.addLabel();
-
-  this.addField(scout.fields.makeTextField($parent)
-    .attr('readonly', 'readonly')
-    .click(this._onClick.bind(this)));
-
-  this.addMandatoryIndicator();
-  this.addIcon();
-  this.addStatus();
-  this.addSmartFieldButtonPopup();
-};
-
-scout.SmartFieldButton.prototype.addSmartFieldButtonPopup = function() {
-  this._popup = scout.create('SmartFieldButtonPopup', {
-    parent: this,
-    $anchor: this.$field,
-    smartFieldButton: this
-  });
-};
-
-/**
- * Method invoked if being rendered within a cell-editor (mode='scout.FormField.MODE_CELLEDITOR'), and once the editor finished its rendering.
- */
-scout.SmartFieldButton.prototype.onCellEditorRendered = function(options) {
-  if (options.openFieldPopup) {
-    this._onClick();
-  }
-};
-
-scout.SmartFieldButton.prototype._renderProposalChooser = function() {};
-
-/**
- * This method is called after a valid option has been selected in the proposal chooser.
- */
-scout.SmartFieldButton.prototype._removeProposalChooser = function() {};
-
-scout.SmartFieldButton.prototype._onClick = function(e) {
-  if (!this._popup.rendered) {
-    this._popup.open();
-  }
-};
-
-/**
- * Returns the bounds of the text-input element. Subclasses may override this method when their
- * text-field is not === this.$field.
- */
-scout.SmartFieldButton.prototype._fieldBounds = function() {
-  return scout.graphics.offsetBounds(this.$field);
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldMultiline.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldMultiline.js
index 2752a63..64417e5 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldMultiline.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldMultiline.js
@@ -47,8 +47,8 @@
 /**
  * @override ValueField.js
  */
-scout.SmartFieldMultiline.prototype._renderDisplayText = function(displayText) {
-  var tmp = displayText.split('\n'),
+scout.SmartFieldMultiline.prototype._renderDisplayText = function() {
+  var tmp = this.displayText.split('\n'),
     firstLine = tmp.shift(),
     additionalLines = scout.arrays.formatEncoded(tmp, '<br/>');
   scout.fields.valOrText(this, this.$field, firstLine);
@@ -71,7 +71,7 @@
  *
  * @override SmartField.js
  */
-scout.SmartFieldMultiline.prototype._readSearchText = function() {
+scout.SmartFieldMultiline.prototype._readDisplayText = function() {
   var i,
     firstLine = scout.fields.valOrText(this, this.$field),
     newDisplayText = [firstLine],
@@ -81,3 +81,11 @@
   }
   return newDisplayText.join('\n');
 };
+
+/**
+ * @override SmartField.js
+ */
+scout.SmartFieldMultiline.prototype._readSearchText = function() {
+  // Only read the first line
+  return scout.fields.valOrText(this, this.$field);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldPopup.js
index d8880df..b89496a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldPopup.js
@@ -41,20 +41,6 @@
 };
 
 /**
- * @override Popup.js
- */
-scout.SmartFieldPopup.prototype._onMouseDown = function(event) {
-  // when user clicks on SmartField input-field, cannot prevent default
-  // because text-selection would not work anymore
-  if (this.$anchor.isOrHas(event.target)) {
-    return;
-  }
-
-  // or else: clicked somewhere else on the document -> close
-  scout.SmartFieldPopup.parent.prototype._onMouseDown.call(this, event);
-};
-
-/**
  * This event handler is called before the mousedown handler on the _document_ is triggered
  * This allows us to prevent the default, which is important for the CellEditorPopup which
  * should stay open when the SmartField popup is closed. It also prevents the focus blur
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldTouchPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldTouchPopup.js
index a37683e..0d14bd9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldTouchPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/smartfield/SmartFieldTouchPopup.js
@@ -13,51 +13,39 @@
 };
 scout.inherits(scout.SmartFieldTouchPopup, scout.TouchPopup);
 
-scout.SmartFieldTouchPopup.prototype._postRender = function() {
-  scout.SmartFieldTouchPopup.parent.prototype._postRender.call(this);
-  this._field._openProposal(true);
+scout.SmartFieldTouchPopup.prototype._init = function(options) {
+  scout.DatePickerTouchPopup.parent.prototype._init.call(this, options);
+  this._field.on('acceptProposal', this._onFieldAcceptOrDeleteProposal.bind(this));
+  this._field.on('deleteProposal', this._onFieldAcceptOrDeleteProposal.bind(this));
+};
+
+scout.SmartFieldTouchPopup.prototype._fieldOverrides = function() {
+  var obj = scout.SmartFieldTouchPopup.parent.prototype._fieldOverrides.call(this);
+  // Make sure proposal chooser does not get cloned, because it would not work (e.g. because selectedRows may not be cloned)
+  // It would also generate a loop because field would try to render the chooser and the popup
+  // -> The original smart field has to control the chooser
+  obj.proposalChooser = null;
+  return obj;
 };
 
 scout.SmartFieldTouchPopup.prototype._renderProposalChooser = function(proposalChooser) {
   proposalChooser.render(this._$widgetContainer);
   proposalChooser.setParent(this);
-  this._widgetContainerHtmlComp.revalidateLayout();
+  proposalChooser.$container.addClass('touch');
+  this._widgetContainerHtmlComp.invalidateLayoutTree();
 };
 
 /**
  * @override Popup.js
  */
-scout.SmartFieldTouchPopup.prototype._onMouseDown = function(event) {
-  // when user clicks on SmartField input-field, cannot prevent default
-  // because text-selection would not work anymore
-  if (this.$anchor.isOrHas(event.target)) {
-    return;
-  }
-
-  // or else: clicked somewhere else on the document -> close
-  scout.SmartFieldTouchPopup.parent.prototype._onMouseDown.call(this, event);
+scout.SmartFieldTouchPopup.prototype._onMouseDownOutside = function(event) {
+  // Sync display text first because accept input needs the correct display text
+  this._touchField.setDisplayText(this._field.displayText);
+  this._touchField.acceptInput();
+  this.close();
 };
 
-/**
- * This event handler is called before the mousedown handler on the _document_ is triggered
- * This allows us to prevent the default, which is important for the CellEditorPopup which
- * should stay open when the SmartField popup is closed. It also prevents the focus blur
- * event on the SmartField input-field.
- */
-//TODO [5.2] cgu, awe: this is not required by the cell editor anymore, but we cannot remove it either because mouse down on a row would immediately close the popup, why?
-scout.SmartFieldTouchPopup.prototype._onContainerMouseDown = function(event) {
-  // when user clicks on proposal popup with table or tree (prevent default,
-  // so input-field does not lose the focus, popup will be closed by the
-  // proposal chooser impl.
-  //  return false;
-  // FIXME awe: (popups) durch das prevent default here, wird verhindert, dass ein text-field im popup den fokus bekommen kann
-  // müssen wir für mobile und editierbare tabellen (?) noch lösen
-};
-
-/**
- * @override Popup.js
- */
-scout.SmartFieldTouchPopup.prototype.close = function(event) {
-  this._field._sendCancelProposal();
-  scout.SmartFieldTouchPopup.parent.prototype.close.call(this);
+scout.SmartFieldTouchPopup.prototype._onFieldAcceptOrDeleteProposal = function(event) {
+  // Delegate to original field
+  this._touchField.setDisplayText(event.displayText);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.css
index 1344b5f..fd3afc4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.css
@@ -19,6 +19,10 @@
     & > .first-field,
     & > .second-field {
       overflow: hidden;
+
+      &.collapsed {
+        display: none;
+      }
     }
 
     & > .splitter {
@@ -88,3 +92,8 @@
     }
   }
 }
+
+.split-box-collapse-key-box {
+  margin-top: -6px;
+  margin-left: 4px;
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.js
index dfccd03..76cb8b9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBox.js
@@ -11,7 +11,8 @@
 scout.SplitBox = function() {
   scout.SplitBox.parent.call(this);
   this.splitHorizontal; // true = split x-axis, false = split y-axis
-  this._addAdapterProperties(['firstField', 'secondField']);
+  this._addAdapterProperties(['firstField', 'secondField', 'collapsibleField']);
+  this._collapseKeyStroke;
 
   this._$splitArea;
   this._$splitter;
@@ -22,6 +23,12 @@
 scout.SplitBox.SPLITTER_POSITION_TYPE_ABSOLUTE_FIRST = 'absoluteFirst';
 scout.SplitBox.SPLITTER_POSITION_TYPE_ABSOLUTE_SECOND = 'absoluteSecond';
 
+scout.SplitBox.prototype._init = function(model) {
+  scout.SplitBox.parent.prototype._init.call(this, model);
+  this._updateCollapseHandle();
+  this._syncCollapseKeyStroke(this.collapseKeyStroke);
+};
+
 scout.SplitBox.prototype._render = function($parent) {
   this.addContainer($parent, 'split-box');
   // This widget does not support label, mandatoryIndicator and status
@@ -191,6 +198,8 @@
   scout.SplitBox.parent.prototype._renderProperties.call(this);
   this._renderSplitterPosition();
   this._renderSplitterEnabled();
+  this._renderCollapsibleField(); // renders collapsibleField _and_ fieldCollapsed
+  this._renderCollapseHandle(); // renders collapseHandle _and_ collapseKeyStroke
 };
 
 scout.SplitBox.prototype._syncSplitterPosition = function(splitterPosition) {
@@ -262,6 +271,94 @@
   }
 };
 
+scout.SplitBox.prototype.setFieldCollapsed = function(collapsed) {
+  if (this.fieldCollapsed === collapsed) {
+    return;
+  }
+  this._setProperty('fieldCollapsed', collapsed);
+  this._sendProperty('fieldCollapsed');
+  this._updateCollapseHandleButtons();
+  if (this.rendered) {
+    this._renderFieldCollapsed();
+  }
+};
+
+scout.SplitBox.prototype._renderFieldCollapsed = function() {
+  this._renderCollapsibleField();
+};
+
+scout.SplitBox.prototype.setCollapsibleField = function(field) {
+  if (this.collapsibleField === field) {
+    return;
+  }
+  this._setProperty('collapsibleField', field);
+  this._sendProperty('collapsibleField');
+  this._updateCollapseHandle();
+  if (this.rendered) {
+    this._renderCollapsibleField();
+  }
+};
+
+scout.SplitBox.prototype._updateCollapseHandle = function() {
+  if (this.collapsibleField) {
+    if (!this._collapseHandle) {
+      this._collapseHandle = scout.create('CollapseHandle', {
+        parent: this
+      });
+      this._collapseHandle.on('action', this.toggleFieldCollapsed.bind(this));
+    }
+    this._updateCollapseHandleButtons();
+  } else {
+     if (this._collapseHandle) {
+       this._collapseHandle.remove();
+       this._collapseHandle = null;
+     }
+  }
+};
+
+scout.SplitBox.prototype._updateCollapseHandleButtons = function() {
+  var leftVisible, rightVisible,
+    collapsed = this.fieldCollapsed;
+  if (this.collapsibleField === this.firstField) {
+    leftVisible  = !collapsed;
+    rightVisible =  collapsed;
+  } else {
+    leftVisible  =  collapsed;
+    rightVisible = !collapsed;
+  }
+  this._collapseHandle.setLeftVisible(leftVisible);
+  this._collapseHandle.setRightVisible(rightVisible);
+};
+
+scout.SplitBox.prototype._renderCollapsibleField = function() {
+  if (this.firstField) {
+    this.firstField.$container.removeClass('collapsed');
+  }
+  if (this.secondField) {
+    this.secondField.$container.removeClass('collapsed');
+  }
+  if (this.collapsibleField && this.fieldCollapsed) {
+    this.collapsibleField.$container.addClass('collapsed');
+  }
+  if (this.rendered) { // don't invalidate layout on initial rendering
+    this.htmlSplitArea.invalidateLayoutTree(false);
+  }
+};
+
+scout.SplitBox.prototype._syncCollapseKeyStroke = function(keyStroke) {
+  if (keyStroke) {
+    this.collapseKeyStroke = new scout.SplitBoxCollapseKeyStroke(this, keyStroke);
+    this.registerKeyStrokes(this.collapseKeyStroke);
+  }
+  return false;
+};
+
+scout.SplitBox.prototype._renderCollapseHandle = function() {
+  if (this._collapseHandle) {
+    this._collapseHandle.render(this.$container);
+  }
+};
+
 scout.SplitBox.prototype.newSplitterPosition = function(newSplitterPosition) {
   if (this.splitterPositionType === scout.SplitBox.SPLITTER_POSITION_TYPE_RELATIVE) {
     // Ensure range 0..1
@@ -284,6 +381,10 @@
   this.htmlSplitArea.invalidateLayoutTree(false);
 };
 
+scout.SplitBox.prototype.toggleFieldCollapsed = function() {
+  this.setFieldCollapsed(!this.fieldCollapsed);
+};
+
 /**
  * @override CompositeField.js
  */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxCollapseKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxCollapseKeyStroke.js
new file mode 100644
index 0000000..4a75c2d
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxCollapseKeyStroke.js
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SplitBoxCollapseKeyStroke = function(splitBox, keyStroke) {
+  scout.SplitBoxCollapseKeyStroke.parent.call(this);
+  this.field = splitBox;
+  this.parseAndSetKeyStroke(keyStroke);
+};
+scout.inherits(scout.SplitBoxCollapseKeyStroke, scout.KeyStroke);
+
+scout.SplitBoxCollapseKeyStroke.prototype.handle = function(event) {
+  this.field.toggleFieldCollapsed();
+};
+
+scout.SplitBoxCollapseKeyStroke.prototype._postRenderKeyBox = function($drawingArea, $keyBox) {
+  var handleOffset,
+    $collapseHandle = this.field._collapseHandle.$container;
+
+  $keyBox.addClass('split-box-collapse-key-box');
+  handleOffset = $collapseHandle.offsetTo(this.field.$container);
+  $keyBox
+    .cssLeft(handleOffset.left - $keyBox.outerWidth())
+    .cssTop(handleOffset.top);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxLayout.js
index 67ab6e3..13b452a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/splitbox/SplitBoxLayout.js
@@ -20,29 +20,40 @@
     $splitter = $container.children('.splitter'),
     $fields = $container.children('.form-field'),
     htmlFirstField = scout.HtmlComponent.optGet($fields.eq(0)),
-    htmlSecondField = scout.HtmlComponent.optGet($fields.eq(1));
+    htmlSecondField = scout.HtmlComponent.optGet($fields.eq(1)),
+    // Calculate available size for split area
+    splitXAxis = this._splitBox.splitHorizontal;
 
-  // Calculate available size for split area
-  var splitXAxis = this._splitBox.splitHorizontal;
   $splitter.removeClass('hidden');
-  var splitterSize = scout.graphics.getVisibleSize($splitter, true);
-  var availableSize = htmlContainer.getAvailableSize()
-    .subtract(htmlContainer.getInsets());
-  if (splitXAxis) { // "|"
-    availableSize.width -= splitterSize.width;
-  } else { // "--"
-    availableSize.height -= splitterSize.height;
+
+  var firstFieldSize, secondFieldSize, firstFieldBounds, secondFieldBounds,
+    splitterSize = scout.graphics.getVisibleSize($splitter, true),
+    availableSize = htmlContainer
+      .getAvailableSize()
+      .subtract(htmlContainer.getInsets()),
+
+    hasFirstField = (htmlFirstField && htmlFirstField.isVisible()),
+    hasSecondField = (htmlSecondField && htmlSecondField.isVisible()),
+    hasTwoFields = hasFirstField && hasSecondField,
+    hasOneField = !hasTwoFields && (hasFirstField || hasSecondField),
+    splitterPosition = this._splitBox.splitterPosition;
+
+  // remove splitter size from available with, only when both fields are visible
+  // otherwise the splitter is invisible and requires no space.
+  var availableSizeForFields = new scout.Dimension(availableSize);
+  if (hasTwoFields) {
+    if (splitXAxis) { // "|"
+      availableSizeForFields.width -= splitterSize.width;
+    } else { // "--"
+      availableSizeForFields.height -= splitterSize.height;
+    }
   }
 
-  var hasFirstField = (htmlFirstField && htmlFirstField.isVisible());
-  var hasSecondField = (htmlSecondField && htmlSecondField.isVisible());
-  var splitterPosition = this._splitBox.splitterPosition;
-
   // Default case: two fields
-  if (hasFirstField && hasSecondField) {
+  if (hasTwoFields) {
     // Distribute available size to the two fields according to the splitter position ratio
-    var firstFieldSize = new scout.Dimension(availableSize);
-    var secondFieldSize = new scout.Dimension(availableSize);
+    firstFieldSize = new scout.Dimension(availableSizeForFields);
+    secondFieldSize = new scout.Dimension(availableSizeForFields);
     if (splitXAxis) { // "|"
       if (this._splitBox.splitterPositionType === scout.SplitBox.SPLITTER_POSITION_TYPE_RELATIVE) {
         // Relative
@@ -50,13 +61,13 @@
         secondFieldSize.width *= (1 - splitterPosition);
       } else {
         // Absolute
-        splitterPosition = Math.min(splitterPosition, availableSize.width);
+        splitterPosition = Math.min(splitterPosition, availableSizeForFields.width);
         if (this._splitBox.splitterPositionType === scout.SplitBox.SPLITTER_POSITION_TYPE_ABSOLUTE_SECOND) {
-          firstFieldSize.width = availableSize.width - splitterPosition;
+          firstFieldSize.width = availableSizeForFields.width - splitterPosition;
           secondFieldSize.width = splitterPosition;
         } else {
           firstFieldSize.width = splitterPosition;
-          secondFieldSize.width = availableSize.width - splitterPosition;
+          secondFieldSize.width = availableSizeForFields.width - splitterPosition;
         }
       }
     } else { // "--"
@@ -66,13 +77,13 @@
         secondFieldSize.height *= (1 - splitterPosition);
       } else {
         // Absolute
-        splitterPosition = Math.min(splitterPosition, availableSize.height);
+        splitterPosition = Math.min(splitterPosition, availableSizeForFields.height);
         if (this._splitBox.splitterPositionType === scout.SplitBox.SPLITTER_POSITION_TYPE_ABSOLUTE_SECOND) {
-          firstFieldSize.height = availableSize.height - splitterPosition;
+          firstFieldSize.height = availableSizeForFields.height - splitterPosition;
           secondFieldSize.height = splitterPosition;
         } else {
           firstFieldSize.height = splitterPosition;
-          secondFieldSize.height = availableSize.height - splitterPosition;
+          secondFieldSize.height = availableSizeForFields.height - splitterPosition;
         }
       }
     }
@@ -80,8 +91,8 @@
     secondFieldSize = secondFieldSize.subtract(htmlSecondField.getMargins());
 
     // Calculate and set bounds (splitter and second field have to be moved)
-    var firstFieldBounds = new scout.Rectangle(0, 0, firstFieldSize.width, firstFieldSize.height);
-    var secondFieldBounds = new scout.Rectangle(0, 0, secondFieldSize.width, secondFieldSize.height);
+    firstFieldBounds = new scout.Rectangle(0, 0, firstFieldSize.width, firstFieldSize.height);
+    secondFieldBounds = new scout.Rectangle(0, 0, secondFieldSize.width, secondFieldSize.height);
     if (splitXAxis) { // "|"
       $splitter.cssLeft(firstFieldBounds.width);
       secondFieldBounds.x = firstFieldBounds.width + splitterSize.width;
@@ -94,12 +105,33 @@
   }
   // Special case: only one field (or none at all)
   else {
-    if (hasFirstField || hasSecondField) {
-      var oneFieldOnlySize = availableSize.subtract(htmlFirstField.getMargins());
-      (hasFirstField ? htmlFirstField : htmlSecondField).setSize(oneFieldOnlySize);
+    if (hasOneField) {
+      var singleField = hasFirstField ? htmlFirstField : htmlSecondField,
+        singleFieldSize = availableSize.subtract(singleField.getMargins());
+      singleField.setBounds(new scout.Rectangle(0, 0, singleFieldSize.width, singleFieldSize.height));
     }
     $splitter.addClass('hidden');
   }
+
+  // Calculate collapse button position
+  if (this._splitBox._collapseHandle) {
+
+    // Horizontal layout:
+    // - if 1st field is collapsible -> align button on the right side of the field
+    // - if 2nd field is collapsible -> align button on the left side of the field
+    var x,
+      $collapseHandle = this._splitBox._collapseHandle.$container,
+      collapseHandleSize = scout.graphics.getSize($collapseHandle);
+
+    if (this._splitBox.collapsibleField === this._splitBox.firstField) {
+      x = hasFirstField ? firstFieldBounds.width - collapseHandleSize.width : 0;
+    } else { // secondField
+      x = hasSecondField ? availableSize.width - secondFieldBounds.width : availableSize.width - collapseHandleSize.width;
+    }
+
+    var collapseHandleLocation = new scout.Point(x, availableSize.height - collapseHandleSize.height);
+    scout.graphics.setLocation($collapseHandle, collapseHandleLocation);
+  }
 };
 
 scout.SplitBoxLayout.prototype.preferredLayoutSize = function($container) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/stringfield/StringField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/stringfield/StringField.js
index e1f90ca..5cf7cf1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/stringfield/StringField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/stringfield/StringField.js
@@ -161,7 +161,7 @@
   if (decorationLink) {
     this.$container.addClass("has-action");
     this.addIcon();
-    this.revalidateLayout();
+    this.invalidateLayoutTree(false);
   } else {
     if (this.$icon) {
       this.$icon.remove();
@@ -178,19 +178,19 @@
   }
 };
 
-scout.StringField.prototype._renderSpellCheckEnabled = function(spellCheckEnabled) {
-  if (spellCheckEnabled) {
+scout.StringField.prototype._renderSpellCheckEnabled = function() {
+  if (this.spellCheckEnabled) {
     this.$field.attr('spellcheck', 'true');
   } else {
     this.$field.attr('spellcheck', 'false');
   }
 };
 
-scout.StringField.prototype._renderDisplayText = function(displayText) {
-  displayText = scout.strings.nvl(displayText);
+scout.StringField.prototype._renderDisplayText = function() {
+  var displayText = scout.strings.nvl(this.displayText);
   var oldDisplayText = scout.strings.nvl(this.$field.val());
   var oldSelection = this._getSelection();
-  scout.StringField.parent.prototype._renderDisplayText.call(this, displayText);
+  scout.StringField.parent.prototype._renderDisplayText.call(this);
   // Try to keep the current selection for cases where the old and new display
   // text only differ because of the automatic trimming.
   if (this.trimText && oldDisplayText !== displayText) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabAreaLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabAreaLayout.js
index 43cfe5b..428af59 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabAreaLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabAreaLayout.js
@@ -23,12 +23,25 @@
   var bounds,
     tabArea = $container[0],
     clientWidth = tabArea.clientWidth,
-    scrollWidth = tabArea.scrollWidth;
+    scrollWidth = tabArea.scrollWidth,
+    menuBar = this._tabBox.menuBar,
+    $status = this._tabBox.$status,
+    statusWidth = 0,
+    statusPosition = this._tabBox.statusPosition;
 
   // If tab area contains a menubar, less space is available
-  var menubar = $container.children('.menubar')[0];
-  if (menubar) {
-    clientWidth -= menubar.clientWidth;
+  clientWidth -= menuBar.$container[0].clientWidth;
+
+  if (statusPosition === scout.FormField.STATUS_POSITION_TOP) {
+    // Status on top means it is inside the tab area
+    if ($status && $status.isVisible()) {
+      statusWidth = $status.outerWidth(true);
+    }
+    if (statusWidth > 0) {
+      clientWidth -= statusWidth;
+      // Status is on the right of the menuBar
+      menuBar.$container.cssRight(statusWidth);
+    }
   }
 
   this._overflowTabs = [];
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.css
index 3aae9a3..b5ff6d7 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.css
@@ -24,85 +24,6 @@
   white-space: nowrap;
   position: relative;
 
-  & > .tab-item {
-    position: relative;
-    display: inline-block;
-    vertical-align: middle;
-    #scout.font-text-normal(@font-weight-bold);
-    color: @title-color;
-    border: none;
-    background-color: transparent;
-    padding: 0 @tabbox-padding-x;
-    border-bottom: solid @tabbox-border-width transparent;
-    cursor: pointer;
-
-    &.selected {
-      color: @active-color;
-      border-bottom-color: @active-color;
-    }
-
-    &.marked:not(.selected) {
-      border-bottom-color: @palette-gray-6;
-    }
-
-    &:hover {
-      color: @hover-color;
-    }
-
-    &:focus {
-      outline: none;
-    }
-
-    &:focus::before {
-      #scout.font-icon();
-      content: @icon-angle-right;
-      color: @active-color;
-      position: absolute;
-      top: @group-title-padding-y;
-      left: @tabbox-padding-x - @tabbox-focus-arrow-width;
-      width: @tabbox-focus-arrow-width;
-      text-align: center;
-    }
-
-    & > .label {
-      padding: @group-title-padding-y 0;
-      display: inline-block;
-      vertical-align: middle;
-    }
-
-    & > .status {
-      margin-left: @field-status-margin-left;
-      padding: 4px 0;
-      display: inline-block;
-      vertical-align: middle;
-
-      #scout.status();
-    }
-
-    &.has-tooltip,
-    &.has-info,
-    &.has-warning,
-    &.has-error {
-      padding-right: @field-status-margin-left;
-    }
-
-    &.has-tooltip > .status {
-      #scout.tooltip-status();
-    }
-
-    &.has-info > .status {
-      #scout.info-status();
-    }
-
-    &.has-warning > .status {
-      #scout.warning-status();
-    }
-
-    &.has-error > .status {
-      #scout.error-status();
-    }
-  }
-
   &::after {
     width: 100%;
     height: @tabbox-border-width;
@@ -112,23 +33,6 @@
     display: block;
   }
 
-  & > .overflow-tab-item {
-    position: relative;
-    display: inline-block;
-    text-align: center;
-    cursor: pointer;
-    padding: 0px 0px;
-
-    &::before {
-      #scout.font-icon();
-      position: relative;
-      bottom: -2px;
-      font-size: 17px;
-      color: @icon-color;
-      content: @icon-ellipsis-v;
-    }
-  }
-
   & > .menubar {
     position: absolute;
     right: 0;
@@ -154,4 +58,126 @@
       }
     }
   }
+
+  & > .status {
+    position: absolute;
+    margin-left: @field-status-margin-left;
+    #scout.status();
+    border-bottom: @tabbox-border-width solid transparent;
+  }
+
+  .tab-box.has-tooltip > & > .status {
+    #scout.tooltip-status();
+  }
+
+  .tab-box.has-info > & > .status {
+    #scout.info-status();
+  }
+
+  .tab-box.has-warning > & > .status {
+    #scout.warning-status();
+  }
+
+  .tab-box.has-error > & > .status {
+    #scout.error-status();
+  }
+}
+
+.tab-item {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  #scout.font-text-normal(@font-weight-bold);
+  color: @title-color;
+  border: none;
+  background-color: transparent;
+  padding: 0 @tabbox-padding-x;
+  border-bottom: solid @tabbox-border-width transparent;
+  cursor: pointer;
+
+  &.selected {
+    color: @active-color;
+    border-bottom-color: @active-color;
+  }
+
+  &.marked:not(.selected) {
+    border-bottom-color: @palette-gray-6;
+  }
+
+  &:hover {
+    color: @hover-color;
+  }
+
+  &:active {
+    color: @active-color;
+  }
+
+  &:focus {
+    outline: none;
+  }
+
+  &:focus::before {
+    #scout.font-icon();
+    content: @icon-angle-right;
+    color: @active-color;
+    position: absolute;
+    top: @group-title-padding-y;
+    left: @tabbox-padding-x - @tabbox-focus-arrow-width;
+    width: @tabbox-focus-arrow-width;
+    text-align: center;
+  }
+
+  & > .label {
+    padding: @group-title-padding-y 0;
+    display: inline-block;
+    vertical-align: middle;
+  }
+
+  & > .status {
+    margin-left: @field-status-margin-left;
+    padding: 4px 0;
+    display: inline-block;
+    vertical-align: middle;
+    #scout.status();
+  }
+
+  &.has-tooltip,
+  &.has-info,
+  &.has-warning,
+  &.has-error {
+    padding-right: @field-status-margin-left;
+  }
+
+  &.has-tooltip > .status {
+    #scout.tooltip-status();
+  }
+
+  &.has-info > .status {
+    #scout.info-status();
+  }
+
+  &.has-warning > .status {
+    #scout.warning-status();
+  }
+
+  &.has-error > .status {
+    #scout.error-status();
+  }
+}
+
+.overflow-tab-item {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  text-align: center;
+  cursor: pointer;
+  padding: 0px 0px;
+
+  &::before {
+    #scout.font-icon();
+    position: relative;
+    font-size: 17px;
+    color: @icon-color;
+    content: @icon-ellipsis-v;
+  }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.js
index e5e33fd..9a9882e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBox.js
@@ -31,6 +31,7 @@
     parent: this,
     menuOrder: new scout.GroupBoxMenuItemsOrder()
   });
+  this._updateMenuBar(this.menus);
 };
 
 scout.TabBox.prototype._render = function($parent) {
@@ -57,7 +58,6 @@
   scout.TabBox.parent.prototype._renderProperties.call(this);
   this._renderTabs();
   this._renderTabContent();
-  this._renderMenus();
 };
 
 /**
@@ -205,21 +205,41 @@
     // I decided to simplify this and always set the title of the first group-box
     // to invisible.
     selectedTabItem.render(this._$tabContent);
-    selectedTabItem._renderLabelVisible(false);
   }
   if (this.rendered) {
     scout.HtmlComponent.get(this._$tabContent).revalidateLayoutTree();
   }
 };
 
-scout.TabBox.prototype._renderMenus = function() {
-  this.updateMenuBar();
-  // TODO [5.2] bsh: Key strokes?
+scout.TabBox.prototype._syncMenus = function(menus, oldMenus) {
+  scout.TabBox.parent.prototype._syncMenus.call(this, menus, oldMenus);
+  if (this.menuBar) {
+    // updateMenuBar is required because menuBar is not created yet when synMenus is called initially
+    this._updateMenuBar(menus, oldMenus);
+  }
 };
 
-scout.TabBox.prototype.updateMenuBar = function() {
+scout.TabBox.prototype._renderMenus = function() {
+  // NOP
+};
+
+scout.TabBox.prototype._removeMenus = function() {
+  // menubar takes care about removal
+};
+
+scout.TabBox.prototype._updateMenuBar = function(menus, oldMenus) {
   var menuItems = scout.menus.filter(this.menus, ['TabBox.Header']);
-  this.menuBar.updateItems(menuItems);
+  this.menuBar.setMenuItems(menuItems);
+};
+
+scout.TabBox.prototype._renderStatusPosition = function() {
+  if (this.statusPosition === scout.FormField.STATUS_POSITION_TOP) {
+    // move into title
+    this.$status.appendTo(this._$tabArea);
+  } else {
+    this.$status.appendTo(this.$container);
+  }
+  this.invalidateLayoutTree();
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBoxLayout.js
index 34d9044..6facfca 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabBoxLayout.js
@@ -23,7 +23,8 @@
     tabAreaWidth = 0,
     tabAreaHeight = 0,
     tabAreaSize = new scout.Dimension(),
-    $status = this._tabBox.$status;
+    $status = this._tabBox.$status,
+    statusPosition = this._tabBox.statusPosition;
 
   containerSize = htmlContainer.getAvailableSize()
     .subtract(htmlContainer.getInsets());
@@ -34,7 +35,9 @@
     tabAreaWidth = containerSize.subtract(tabAreaMargins).width;
     if ($status && $status.isVisible()) {
       this._layoutStatus();
-      tabAreaWidth -= $status.outerWidth(true);
+      if (statusPosition === scout.FormField.STATUS_POSITION_DEFAULT) {
+        tabAreaWidth -= $status.outerWidth(true);
+      }
     }
     innerTabAreaSize = new scout.Dimension(tabAreaWidth, tabAreaHeight);
     htmlTabArea.setSize(innerTabAreaSize);
@@ -56,13 +59,22 @@
     $tabArea = this._tabBox._$tabArea,
     tabAreaInnerHeight = $tabArea.innerHeight(),
     $status = this._tabBox.$status,
-    statusMargins = scout.graphics.getMargins($status);
+    statusMargins = scout.graphics.getMargins($status),
+    statusTop = top,
+    statusPosition = this._tabBox.statusPosition,
+    statusHeight = tabAreaInnerHeight - statusMargins.vertical();
+
+  if (statusPosition === scout.FormField.STATUS_POSITION_DEFAULT) {
+    statusTop += $tabArea.cssMarginTop();
+  } else {
+    statusHeight -= $status.cssBorderWidthY(); // status has a transparent border to align icon with text
+  }
 
   $status.cssWidth(this._statusWidth)
-    .cssTop(top + $tabArea.cssMarginTop())
+    .cssTop(statusTop)
     .cssRight(right)
-    .cssHeight(tabAreaInnerHeight - statusMargins.vertical())
-    .cssLineHeight(tabAreaInnerHeight - statusMargins.vertical());
+    .cssHeight(statusHeight)
+    .cssLineHeight(statusHeight);
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabItem.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabItem.js
index f3c3f8f..ae9e6ae 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabItem.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/tabbox/TabItem.js
@@ -46,6 +46,7 @@
   this.$tabContainer = $parent.appendDiv('tab-item')
     .data('tabItem', this)
     .on('mousedown', this._onTabMouseDown.bind(this));
+  this.tabHtmlComp = new scout.HtmlComponent(this.$tabContainer, this.session);
 
   this.addLabel();
   this.addStatus();
@@ -59,9 +60,6 @@
 };
 
 scout.TabItem.prototype._onTabMouseDown = function(event) {
-  if (event && event.originalEvent) {
-    event.originalEvent.scoutOriginalTargetWidget = this;
-  }
   if (this._preventTabActivation) {
     this._preventTabActivation = false;
     return;
@@ -164,6 +162,11 @@
   this.$label.textOrNbsp(scout.strings.removeAmpersand(this.label));
 };
 
+scout.TabItem.prototype._renderLabelVisible = function() {
+  // Never make the title of the group box visible -> label is rendered into tabContainer
+  scout.TabItem.parent.prototype._renderLabelVisible.call(this, false);
+};
+
 scout.TabItem.prototype.addLabel = function() {
   if (this.$label) {
     return;
@@ -215,6 +218,15 @@
   }
 };
 
+scout.TabItem.prototype._renderStatusVisible = function() {
+  var wasVisible = this.$status.isVisible();
+  scout.TabItem.parent.prototype._renderStatusVisible.call(this);
+  if (this.rendered && wasVisible !== this._computeStatusVisible()) {
+    // Make sure tab area gets re layouted on status visibility changes, it may necessary to show ellipsis now if status got visible
+    this.tabHtmlComp.invalidateLayoutTree();
+  }
+};
+
 scout.TabItem.prototype._syncMenusVisible = function() {
   // Always invisible because menus are displayed in menu bar and not with status icon
   // Actually not needed at the moment because only value fields have menus (at least at the java model).
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wizard/WizardProgressField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wizard/WizardProgressField.js
index 78c85df..f9c1f01 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wizard/WizardProgressField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wizard/WizardProgressField.js
@@ -80,10 +80,6 @@
         position: 'bottom'
       });
     }
-    scout.FormField.prototype._renderCssClass = function(cssClass, oldCssClass) {
-      this.$container.removeClass(oldCssClass);
-      this.$container.addClass(cssClass);
-    };
     this._updateStepClasses(step);
 
     // Inspector info
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wrappedform/WrappedFormField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wrappedform/WrappedFormField.js
index 8063318..d710f3a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wrappedform/WrappedFormField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/wrappedform/WrappedFormField.js
@@ -29,15 +29,26 @@
  * Will also be called by model adapter on property change event
  */
 scout.WrappedFormField.prototype._renderInnerForm = function() {
-  if (this.innerForm) {
-    this.innerForm.displayHint = scout.Form.DisplayHint.VIEW; // by definition, an inner form is a view.
-    this.innerForm.modal = false; // by definition, an inner form is not modal.
-    this.innerForm.renderInitialFocusEnabled = false; // do not render initial focus of form
+  if (!this.innerForm) {
+    return;
+  }
 
-    this.innerForm.render(this.$container);
+  this.innerForm.displayHint = scout.Form.DisplayHint.VIEW; // by definition, an inner form is a view.
+  this.innerForm.modal = false; // by definition, an inner form is not modal.
+  this.innerForm.renderInitialFocusEnabled = this.initialFocusEnabled; // do not render initial focus of form if disabled.
 
-    this.addField(this.innerForm.$container);
-    this.innerForm.invalidateLayoutTree();
+  this.innerForm.render(this.$container);
+
+  this.addField(this.innerForm.$container);
+  this.innerForm.invalidateLayoutTree();
+
+  // required because active element is lost when 'addField' is called.
+  this._renderInitialFocusEnabled();
+};
+
+scout.WrappedFormField.prototype._renderInitialFocusEnabled = function() {
+  if (this.innerForm && this.initialFocusEnabled) {
+    this.innerForm.renderInitialFocus();
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/DeferredGlassPaneTarget.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/glasspane/DeferredGlassPaneTarget.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/DeferredGlassPaneTarget.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/glasspane/DeferredGlassPaneTarget.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/GlassPaneRenderer.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/glasspane/GlassPaneRenderer.js
similarity index 95%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/GlassPaneRenderer.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/glasspane/GlassPaneRenderer.js
index aa0fcef..e9a1ae2 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/GlassPaneRenderer.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/glasspane/GlassPaneRenderer.js
@@ -105,7 +105,8 @@
   if (this._element instanceof scout.Form && this._element.isView()) {
     // If the blocking element is a view, the $container cannot be animated (this only works for dialogs). Instead,
     // highlight the view tab (or the overflow item, if the view tab is not visible).
-    $animationTarget = this.session.desktop.viewTabsController.viewTab(this._element).$container;
+
+    $animationTarget = this.session.desktop.bench.getViewTab(this._element).$container;
     if (!$animationTarget.isVisible()) {
       $animationTarget = $animationTarget.siblings('.overflow-tab-item');
     }
@@ -116,8 +117,7 @@
   if ($animationTarget) {
     $animationTarget.addClassForAnimation('modality-highlight', {
       // remove shown as well, user may click the glasspane before the widget itself was able to remove the shown class
-      classesToRemove: 'modality-highlight shown',
-      delay: 500
+      classesToRemove: 'modality-highlight shown'
     });
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStroke.js
index c5342ed..a79b336 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStroke.js
@@ -170,14 +170,14 @@
     return null;
   }
 
-  scout.keyStrokeBox.drawSingleKeyBoxItem(
+  var $keyBox = scout.keyStrokeBox.drawSingleKeyBoxItem(
     this.renderingHints.offset,
     this.renderingHints.text || scout.codesToKeys[event.which],
     $drawingArea,
     this.ctrl, this.alt, this.shift,
     this.renderingHints.hAlign === scout.hAlign.RIGHT);
 
-  this._postRenderKeyBox($drawingArea);
+  this._postRenderKeyBox($drawingArea, $keyBox);
   return $drawingArea;
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeContext.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeContext.js
index 23c72ca..6335c57 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeContext.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeContext.js
@@ -105,8 +105,9 @@
     .forEach(function(ks) {
       this.keyStrokes.push(ks);
 
-      // Registers a destroy listener, so that the keystroke is uninstalled once its field (if applicable) is destroyed.
-      if (ks.field && ks.field.events) {
+      // Registers a destroy listener, so that the keystroke is uninstalled once its field (if applicable, only model adapters fire destroy) is destroyed.
+      // TODO CGU Actually it would be better if every widget can be destroyed -> move destroy to Widget.js
+      if (ks.field && ks.field instanceof scout.ModelAdapter) {
         ks.destroyListener = function(event) {
           this.unregisterKeyStroke(ks);
         }.bind(this);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeManager.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeManager.js
index 1968657..1bebf93 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeManager.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeManager.js
@@ -91,7 +91,7 @@
   }
 
   keyStrokeContext._handler.$target.off('keydown', keyStrokeContext._handler);
-  keyStrokeContext._handler.$target.off('up', keyStrokeContext._handler);
+  keyStrokeContext._handler.$target.off('keyup', keyStrokeContext._handler);
   keyStrokeContext._handler.$target = null;
   keyStrokeContext._handler = null;
 };
@@ -169,7 +169,7 @@
     // Handle the keystroke.
     keyStroke.handle(event);
     if (this.session.desktop) { // check that desktop is ready (may be undefined on "Initialization failed" message, would cause an error when the user presses Enter)
-      this.session.desktop._trigger('keystrokeConsumed', {
+      this.session.desktop.trigger('keystrokeConsumed', {
         keyStrokeEvent: event,
         $target: keyStrokeContext.$getBindTarget(),
         keyStroke: keyStroke
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeSupport.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeSupport.js
deleted file mode 100644
index 60fa8cd..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/KeyStrokeSupport.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/**
- * Provides methods to "sync" properties 'keyStrokes' and 'menus' on a model-adapter.
- * This class is basically required because Table, Tree and FormField have no common base-class
- * but all require support for keyStrokes and menus.
- */
-scout.KeyStrokeSupport = function(adapter) {
-  this._adapter = adapter;
-};
-
-scout.KeyStrokeSupport.prototype.syncKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
-  this._updateKeyStrokes(newKeyStrokes, oldKeyStrokes);
-  this._adapter.keyStrokes = newKeyStrokes;
-};
-
-scout.KeyStrokeSupport.prototype.syncMenus = function(newMenus, oldMenus) {
-  this._updateKeyStrokes(newMenus, oldMenus);
-  this._adapter.menus = newMenus;
-};
-
-scout.KeyStrokeSupport.prototype._updateKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
-  // 1st: unregister all old key-strokes
-  if (oldKeyStrokes && Array.isArray(oldKeyStrokes)) {
-    oldKeyStrokes.forEach(function(keyStroke) {
-      this.keyStrokeContext.unregisterKeyStroke(keyStroke);
-    }, this._adapter);
-  }
-  // 2nd: register all new key-strokes
-  if (newKeyStrokes && Array.isArray(newKeyStrokes)) {
-    newKeyStrokes.forEach(function(keyStroke) {
-      this.keyStrokeContext.registerKeyStroke(keyStroke);
-    }, this._adapter);
-  }
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/keybox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keybox.css
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/keybox.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keybox.css
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keys.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keys.js
index 3ce2aa6..a4c04f1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keys.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/keystroke/keys.js
@@ -103,7 +103,8 @@
   OPEN_BRACKET: 219, //'
   BACK_SLASH: 220, //ä
   CLOSE_BRACKET: 221, //^
-  SINGLE_QUOTE: 222 //ö
+  SINGLE_QUOTE: 222, //ö,
+  ANGULAR_BRACKET: 226
 };
 
 scout.codesToKeys = {
@@ -200,7 +201,8 @@
   219: '\'',
   220: 'ä',
   221: '^',
-  222: 'ö'
+  222: 'ö',
+  226: '<'
 };
 
 scout.keyStrokeBox = {
@@ -232,11 +234,11 @@
       keyBoxText = 'Ctrl ' + keyBoxText;
     }
     if ($container.css('position') === 'absolute' || $container.css('position') === 'relative' || ($container.css('position') === 'static' && $existingKeyBoxes.length > 0)) {
-      $container.prependDiv('key-box ', keyBoxText).css(align, '' + offset + 'px');
+      return $container.prependDiv('key-box ', keyBoxText).css(align, '' + offset + 'px');
     } else {
       var pos = $container.position();
       if (pos) {
-        $container.prependDiv('key-box ', keyBoxText).css(align, '' + (pos.left + offset) + 'px');
+        return $container.prependDiv('key-box ', keyBoxText).css(align, '' + (pos.left + offset) + 'px');
       } else {
         $.log.warn('(keys#drawSingleKeyBoxItem) pos is undefined. $container=' + $container);
       }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
index 0e1bf3a..5cd0ed7 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/HtmlComponent.js
@@ -16,7 +16,7 @@
     throw new Error('session must be defined for ' + this.debug());
   }
   this.$comp = $comp;
-  this._layout = new scout.NullLayout();
+  this.layout = new scout.NullLayout();
   this.layoutData;
   this.valid = false;
 
@@ -26,6 +26,11 @@
   this.layouted = false;
 
   /**
+   * May be set to temporarily disable invalidation (e.g. if the component gets modified during the layouting process)
+   */
+  this.suppressInvalidate = false;
+
+  /**
    * Set pixelBasedSizing to false if your component automatically adjusts its size,
    * e.g. by using CSS styling -> setSize won't be called.
    */
@@ -49,6 +54,20 @@
 };
 
 /**
+ * @returns true if the given htmlComponent is an ancestor, false if not
+ */
+scout.HtmlComponent.prototype.isDescendantOf = function(htmlComp) {
+  var $parent = this.$comp.parent();
+  while ($parent.length > 0) {
+    if (scout.HtmlComponent.optGet($parent) === htmlComp) {
+      return true;
+    }
+    $parent = $parent.parent();
+  }
+  return false;
+};
+
+/**
  * Computes the preferred height if the component is scrollable and returns it if it is greater than the actual size.
  * If it is not scrollable, the actual height is returned.<p>
  * The returned width is always the actual width because there are no horizontal scrollbars.
@@ -72,8 +91,8 @@
  */
 scout.HtmlComponent.prototype.invalidateLayout = function() {
   this.valid = false;
-  if (this._layout) {
-    this._layout.invalidate();
+  if (this.layout) {
+    this.layout.invalidate();
   }
 };
 
@@ -82,12 +101,12 @@
  * @exception when component has no layout
  */
 scout.HtmlComponent.prototype.validateLayout = function() {
-  if (!this._layout) {
+  if (!this.layout) {
     throw new Error('Called layout() but component has no layout');
   }
   if (!this.valid) {
     this.layouting = true;
-    this._layout.layout(this.$comp);
+    this.layout.layout(this.$comp);
     this.layouting = false;
     this.layouted = true;
     // Save size for later use (necessary if pixelBasedSizing is set to false)
@@ -108,6 +127,9 @@
  * Invalidates the component-tree up to the next validate root, but only if invalidateParents is set to true.
  */
 scout.HtmlComponent.prototype.invalidateLayoutTree = function(invalidateParents) {
+  if (this.suppressInvalidate) {
+    return;
+  }
   if (scout.nvl(invalidateParents, true)) {
     this.session.layoutValidator.invalidateTree(this); // will call invalidateLayout(), which sets this.valid = false
   } else {
@@ -151,7 +173,7 @@
  * Sets the given layout.
  */
 scout.HtmlComponent.prototype.setLayout = function(layout) {
-  this._layout = layout;
+  this.layout = layout;
 };
 
 /**
@@ -159,8 +181,8 @@
  * @exception When component has no layout
  */
 scout.HtmlComponent.prototype.getPreferredSize = function() {
-  if (this._layout) {
-    var prefSize = this._layout.preferredLayoutSize(this.$comp);
+  if (this.layout) {
+    var prefSize = this.layout.preferredLayoutSize(this.$comp);
     $.log.trace('(HtmlComponent#getPreferredSize) ' + this.debug() + ' preferredSize=' + prefSize);
     return prefSize;
   } else {
@@ -214,6 +236,14 @@
   return scout.graphics.offsetBounds(this.$comp);
 };
 
+/**
+ * Delegation to scout.graphics.setLocation
+ * @param location scout.Point
+ */
+scout.HtmlComponent.prototype.setLocation = function(location) {
+  scout.graphics.setLocation(this.$comp, location);
+};
+
 scout.HtmlComponent.prototype.setBounds = function(bounds) {
   if (!this.isAttachedAndVisible()) {
     // don't invalidate the layout if component is invisible because sizes may not be read correctly and therefore prefSize will be wrong
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LayoutValidator.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LayoutValidator.js
index d065d3a..a144190 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LayoutValidator.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LayoutValidator.js
@@ -10,12 +10,9 @@
  ******************************************************************************/
 scout.LayoutValidator = function() {
   this._invalidComponents = [];
+  this._validateTimeoutId = null;
 };
 
-// FIXME cgu: maybe it is necessary to sort the list so that the top most root is layouted first.
-
-// Testcase: Field in scrollable groupbox gets invisible and also a field outside the groupbox.
-// If scrollable is layouted first it may be relayouted again when the form gets layouted
 scout.LayoutValidator.prototype.invalidateTree = function(htmlComp) {
   var validateRoot,
     htmlCompParent = htmlComp;
@@ -39,9 +36,29 @@
 };
 
 scout.LayoutValidator.prototype.invalidate = function(htmlComp) {
+  var position = 0;
+  // Don't insert if already inserted
+  if (this._invalidComponents.indexOf(htmlComp) >= 0) {
+    return;
+  }
+
+  // Make sure it will be inserted before any descendant
+  // This prevents multiple layouting of the descendant
+  this._invalidComponents.forEach(function(invalidComponent, i) {
+    if (invalidComponent.isDescendantOf(htmlComp)) {
+      return;
+    }
+    position++;
+  }, this);
+
   // Add validate root to list of invalid components. These are the starting point for a subsequent call to validate().
-  if (this._invalidComponents.indexOf(htmlComp) < 0) {
-    this._invalidComponents.push(htmlComp);
+  scout.arrays.insert(this._invalidComponents, htmlComp, position);
+
+  // Schedule validation
+  if (this._validateTimeoutId === null) {
+    this._validateTimeoutId = setTimeout(function() {
+      this.validate();
+    }.bind(this));
   }
 };
 
@@ -49,18 +66,24 @@
  * Layouts all invalid components (as long as they haven't been removed).
  */
 scout.LayoutValidator.prototype.validate = function() {
-  this._invalidComponents.forEach(function(comp) {
+  clearTimeout(this._validateTimeoutId);
+  this._validateTimeoutId = null;
+  this._invalidComponents.slice().forEach(function(comp) {
     if (comp.isAttached()) { // don't layout components which don't exist anymore or are detached from the DOM
       comp.validateLayout();
       scout.arrays.remove(this._invalidComponents, comp);
     }
-  });
+  }, this);
 };
 
-scout.LayoutValidator.prototype.cleanupInvalidObjects = function($parentContainer){
-  this._invalidComponents.forEach(function(comp){
-    if(comp.$comp.closest($parentContainer).length>0){
+/**
+ * Removes those components from this._invalidComponents which have the given container as ancestor.
+ * The idea is to remove all components whose ancestor is about to be removed from the DOM.
+ */
+scout.LayoutValidator.prototype.cleanupInvalidComponents = function($parentContainer){
+  this._invalidComponents.slice().forEach(function(comp){
+    if (comp.$comp.closest($parentContainer).length > 0){
       scout.arrays.remove(this._invalidComponents, comp);
     }
-  }.bind(this));
+  }, this);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LogicalGridData.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LogicalGridData.js
index 0db2194..31109a8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LogicalGridData.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/LogicalGridData.js
@@ -71,8 +71,8 @@
   this.widthHint = data.widthInPixel;
   this.heightHint = data.heightInPixel;
 
-  // when having the label on top, the the row size has to be increased
-  if (this.model.labelPosition === scout.FormField.LABEL_POSITION_TOP) {
+  // when having the label on top, the row height has to be increased
+  if (this.model.labelVisible && this.model.$label && this.model.labelPosition === scout.FormField.LABEL_POSITION_TOP) {
     this.logicalRowHeightAddition = scout.HtmlEnvironment.formRowHeight;
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/NullLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/NullLayout.js
index 41b3f29..5036896 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/NullLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/NullLayout.js
@@ -20,7 +20,7 @@
   $container.children().each(function() {
     var htmlComp = scout.HtmlComponent.optGet($(this));
     if (htmlComp) {
-      htmlComp.validateLayout();
+      htmlComp.revalidateLayout();
     }
   });
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
index 6864881..75795c8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/layout/graphics.js
@@ -20,32 +20,37 @@
    *
    * @memberOf scout.graphics
    */
-  prefSize: function($elem, includeMargin, useCssSize) {
+  prefSize: function($elem, includeMargin, options) {
     // Return 0/0 if element is not displayed (display: none).
     // We don't use isVisible by purpose because isVisible returns false for elements with visibility: hidden which is wrong here (we would like to be able to measure hidden elements)
     if ($elem.isDisplayNone()) {
       return new scout.Dimension(0, 0);
     }
 
+    var defaults = {
+      useCssSize: false,
+      resetWidth: true
+    };
+    options = $.extend({}, defaults, options);
+
     var oldStyle = $elem.attr('style');
     var oldScrollLeft = $elem.scrollLeft();
     var oldScrollTop = $elem.scrollTop();
 
     // UseCssSize is necessary if the css rules have a fix height or width set.
     // Otherwise setting the width/height to auto could result in a different size
-    var newWidth = (useCssSize ? '' : 'auto');
-    var newHeight = (useCssSize ? '' : 'auto');
+    var newWidth = (options.useCssSize ? '' : scout.nvl(options.widthHint, 'auto'));
+    var newHeight = (options.useCssSize ? '' : 'auto');
 
     // modify properties which prevent reading the preferred size
     $elem.css({
       'width': newWidth,
-      'height': newHeight,
-      'white-space': 'no-wrap'
+      'height': newHeight
     });
 
     var prefSize;
     // measure
-    if (useCssSize) {
+    if (options.useCssSize) {
       prefSize = scout.graphics.getSize($elem, includeMargin);
     } else {
       prefSize = scout.graphics.getScrollSizes($elem, includeMargin);
@@ -80,7 +85,7 @@
    */
   /**
    * Returns the size of the component, insets included.
-   * @param includeMargin when set to true, returned dimensions include margins of component
+   * @param includeMargin when set to true, returned dimensions include margins of component, default is <code>false</code>.
    */
   getSize: function($comp, includeMargin) {
     includeMargin = scout.nvl(includeMargin, false);
@@ -205,7 +210,7 @@
     if (!$comp) {
       return '$comp is undefined';
     }
-    if (!($comp instanceof jQuery)) {
+    if (!($comp instanceof $)) {
       $comp = $($comp);
     }
     if ($comp.length === 0) {
@@ -251,6 +256,10 @@
   return (this.x === o.x && this.y === o.y);
 };
 
+scout.Point.prototype.clone = function(o) {
+  return new scout.Point(this.x, this.y);
+};
+
 /**
  * JavaScript port from java.awt.Dimension.
  * @param vararg width (number) or otherDimension (scout.Dimension)
@@ -277,6 +286,10 @@
   return (this.width === o.width && this.height === o.height);
 };
 
+scout.Dimension.prototype.clone = function() {
+  return new scout.Dimension(this.width, this.height);
+};
+
 scout.Dimension.prototype.subtract = function(insets) {
   return new scout.Dimension(
     this.width - insets.horizontal(),
@@ -310,6 +323,10 @@
   return 'Rectangle[x=' + this.x + ' y=' + this.y + ' width=' + this.width + ' height=' + this.height + ']';
 };
 
+scout.Rectangle.prototype.clone = function(o) {
+  return new scout.Rectangle(this.x, this.y, this.width, this.height);
+};
+
 scout.Rectangle.prototype.center = function() {
   return new scout.Point(this.x + this.width / 2, this.y + this.height / 2);
 };
@@ -406,6 +423,10 @@
   return 'Insets[top=' + this.top + ' right=' + this.right + ' bottom=' + this.bottom + ' left=' + this.left + ']';
 };
 
+scout.Insets.prototype.clone = function() {
+  return new scout.Insets(this.top, this.right, this.bottom, this.left);
+};
+
 /**
  * JavaScript port from java.util.TreeSet.
  */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.css
similarity index 69%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.css
index 6331768..e39effb 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.css
@@ -8,7 +8,7 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-#login-box {
+.login-box-content > form {
   & > input,
   & > .button {
     width: 100%;
@@ -18,16 +18,20 @@
   }
 }
 
-#login-button {
-  background-color: @default-button-background-color;
-  color: @default-button-color;
-  border-width: 0;
+/*
+ * Login button is a default button -> styles are defined in main.css.
+ * Difference to regular default button is the disabled style and the ability to turn red.
+ */
+.login-button {
 
-  &:active {
-    background-color: @default-button-active-background-color;
+  &:disabled {
+    color: @default-button-color;
+    border-color: @default-button-background-color;
+    background-color: @default-button-background-color;
   }
 
-  &.login-error {
+  &.login-error:not(.disabled) {
+    border-color: @palette-red-4;
     background-color: @palette-red-4;
 
     /* Also change color of focus glow */
@@ -36,13 +40,18 @@
       #scout.glow(@palette-red-4);
     }
 
+    &:hover {
+      background-color: @palette-red-4;
+    }
+
     &:active {
+      border-color: @palette-red-4;
       background-color: darken(@palette-red-4, 5%);
     }
   }
 }
 
-#login-button-loading {
+.login-button-loading {
   #scout.animation(rotation 0.9s linear infinite);
   display: inline-block;
   border-radius: 50%;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.js
new file mode 100644
index 0000000..e05e6d1
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LoginBox.js
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.LoginBox = function(opts) {
+  scout.LoginBox.parent.call(this, opts);
+
+  var defaultOpts = {
+    logoUrl: 'res/logo.png',
+    texts: {
+      'ui.Login': 'Login',
+      'ui.LoginFailed': 'Login failed',
+      'ui.User': 'User',
+      'ui.Password': 'Password'
+    }
+  };
+  this.options = $.extend({}, defaultOpts, opts);
+  this.texts = new scout.Texts(this.options.texts);
+  this.logoUrl = this.options.logoUrl;
+};
+scout.inherits(scout.LoginBox, scout.Box);
+
+scout.LoginBox.prototype.render = function($parent) {
+  scout.LoginBox.parent.prototype.render.call(this, $parent);
+
+  this.$container.addClass('login-box');
+  this.$content.addClass('login-box-content ');
+  this.$form = $('<form>')
+    .attr('action', 'auth')
+    .attr('method', 'post')
+    .submit(this._onLoginFormSubmit.bind(this))
+    .appendTo(this.$content);
+  this.$user = $('<input>')
+    .attr('type', 'text')
+    .attr('autocapitalize', 'off')
+    .attr('autocorrect', 'off')
+    .placeholder(this.texts.get('ui.User'))
+    .appendTo(this.$form);
+  this.$password = $('<input>')
+    .attr('type', 'password')
+    .placeholder(this.texts.get('ui.Password'))
+    .appendTo(this.$form);
+  this.$button = $('<button>')
+    .attr('type', 'submit')
+    .addClass('login-button button default')
+    .text(this.texts.get('ui.Login'))
+    .appendTo(this.$form);
+
+  this.$user.focus();
+};
+
+scout.LoginBox.prototype._resetButtonText = function() {
+  this.$button
+    .text(this.texts.get('ui.Login'))
+    .removeClass('login-error');
+};
+
+scout.LoginBox.prototype._onLoginFormSubmit = function(event) {
+  // Prevent default submit action
+  event.preventDefault();
+
+  var url = this.$form.attr('action');
+  var data = {
+    user: this.$user.val(),
+    password: this.$password.val()
+  };
+
+  this.$button
+    .removeClass('login-error')
+    .setEnabled(false);
+  this.$user.off('input.resetLoginError');
+  this.$password.off('input.resetLoginError');
+  if (scout.device.supportsCssAnimation()) {
+    this.$button
+      .html('')
+      .append($('<div>').addClass('login-button-loading'));
+  }
+
+  $.post(url, data)
+    .done(this._onPostDone.bind(this))
+    .fail(this._onPostFail.bind(this));
+};
+
+scout.LoginBox.prototype._onPostDone = function(data) {
+  // Calculate target URL
+  var url = this.options.redirectUrl;
+  if (!url) {
+    url = (window.location.href || '').trim();
+    var prepareRedirectUrlFunc = this.options.prepareRedirectUrlFunc || scout.LoginBox.prepareRedirectUrl;
+    // Remove login.html and everything after it from the URL
+    url = prepareRedirectUrlFunc(url);
+  }
+
+  // Go to target URL
+  if (url) {
+    window.location.href = url;
+  } else {
+    window.location.reload();
+  }
+};
+
+scout.LoginBox.prototype._onPostFail = function(jqXHR, textStatus, errorThrown) {
+  // execute delayed to make sure loading animation is visible, otherwise (if it is very fast), it flickers
+  setTimeout(function() {
+    this.$button
+      .setEnabled(true)
+      .html('')
+      .text(this.texts.get('ui.LoginFailed'))
+      .addClass('login-error');
+	this.$user
+	  .val('')
+	  .focus()
+	  .one('input.resetLoginError', this._resetButtonText.bind(this));
+	this.$password
+	  .val('')
+	  .one('input.resetLoginError', this._resetButtonText.bind(this));
+  }.bind(this), 300);
+};
+
+// ----- Helper functions -----
+
+scout.LoginBox.prepareRedirectUrl = function(url) {
+  var urlParts = /^([^?#]*)(\?[^#]*)?(#.*)?$/.exec(url || ''); // $1 = baseUrl, $2 = queryPart, $3 = hashPart
+  var filteredBaseUrl = urlParts[1]
+    .replace(/login.html$/, '')
+    .replace(/login$/, '')
+    .replace(/logout$/, '');
+  return filteredBaseUrl + (urlParts[2] ? urlParts[2] : '') + (urlParts[3] ? urlParts[3] : '');
+};
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LogoutBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LogoutBox.js
new file mode 100644
index 0000000..5066e73
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/LogoutBox.js
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.LogoutBox = function(opts) {
+  scout.LogoutBox.parent.call(this, opts);
+
+  var defaultOpts = {
+    loginUrl: sessionStorage.getItem('scout:loginUrl') || './',
+    logoUrl: 'res/logo.png',
+    texts: {
+      'ui.LogoutSuccessful': 'Good bye!',
+      'ui.LoginAgain': 'Login again'
+    }
+  };
+  this.options = $.extend({}, defaultOpts, opts);
+  this.texts = new scout.Texts(this.options.texts);
+  this.loginUrl = this.options.loginUrl;
+  this.logoUrl = this.options.logoUrl;
+};
+scout.inherits(scout.LogoutBox, scout.Box);
+
+scout.LogoutBox.prototype.render = function($parent) {
+  scout.LogoutBox.parent.prototype.render.call(this, $parent);
+
+  this.$content.addClass('small centered')
+    .appendDiv().html(scout.strings.nl2br(this.texts.get('ui.LogoutSuccessful')));
+
+  this.$buttonBar = $('<div>')
+    .addClass('button-bar')
+    .appendTo(this.$content);
+  $('<button>')
+    .addClass('button')
+    .text(this.texts.get('ui.LoginAgain'))
+    .on('click', this._loginAgain.bind(this))
+    .appendTo(this.$buttonBar);
+
+  scout.prepareDOM();
+};
+
+scout.LogoutBox.prototype._loginAgain = function() {
+  window.location = this.loginUrl;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.js
index 35b138a..5c8eeeb 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/login.js
@@ -14,126 +14,13 @@
    * opts:
    * - redirectUrl: URL to redirect to after successful login
    * - prepareRedirectUrl: function(s) that is called on the redirectUrl before opening it
+   * - logoUrl: default points to 'res/logo.png'
    */
   init: function(opts) {
-    var $buttonDiv, texts, defaultOpts = {
-      texts: {
-        'ui.Login': 'Login',
-        'ui.LoginFailed': 'Login failed',
-        'ui.User': 'User',
-        'ui.Password': 'Password'
-      }
-    };
-    this.options = $.extend({}, defaultOpts, opts);
-    texts = new scout.Texts(this.options.texts);
-    this.$form = $('<form>')
-      .attr('action', 'auth')
-      .attr('method', 'post')
-      .submit(onLoginFormSubmit.bind(this))
-      .appendTo($('body'));
-    this.$container = $('<div>')
-      .attr('id', 'login-box')
-      .addClass('box-with-logo')
-      .appendTo(this.$form);
-    this.$user = $('<input>')
-      .attr('type', 'text')
-      .attr('autocapitalize', 'off')
-      .attr('autocorrect', 'off')
-      .placeholder(texts.get('ui.User'))
-      .appendTo(this.$container);
-    this.$password = $('<input>')
-      .attr('type', 'password')
-      .placeholder(texts.get('ui.Password'))
-      .appendTo(this.$container);
-    this.$button = $('<button>')
-      .attr('id', 'login-button')
-      .attr('type', 'submit')
-      .addClass('button default')
-      .text(texts.get('ui.Login'))
-      .appendTo(this.$container);
-
-    this.$user.focus();
-
     scout.prepareDOM();
 
-    // ----- Helper functions -----
-
-    function onLoginFormSubmit(event) {
-      // Prevent default submit action
-      event.preventDefault();
-
-      var url = this.$form.attr('action');
-      var data = {
-        user: this.$user.val(),
-        password: this.$password.val()
-      };
-
-      this.$button
-        .removeClass('login-error')
-        .setEnabled(false);
-      this.$user.off('input.resetLoginError');
-      this.$password.off('input.resetLoginError');
-      if (scout.device.supportsCssAnimation()) {
-        this.$button
-          .html('')
-          .append($('<div>').attr('id', 'login-button-loading'));
-      }
-
-      $.post(url, data)
-        .done(onPostDone.bind(this))
-        .fail(onPostFail.bind(this));
-    }
-
-    function onPostDone(data) {
-      // Calculate target URL
-      var url = this.options.redirectUrl;
-      if (!url) {
-        url = (window.location.href || '').trim();
-        var prepareRedirectUrlFunc = this.options.prepareRedirectUrlFunc || prepareRedirectUrl;
-        // Remove login.html and everything after it from the URL
-        url = prepareRedirectUrlFunc(url);
-      }
-
-      // Go to target URL
-      if (url) {
-        window.location.href = url;
-      } else {
-        window.location.reload();
-      }
-    }
-
-    function onPostFail(jqXHR, textStatus, errorThrown) {
-      // execute delayed to make sure loading animation is visible, otherwise (if it is very fast), it flickers
-      setTimeout(function() {
-        this.$button
-          .setEnabled(true)
-          .html('')
-          .text(texts.get('ui.LoginFailed'))
-          .addClass('login-error');
-        this.$user
-          .val('')
-          .focus()
-          .one('input.resetLoginError', resetButtonText.bind(this));
-        this.$password
-          .val('')
-          .one('input.resetLoginError', resetButtonText.bind(this));
-      }.bind(this), 300);
-    }
-
-    function prepareRedirectUrl(url) {
-      var urlParts = /^([^?#]*)(\?[^#]*)?(#.*)?$/.exec(url || ''); // $1 = baseUrl, $2 = queryPart, $3 = hashPart
-      var filteredBaseUrl = urlParts[1]
-        .replace(/login.html$/, '')
-        .replace(/login$/, '')
-        .replace(/logout$/, '');
-      return filteredBaseUrl + (urlParts[2] ? urlParts[2] : '') + (urlParts[3] ? urlParts[3] : '');
-    }
-
-    function resetButtonText() {
-      this.$button
-        .text(texts.get('ui.Login'))
-        .removeClass('login-error');
-    }
+    var loginBox = new scout.LoginBox(opts);
+    loginBox.render($('body'));
   }
 
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/logout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/logout.js
index ba8a1a4..6d15e4d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/logout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/login/logout.js
@@ -10,37 +10,16 @@
  ******************************************************************************/
 scout.logout = {
 
+  /**
+   * opts:
+   * - loginUrl: URL to redirect after login again button click
+   * - logoUrl: default points to 'res/logo.png'
+   */
   init: function(opts) {
-    var $container,
-      defaultOpts = {
-        loginUrl: sessionStorage.getItem('scout:loginUrl') || './',
-        texts: {
-          'ui.LogoutSuccessful': 'Good bye!',
-          'ui.LoginAgain': 'Login again'
-        }
-      };
-    var options = $.extend({}, defaultOpts, opts);
-    var texts = new scout.Texts(options.texts);
-    var $box = $('<div>')
-      .addClass('box-with-logo small centered')
-      .html(scout.strings.nl2br(texts.get('ui.LogoutSuccessful')))
-      .appendTo($('body'));
-    var $buttonBar = $('<div>')
-      .addClass('button-bar')
-      .appendTo($box);
-    $('<button>')
-      .addClass('button')
-      .text(texts.get('ui.LoginAgain'))
-      .on('click', loginAgain)
-      .appendTo($buttonBar);
-
     scout.prepareDOM();
 
-    // ----- Helper functions -----
-
-    function loginAgain() {
-      window.location = options.loginUrl;
-    }
+    var logoutBox = new scout.LogoutBox(opts);
+    logoutBox.render($('body'));
   }
 
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.css
index 0298e8f..77f3f84 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.css
@@ -23,11 +23,14 @@
   width: 100%;
   margin: 0px;
   overflow: hidden;
-  -webkit-touch-callout: none;
-  #scout.user-select(none);
-  -moz-user-select: -moz-none;
   cursor: default;
   color: @text-color;
+  #scout.user-select(none);
+  -moz-user-select: -moz-none;
+  /* Prevent mobile safari from adjusting text, due to our dynamic layouting it will be always wrong */
+  -webkit-text-size-adjust: none;
+  /* Disable highlight color. May be enabled for specific elements if required */
+  -webkit-tap-highlight-color: rgba(0,0,0,0);
 }
 
 /* -moz variant is required, see https://bugzilla.mozilla.org/show_bug.cgi?id=509958 */
@@ -217,6 +220,31 @@
     }
   }
 
+  &.default:not(.disabled) {
+    background-color: @default-button-background-color;
+    /* border is necessary to align the text with text from buttons with a real border */
+    border-color: @default-button-background-color;
+    color: @default-button-color;
+
+    &:focus {
+      color: @default-button-color;
+    }
+
+    &:hover {
+      background-color: @default-button-hover-background-color;
+    }
+
+    &:active {
+      background-color: @default-button-active-background-color;
+      border-color: @default-button-active-background-color;
+    }
+
+    & > .font-icon {
+      font-weight: normal;
+      color: @icon-inverted-color;
+    }
+  }
+
   &:disabled {
     background-color: @button-disabled-background-color;
     border-color: @button-disabled-border-color;
@@ -279,6 +307,11 @@
   resize: none;
   /* Override default overflow value 'scroll' in IE */
   overflow: auto;
+
+  /* remove platform specific styling, mainly used to remove shadow on ios safari */
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
 }
 
 /* cursor handling */
@@ -327,6 +360,25 @@
   cursor: move;
 }
 
+.closer {
+  #scout.font-icon();
+  font-size: 17px;
+  cursor: pointer;
+  color: @icon-light-color;
+
+  &::before {
+    content: @icon-remove;
+  }
+
+  &:active {
+    color: @active-color;
+  }
+
+  &:hover {
+    color: @hover-color;
+  }
+}
+
 /* Used to display errors from server when desktop is not available */
 .fatal-error {
   margin: 10px;
@@ -366,6 +418,10 @@
   text-decoration: underline;
   cursor: pointer;
 
+  &:active {
+    color: @text-color;
+  }
+
   &:focus {
     outline-color: @applink-color;
   }
@@ -384,7 +440,8 @@
 /* of these elements (iff they are "positioned"). To bring a new element to the top, add it to the end of the list. */
 /* https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context */
 .scout > .desktop-navigation,
-.scout > .desktop-taskbar,
+.scout > .desktop-header,
+.scout > .desktop-bench,
 .scout > .desktop-bench,
 .scout > .splitter,
 .scout > .glasspane,
@@ -395,7 +452,7 @@
 .scout > .file-chooser,
 .scout > .tooltip,
 .scout > .popup,
-.scout > .form-tool-popup,
+.scout > .form-menu-popup,
 .scout > .smart-field-popup,
 .scout > .date-picker-popup,
 .scout > .table-header-menu,
@@ -403,45 +460,10 @@
   z-index: 0;
 }
 
-/* Used for static pages like login, logout, unsupported-browser and noscript section.
- * Background-image is not defined here, because logo is always project specific.
- * You should define a CSS rule in your project-specific .css files.
- */
-.box-with-logo {
-  border: 1px solid @palette-gray-5;
-  background-color: @background-color;
-  max-width: 420px;
-  margin: 150px auto;
-  padding: 40px 70px;
-  #scout.drop-shadow();
-
-  background-position: center 45px;
-  background-repeat: no-repeat;
-  padding-top: 140px;
-
-  & > .button-bar {
-    padding-top: 32px;
-    text-align: center;
-
-    & > .button {
-      padding: 7px @button-padding-x;
-    }
-  }
-
-  &.small {
-    background-size: 25%;
-    padding-top: 100px;
-  }
-
-  &.centered {
-    text-align: center;
-  }
-}
-
 noscript {
   display: block;
 
-  & > h1 {
+  & > .wrapper > .box-content > h1 {
     #scout.font-text-normal(bold);
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.js
index df207b9..5bf3d00 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/main.js
@@ -158,7 +158,7 @@
 
   $('.scout').each(function() {
     var $entryPoint = $(this),
-      $box = $entryPoint.appendDiv('box-with-logo small'),
+      $box = $entryPoint.appendDiv(),
       newOptions = scout.objects.valueCopy(options);
 
     newOptions.checkBrowserCompatibility = false;
@@ -176,6 +176,10 @@
  * Note: we do not install an error handler on popup-windows because everything is controlled by the main-window
  * so exceptions will also occur in that window. This also means, the fatal message-box will be displayed in the
  * main-window, even when a popup-window is opened and active.
+ *
+ * Caution: The error.stack doesn't look the same in different browsers. Chrome for instance puts the error message
+ * on the first line of the stack. Firefox does only contain the stack lines, without the message, but in return
+ * the stack trace is much longer :)
  */
 scout._installGlobalJavascriptErrorHandler = function() {
   window.onerror = function(errorMessage, fileName, lineNumber, columnNumber, error) {
@@ -183,9 +187,9 @@
       var errorCode = getJsErrorCode(error),
         logStr = errorMessage + ' at ' + fileName + ':' + lineNumber;
       if (error && error.stack) {
-        logStr = error.stack;
+        logStr += '\n' + error.stack;
       }
-      logStr += ' (' + 'Code ' + errorCode + ')';
+      logStr += '\n(' + 'Code ' + errorCode + ')';
       $.log.error(logStr);
       if (window.console) {
         window.console.log(logStr);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/ContextMenuPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/ContextMenuPopup.js
index e05b376..77cfa49 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/ContextMenuPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/ContextMenuPopup.js
@@ -133,7 +133,7 @@
 
 scout.ContextMenuPopup.prototype.renderSubMenuItems = function(parentMenu, menus, animated, initialSubMenuRendering) {
   if (!this.session.desktop.rendered && !initialSubMenuRendering) {
-    this.initialSubmenusToRender = {
+    this.initialSubMenusToRender = {
       parentMenu: parentMenu,
       menus: menus
     };
@@ -225,7 +225,7 @@
             parent: this
           });
           this._updateFirstLastClass();
-          this.$body.css('box-shadow', "");
+          this.$body.css('box-shadow', '');
         }
       }.bind(this)
     });
@@ -278,39 +278,25 @@
   }
 
   iconOffset = iconOffset ? iconOffset : 0;
-  menus.some(function(menu) {
+  menus.forEach(function(menu) {
     // Invisible menus are rendered as well because their visibility might change dynamically
     if (menu.separator) {
       return;
     }
+
     // prevent loosing original parent
     var parentMenu = menu.parent;
     if (this.options.cloneMenuItems && !menu.cloneOf) {
       menu = menu.cloneAdapter({
         parent: this
       });
-      menu.on('propertyChange', function(event) {
-        if (event.selected) {
-          var propertyChangeEvent = {
-            properties: {
-              selected: event.selected
-            }
-          };
-          menu.cloneOf.onModelPropertyChange(propertyChangeEvent);
-        }
-      });
+      menu.on('propertyChange', this._onMenuPropertyChange.bind(this));
     } else {
-      var oldParent = menu.parent;
+      menu.oldParentMenu = parentMenu;
       menu.setParent(this);
     }
-    var menuRemoveHandler = function(event) {
-      var removedMenu = event.eventOn;
-      if (removedMenu.cloneOf) {
-        this.session.unregisterAllAdapterClones(removedMenu.cloneOf);
-      }
-      removedMenu.setParent(oldParent);
-    }.bind(this);
-    menu.on('remove', menuRemoveHandler);
+    menu.on('remove', this._onMenuRemove.bind(this));
+
     // just set once because on second execution of this menu.parent is set to a popup
     if (!menu.parentMenu) {
       menu.parentMenu = parentMenu;
@@ -318,33 +304,62 @@
     menu.render(this.$body);
     menu.afterSendDoAction = this.close.bind(this);
     menu.on('propertyChange', this._onMenuItemPropertyChange.bind(this));
-    if (menu.iconId && menu.$container.data('$icon').cssWidth() > iconOffset) {
-      iconOffset = menu.$container.data('$icon').cssWidth();
-      // update already rendered menu-items
-      this.$body.children().each(function(index, element) {
-        var $element = $(element);
-        var $icon = $element.data('$icon');
-        if ($icon && $icon.cssWidth() < iconOffset) {
-          $element.find('.text').css('padding-left', iconOffset - $icon.cssWidth());
-        } else if (element !== menu.$container[0]) {
-          $element.find('.text').css('padding-left', iconOffset);
-        }
-      });
-    } else if (iconOffset && !menu.iconId) {
-      menu.$container.find('.text').css('padding-left', iconOffset);
-    } else if (menu.$container.data('$icon') && menu.$container.data('$icon').cssWidth() < iconOffset) {
-      menu.$container.find('.text').css('padding-left', iconOffset - menu.$container.data('$icon').cssWidth());
-    }
+    iconOffset = this._updateIconAndText(menu, iconOffset);
   }, this);
-  while (this.initialSubmenusToRender && !initialSubMenuRendering) {
-    var parentMenu = this.initialSubmenusToRender.parentMenu,
-      subMenus = this.initialSubmenusToRender.menus;
-    this.initialSubmenusToRender = undefined;
-    this.renderSubMenuItems(parentMenu, subMenus, false, true);
-  }
+
+  this._handleInitialSubMenus(initialSubMenuRendering);
   this._updateFirstLastClass();
 };
 
+scout.ContextMenuPopup.prototype._handleInitialSubMenus = function(initialSubMenuRendering) {
+  var menusObj;
+  while(this.initialSubMenusToRender && !initialSubMenuRendering) {
+    menusObj = this.initialSubMenusToRender;
+    this.initialSubMenusToRender = undefined;
+    this.renderSubMenuItems(menusObj.parentMenu, menusObj.menus, false, true);
+  }
+};
+
+scout.ContextMenuPopup.prototype._updateIconAndText = function(menu, iconOffset) {
+  if (menu.iconId && menu.$container.data('$icon').cssWidth() > iconOffset) {
+    iconOffset = menu.$container.data('$icon').cssWidth();
+    // update already rendered menu-items
+    this.$body.children().each(function(index, element) {
+      var $element = $(element);
+      var $icon = $element.data('$icon');
+      if ($icon && $icon.cssWidth() < iconOffset) {
+        $element.find('.text').css('padding-left', iconOffset - $icon.cssWidth());
+      } else if (element !== menu.$container[0]) {
+        $element.find('.text').css('padding-left', iconOffset);
+      }
+    });
+  } else if (iconOffset && !menu.iconId) {
+    menu.$container.find('.text').css('padding-left', iconOffset);
+  } else if (menu.$container.data('$icon') && menu.$container.data('$icon').cssWidth() < iconOffset) {
+    menu.$container.find('.text').css('padding-left', iconOffset - menu.$container.data('$icon').cssWidth());
+  }
+  return iconOffset;
+};
+
+scout.ContextMenuPopup.prototype._onMenuPropertyChange = function(event) {
+  if (event.selected) {
+    var menu = event.source;
+    menu.cloneOf.onModelPropertyChange({
+      properties: {
+        selected: event.selected
+      }
+    });
+  }
+};
+
+scout.ContextMenuPopup.prototype._onMenuRemove = function(event) {
+  var menu = event.source;
+  if (this.options.cloneMenuItems && menu.cloneOf) {
+    this.session.unregisterAllAdapterClones(menu.cloneOf);
+  }
+  menu.setParent(menu.oldParentMenu);
+};
+
 /**
  * When cloneMenuItems is true, it means the menu instance is also used elsewhere (for instance in a menu-bar).
  * When cloneMenuItems is false, it means the menu instance is only used in this popup.
@@ -368,15 +383,6 @@
   scout.ContextMenuPopup.parent.prototype._remove.call(this);
 };
 
-scout.ContextMenuPopup.prototype.close = function(event) {
-  if ((event && this.openEvent && event.originalEvent !== this.openEvent.originalEvent) || !event || !this.openEvent) {
-    if (this.$container) {
-      this.$container.stop(true);
-    }
-    scout.ContextMenuPopup.parent.prototype.close.call(this, event);
-  }
-};
-
 /**
  * @override PopupWithHead.js
  */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.css
index 3ef7e12..433c716 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.css
@@ -27,6 +27,10 @@
     color: @hover-color;
   }
 
+  &:not(.disabled):active {
+    color: @active-color;
+  }
+
   &.disabled {
     color: @disabled-color;
     cursor: default;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.js
index 04e9240..f0ffc72 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/Menu.js
@@ -17,6 +17,7 @@
   this.excludedByFilter = false;
 
   this.subMenuExpanded = false;
+  this.subMenuIconVisible = true;
 
   /**
    * This property is set if this is a subMenu. The property is set when this submenu is rendered.
@@ -33,7 +34,7 @@
 scout.inherits(scout.Menu, scout.Action);
 
 /**
- * @override ModelAdapter
+ * @override Widget
  */
 scout.Menu.prototype._initKeyStrokeContext = function(keyStrokeContext) {
   scout.Menu.parent.prototype._initKeyStrokeContext.call(this, keyStrokeContext);
@@ -48,6 +49,7 @@
     this._renderItem($parent);
   }
   this.$container.unfocusable();
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
 };
 
 scout.Menu.prototype._remove = function() {
@@ -71,32 +73,32 @@
     .on('mousedown', mouseEventHandler)
     .on('contextmenu', mouseEventHandler)
     .on('click', mouseEventHandler);
-  if (this.childActions.length > 0 && this.text) {
+  if (this.childActions.length > 0 && this.text && this.subMenuIconVisible) {
     this.$submenuIcon = this.$container.appendSpan('submenu-icon');
   }
 
   // when menus with button style are displayed in a overflow-menu,
   // render as regular menu, ignore button styles.
-  if (scout.Action.ActionStyle.BUTTON === this.actionStyle && !this.overflow) {
+  if (this.isButton() && !this.overflow) {
     this.$container.addClass('menu-button');
   }
 };
 
-scout.Menu.prototype._renderSelected = function(event) {
-  if (!this._doActionTogglesPopup()) {
+scout.Menu.prototype._renderSelected = function() {
+  if (!this._doActionTogglesSubMenu()) {
     scout.Menu.parent.prototype._renderSelected.call(this);
   }
   if (this.selected) {
     if (this._doActionTogglesSubMenu()) {
       this._renderSubMenuItems(this, this.childActions);
     } else if (this._doActionTogglesPopup()) {
-      this._openPopup(event);
+      this._openPopup();
     }
   } else {
     if (this._doActionTogglesSubMenu() && this.rendered) {
       this._removeSubMenuItems(this);
     } else {
-      this._closePopup(event);
+      this._closePopup();
       this._closeSubMenues();
     }
   }
@@ -129,7 +131,7 @@
 };
 
 scout.Menu.prototype._doActionTogglesSubMenu = function() {
-  return this.parent instanceof scout.ContextMenuPopup || this.parent instanceof scout.Menu;
+  return this.childActions.length > 0 && (this.parent instanceof scout.ContextMenuPopup || this.parent instanceof scout.Menu);
 };
 
 scout.Menu.prototype._getSubMenuLevel = function() {
@@ -148,9 +150,9 @@
   // the impression of a faster UI, open the popup already on 'mousedown', not
   // on 'click'. All other actions are handled on 'click'.
   if (event.type === 'mousedown' && this._doActionTogglesPopup()) {
-    this.doAction(event);
+    this.doAction();
   } else if ((event.type === 'click' || event.type === 'contextmenu') && !this._doActionTogglesPopup()) {
-    this.doAction(event);
+    this.doAction();
   }
 };
 
@@ -168,43 +170,44 @@
     this.$submenuIcon.appendTo(this.$container);
   }
   this._updateIconAndTextStyle();
+  this.invalidateLayoutTree();
 };
 
 scout.Menu.prototype._renderIconId = function() {
   scout.Menu.parent.prototype._renderIconId.call(this);
   this._updateIconAndTextStyle();
+  this.invalidateLayoutTree();
+};
+
+scout.Menu.prototype._renderVisible = function() {
+  scout.Menu.parent.prototype._renderVisible.call(this);
+  this.invalidateLayoutTree();
 };
 
 scout.Menu.prototype.isTabTarget = function() {
-  return this.enabled && this.visible && (this.actionStyle === scout.Action.ActionStyle.BUTTON || !this.separator);
+  return this.enabled && this.visible && (this.isButton() || !this.separator);
 };
 
 scout.Menu.prototype._updateIconAndTextStyle = function() {
-  var hasText = scout.strings.hasText(this.text);
+  var hasText = scout.strings.hasText(this.text) && this.textVisible;
   var hasTextAndIcon = !!(hasText && this.iconId);
   this.$container.toggleClass('menu-textandicon', hasTextAndIcon);
   this.$container.toggleClass('menu-icononly', !hasText);
 };
 
-scout.Menu.prototype._closePopup = function(event) {
+scout.Menu.prototype._closePopup = function() {
   if (this.popup) {
-    this.popup.close(event);
+    this.popup.close();
   }
 };
 
-/**
- * @param event
- *          UI event that triggered the popup (e.g. 'mouse clicked'). This argument
- *          is passed to the MenuBarPopup  as 'ignoreEvent'. It prevents the popup
- *          from being closed again by the same event that bubbled to other elements.
- */
-scout.Menu.prototype._openPopup = function(event) {
+scout.Menu.prototype._openPopup = function() {
   if (this.popup) {
     // already open
     return;
   }
-  this.popup = this._createPopup(event);
-  this.popup.open(null, event);
+  this.popup = this._createPopup();
+  this.popup.open();
   this.popup.on('remove', function(event) {
     this.popup = null;
   }.bind(this));
@@ -215,6 +218,9 @@
   this.popup.on('close', function(event) {
     this.setSelected(false);
   }.bind(this));
+  if (this._customCssClasses) {
+    this.popup.$container.addClass(this._customCssClasses);
+  }
 };
 
 scout.Menu.prototype._createPopup = function(event) {
@@ -241,3 +247,28 @@
 scout.Menu.prototype.isToggleAction = function() {
   return this.childActions.length > 0 || this.toggleAction;
 };
+
+scout.Menu.prototype.isButton = function() {
+  return scout.Action.ActionStyle.BUTTON === this.actionStyle;
+};
+
+scout.Menu.prototype.setSelected = function(selected, notifyServer) {
+  if (selected === this.selected) {
+    return;
+  }
+  scout.Menu.parent.prototype.setSelected.call(this, selected, notifyServer);
+  if (!this._doActionTogglesSubMenu() && !this._doActionTogglesPopup()) {
+    return;
+  }
+  // If menu toggles a popup and is in an ellipsis menu which is not selected it needs a special treatment
+  if (this.overflowMenu && !this.overflowMenu.selected) {
+    this._handleSelectedInEllipsis();
+  }
+};
+
+scout.Menu.prototype._handleSelectedInEllipsis = function() {
+  // If the selection toggles a popup, open the ellipsis menu as well, otherwise the popup would not be shown
+  if (this.selected) {
+    this.overflowMenu.setSelected(true);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuExecKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuExecKeyStroke.js
index dce45a1..eccda63 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuExecKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuExecKeyStroke.js
@@ -25,5 +25,5 @@
  * @override KeyStroke.js
  */
 scout.MenuExecKeyStroke.prototype.handle = function(event) {
-  this.field.doAction(event);
+  this.field.doAction();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuItemsOrder.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuItemsOrder.js
index a8a1dc8..ca3ea32 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuItemsOrder.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuItemsOrder.js
@@ -21,7 +21,6 @@
     selectionItems = [],
     rightItems = [];
 
-
   var isEmptyspaceMenuVisible = false,
   isSelectionMenuVisible =false;
   items.forEach(function(item) {
@@ -29,7 +28,7 @@
     if (item.createdBy === this) {
       return;
     }
-    if (scout.menus.isButton(item)) {
+    if (item.isButton()) {
       buttons.push(item);
     } else if (item.horizontalAlignment === 1) {
       rightItems.push(item);
@@ -72,7 +71,7 @@
  */
 scout.MenuItemsOrder.prototype._createSeparator = function() {
   return scout.create('Menu', {
-    parent: this.session.desktop, // TODO [5.2] cgu: this is not correct, menubar should be the parent
+    parent: this.menuBar,
     createdBy: this,
     separator: true
   });
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.css
similarity index 96%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.css
index 5189194..2a1b87c 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.css
@@ -40,8 +40,8 @@
   width: 100%;
   background-color: @menubar-background-color;
   display: table;
-  padding-top: 3px;
-  padding-bottom: 3px;
+  padding-top: 2px;
+  padding-bottom: 2px;
   /* default style is 'top' */
   border-bottom: 1px solid @border-color;
 
@@ -83,6 +83,14 @@
         color: @menubar-item-color;
       }
 
+      &:not(.disabled):hover {
+        color: @hover-color;
+      }
+
+      &:not(.disabled):active {
+        color: @active-color;
+      }
+
       &:focus {
         outline: none;
 
@@ -220,8 +228,8 @@
 
 .main-menubar {
   padding-left: @bench-padding-x;
-  padding-right: @bench-padding-x; // - @desktop-table-header-menubar-padding-right;
-  height: 52px;
+  padding-right: @bench-padding-x;
+  height: 50px;
   background-color: @main-menubar-background-color;
 
   & > .menubox {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
similarity index 79%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
index fc2db0d..2954048 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBar.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
@@ -12,13 +12,17 @@
   scout.MenuBar.parent.call(this);
 
   this._addKeyStrokeContextSupport();
+  this._addEventSupport();
   this.menuSorter;
   this.position = 'top'; // or 'bottom'
   this.size = 'small'; // or 'large'
   this.tabbable = true;
   this._internalMenuItems = []; // original list of menuItems that was passed to updateItems(), only used to check if menubar has changed
   this.menuItems = []; // list of menuItems (ordered, may contain additional UI separators, some menus may not be rendered)
-  this._orderedMenuItems = null; // Object containing "left" and "right" menus
+  this._orderedMenuItems = {
+    left: [],
+    right: []
+  }; // Object containing "left" and "right" menus
   this._defaultMenu = null;
   this.visible = false;
 
@@ -37,14 +41,10 @@
     // because the layout calls rebuildItemsInternal().
     if (event.changedProperties.length > 0) {
       if (event.changedProperties.length === 1 && event.changedProperties[0] === 'enabled') {
-        // Optimization: don't invalidate layout when only the enabled state has changed (this should not affect the layout).
         this.updateDefaultMenu();
-        return;
+      } else if (event.changedProperties.indexOf('visible') > -1) {
+        this.updateVisibility();
       }
-      if (event.changedProperties.indexOf('visible') > -1) {
-        this.updateVisibility(true);
-      }
-      this.htmlComp.invalidateLayoutTree();
     }
   }.bind(this);
 };
@@ -54,7 +54,9 @@
   scout.MenuBar.parent.prototype._init.call(this, options);
 
   this.menuSorter = options.menuOrder;
+  this.menuSorter.menuBar = this;
   this.menuFilter = options.menuFilter;
+  this.updateVisibility();
 };
 
 scout.MenuBar.prototype._initKeyStrokeContext = function(keyStrokeContext) {
@@ -68,14 +70,14 @@
  * @override Widget.js
  */
 scout.MenuBar.prototype._render = function($parent) {
-  // Visibility may change when updateItems() function is called, see updateVisibility().
-  this.visible = (this.menuItems.length > 0);
   this.$container = $parent.makeDiv('menubar')
     .attr('id', 'MenuBar-' + scout.objectFactory.createUniqueId())
-    .toggleClass('main-menubar', this.size === 'large')
-    .setVisible(this.visible);
+    .toggleClass('main-menubar', this.size === 'large');
+
   this.$left = this.$container.appendDiv('menubox left');
+  new scout.HtmlComponent(this.$left, this.session);
   this.$right = this.$container.appendDiv('menubox right');
+  new scout.HtmlComponent(this.$right, this.session);
 
   this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
   this.htmlComp.setLayout(new scout.MenuBarLayout(this));
@@ -86,6 +88,24 @@
     this.$container.addClass('bottom');
     $parent.append(this.$container);
   }
+  this.rebuildItemsInternal();
+};
+
+scout.MenuBar.prototype._remove = function() {
+  scout.MenuBar.parent.prototype._remove.call(this);
+  this._removeMenuItems();
+  this.visibleMenuItems = [];
+  this.visible = false;
+};
+
+scout.MenuBar.prototype._renderProperties = function() {
+  scout.MenuBar.parent.prototype._renderProperties.call(this);
+  this._renderVisible();
+};
+
+scout.MenuBar.prototype._renderVisible = function() {
+  this.$container.setVisible(this.visible);
+  this.invalidateLayoutTree();
 };
 
 scout.MenuBar.prototype.bottom = function() {
@@ -100,27 +120,10 @@
   this.size = 'large';
 };
 
-scout.MenuBar.prototype._remove = function() {
-  scout.MenuBar.parent.prototype._remove.call(this);
-  this._removeMenuItems();
-  // Reset internal state (don't do it inside _removeMenuItems, because that is also called from _updateItems())
-  this._internalMenuItems = [];
-  this.menuItems = [];
-  this._orderedMenuItems = null;
-  this.visibleMenuItems = [];
-  this.visible = false;
-};
-
-scout.MenuBar.prototype._removeMenuItems = function() {
+scout.MenuBar.prototype._destroyMenuSorterSeparators = function() {
   this.menuItems.forEach(function(item) {
-    item.off('propertyChange', this._menuItemPropertyChangeListener);
-    // remove DOM for existing menu items and destroy items that have
-    // been created by the menuSorter (e.g. separators).
     if (item.createdBy === this.menuSorter) {
       item.destroy();
-    } else {
-      item.overflow = false;
-      item.remove();
     }
   }, this);
 };
@@ -137,38 +140,48 @@
  * Do not call this internal method from outside (except from the MenuBarLayout).
  */
 scout.MenuBar.prototype.rebuildItemsInternal = function() {
-  this._updateItems(this._internalMenuItems);
+  this._updateItems();
 };
 
-scout.MenuBar.prototype.updateItems = function(menuItems) {
+scout.MenuBar.prototype.setMenuItems = function(menuItems) {
   menuItems = scout.arrays.ensure(menuItems);
-
   // Only update if list of menus changed. Don't compare this.menuItems, because that list
   // may contain additional UI separators, and may not be in the same order
   var sameMenuItems = scout.arrays.equals(this._internalMenuItems, menuItems);
-  var hasUnrenderedMenuItems = menuItems.some(function(elem) {
-    return !elem.rendered;
-  });
-  if (!sameMenuItems || hasUnrenderedMenuItems) {
+
+  if (!sameMenuItems) {
+    if (this.rendered) {
+      this._removeMenuItems();
+    }
+
+    // The menuSorter may add separators to the list of items -> destroy the old ones first
+    this._destroyMenuSorterSeparators();
     this._internalMenuItems = menuItems;
-    this.rebuildItems(); // Re-layout menubar
-  } else {
-    // Don't rebuild menubar, but update "markers"
-    this.updateVisibility();
-    this.updateDefaultMenu();
-    this.updateLastItemMarker();
+    this._orderedMenuItems = this.menuSorter.order(menuItems, this);
+    this.menuItems = this._orderedMenuItems.left.concat(this._orderedMenuItems.right);
+    this.menuItems.forEach(function(menuItem) {
+      menuItem.setParent(this);
+    }, this);
+  }
+
+  if (this.rendered) {
+    var hasUnrenderedMenuItems = this.menuItems.some(function(elem) {
+      return !elem.rendered;
+    });
+    if (!sameMenuItems || hasUnrenderedMenuItems) {
+      this.rebuildItems(); // Re-layout menubar
+    } else {
+      // Don't rebuild menubar, but update "markers"
+      this.updateVisibility();
+      this.updateDefaultMenu();
+      this.updateLastItemMarker();
+    }
   }
 };
 
-scout.MenuBar.prototype._updateItems = function(menuItems) {
+scout.MenuBar.prototype._updateItems = function() {
   this._removeMenuItems();
 
-  // The menuSorter may add separators to the list of items, that's why we
-  // store the return value of menuSorter in this.menuItems and not the
-  // menuItems passed to the updateItems method. We must do this because
-  // otherwise we could not remove the added separator later.
-  this._orderedMenuItems = this.menuSorter.order(menuItems, this);
-  this.menuItems = this._orderedMenuItems.left.concat(this._orderedMenuItems.right);
   this.visibleMenuItems = this.menuItems;
   this._lastVisibleItemLeft = null;
   this._lastVisibleItemRight = null;
@@ -233,18 +246,19 @@
   }
 };
 
-scout.MenuBar.prototype.updateVisibility = function(suppressLayout) {
-  var oldVisible = this.visible;
-  this.visible = !this.hiddenByUi && this.menuItems.some(function(m) {
+scout.MenuBar.prototype.updateVisibility = function() {
+  this.setVisible(!this.hiddenByUi && this.menuItems.some(function(m) {
     return m.visible;
-  });
+  }));
+};
 
-  // Update visibility, layout
-  if (this.visible !== oldVisible) {
-    this.$container.setVisible(this.visible);
-    if (!suppressLayout) {
-      this.htmlComp.invalidateLayoutTree();
-    }
+scout.MenuBar.prototype.setVisible = function(visible) {
+  if (this.visible === visible) {
+    return;
+  }
+  this._setProperty('visible', visible);
+  if (this.rendered) {
+    this._renderVisible();
   }
 };
 
@@ -313,3 +327,11 @@
     item.on('propertyChange', this._menuItemPropertyChangeListener);
   }.bind(this));
 };
+
+scout.MenuBar.prototype._removeMenuItems = function() {
+  this.menuItems.forEach(function(item) {
+    item.off('propertyChange', this._menuItemPropertyChangeListener);
+    item.overflow = false;
+    item.remove();
+  }, this);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarLayout.js
similarity index 97%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarLayout.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarLayout.js
index 1a6d754..eb3fa64 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarLayout.js
@@ -35,7 +35,7 @@
   var rightWidth = this._menuBar.$right.width();
 
   // use availableWidth + 1 because of rounding problems in JQuery
-  if (leftWidth + rightWidth <= availableWidth+1) {
+  if (leftWidth + rightWidth <= availableWidth + 1) {
     // ok, no ellisis required
     this._menuBar.visibleMenuItems = this._menuBar.menuItems;
   } else {
@@ -140,7 +140,9 @@
 
 scout.MenuBarLayout.prototype.preferredLayoutSize = function($container) {
   // Menubar has an absolute css height set -> useCssSize = true
-  return scout.graphics.prefSize($container, false, true);
+  return scout.graphics.prefSize($container, false, {
+    useCssSize: true
+  });
 };
 
 /* --- STATIC HELPERS ------------------------------------------------------------- */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarLeftKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarLeftKeyStroke.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarLeftKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarLeftKeyStroke.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarPopup.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarPopup.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarPopup.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarRightKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarRightKeyStroke.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/MenuBarRightKeyStroke.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBarRightKeyStroke.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBox.js
new file mode 100644
index 0000000..a833f1a
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBox.js
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.MenuBox = function(menuBar) {
+  scout.MenuBox.parent.call(this);
+  this.compact = false;
+};
+scout.inherits(scout.MenuBox, scout.Widget);
+
+scout.MenuBox.prototype._init = function(options) {
+  scout.MenuBox.parent.prototype._init.call(this, options);
+  this.menus = options.menus || [];
+  this.customMenuCssClasses = options.customMenuCssClasses || '';
+  this.customMenuCssClasses += ' ' + 'menu-box-item';
+  this._initMenus(this.menus);
+};
+
+scout.MenuBox.prototype._initMenus = function(menus) {
+  menus.forEach(this._initMenu.bind(this));
+};
+
+scout.MenuBox.prototype._initMenu = function(menu) {
+  menu.setParent(this);
+  menu._customCssClasses = this.customMenuCssClasses;
+};
+
+/**
+ * @override Widget.js
+ */
+scout.MenuBox.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('menu-box');
+
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.MenuBoxLayout(this));
+};
+
+scout.MenuBox.prototype._renderProperties = function() {
+  this._renderMenus();
+  this._renderCompact();
+};
+
+scout.MenuBox.prototype._renderMenus = function() {
+  this.menus.forEach(function(menu) {
+    menu.render(this.$container);
+  }, this);
+};
+
+scout.MenuBox.prototype._renderCompact = function() {
+  this.$container.toggleClass('compact', this.compact);
+  this.invalidateLayoutTree();
+};
+
+scout.MenuBox.prototype.setCompact = function(compact) {
+  if (this.compact === compact) {
+    return;
+  }
+  this.compact = compact;
+  if (this.rendered) {
+    this._renderCompact();
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBoxLayout.js
new file mode 100644
index 0000000..d066b03
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubox/MenuBoxLayout.js
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.MenuBoxLayout = function(menuBox) {
+  scout.MenuBoxLayout.parent.call(this);
+  this.menuBox = menuBox;
+};
+scout.inherits(scout.MenuBoxLayout, scout.AbstractLayout);
+
+/**
+ * @override AbstractLayout.js
+ */
+scout.MenuBoxLayout.prototype.layout = function($container) {
+  this._layout($container);
+
+  this.visibleMenus().forEach(function(menu) {
+    // Make sure open popups are at the correct position after layouting
+    if (menu.popup) {
+      menu.popup.position();
+    }
+  });
+};
+
+scout.MenuBoxLayout.prototype._layout = function($container) {
+  var htmlContainer = this.menuBox.htmlComp,
+    containerSize = htmlContainer.getSize(),
+    menus = this.visibleMenus(),
+    menusWidth = 0;
+
+  this.undoCollapse(menus);
+  this.undoCompact(menus);
+  this.undoShrink(menus);
+  menusWidth = this.actualPrefSize(menus).width;
+  if (menusWidth <= containerSize.width) {
+    // OK, every menu fits into container
+    return;
+  }
+
+  // Menus don't fit
+
+  // First approach: Set menuBox into compact mode
+  this.compact(menus);
+  menusWidth = this.actualPrefSize(menus).width;
+  if (menusWidth <= containerSize.width) {
+    // OK, every menu fits into container
+    return;
+  }
+
+  // Second approach: Make text invisible and only show the icon (if available)
+  this.shrink(menus);
+  menusWidth = this.actualPrefSize(menus).width;
+  if (menusWidth <= containerSize.width) {
+    // OK, every menu fits into container
+    return;
+  }
+
+  // Third approach: Create ellipsis and move overflown menus into it
+  this.collapse(menus, containerSize, menusWidth);
+};
+
+scout.MenuBoxLayout.prototype.preferredLayoutSize = function($container) {
+  var menus = this.visibleMenus();
+
+  this.undoCollapse(menus);
+  this.undoCompact(menus);
+  this.undoShrink(menus);
+
+  return this.actualPrefSize();
+};
+
+scout.MenuBoxLayout.prototype.compact = function(menus) {
+  if (this.menuBox.compactOrig === undefined) {
+    this.menuBox.compactOrig = this.compact;
+    this.menuBox.htmlComp.suppressInvalidate = true;
+    this.menuBox.setCompact(true);
+    this.menuBox.htmlComp.suppressInvalidate = false;
+  }
+
+  this.compactMenus(menus);
+};
+
+scout.MenuBoxLayout.prototype.undoCompact = function(menus) {
+  if (this.menuBox.compactOrig !== undefined) {
+    this.menuBox.htmlComp.suppressInvalidate = true;
+    this.menuBox.setCompact(this.compactOrig);
+    this.menuBox.htmlComp.suppressInvalidate = false;
+    this.menuBox.compactOrig = undefined;
+  }
+
+  this.undoCompactMenus(menus);
+};
+
+/**
+ * Sets all menus into compact mode.
+ */
+scout.MenuBoxLayout.prototype.compactMenus = function(menus) {
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    if (menu.compactOrig !== undefined) {
+      // already done
+      return;
+    }
+    menu.compactOrig = menu.compact;
+    menu.htmlComp.suppressInvalidate = true;
+    menu.setCompact(true);
+    menu.htmlComp.suppressInvalidate = false;
+  }, this);
+
+  if (this._ellipsis) {
+    this._ellipsis.setCompact(true);
+  }
+};
+
+/**
+ * Restores to the previous state of the compact property.
+ */
+scout.MenuBoxLayout.prototype.undoCompactMenus = function(menus) {
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    if (menu.compactOrig === undefined) {
+      return;
+    }
+    // Restore old compact state
+    menu.htmlComp.suppressInvalidate = true;
+    menu.setCompact(menu.compactOrig);
+    menu.htmlComp.suppressInvalidate = false;
+    menu.compactOrig = undefined;
+  }, this);
+
+  if (this._ellipsis) {
+    this._ellipsis.setCompact(false);
+  }
+};
+
+scout.MenuBoxLayout.prototype.shrink = function(menus) {
+  this.shrinkMenus(menus);
+};
+
+/**
+ * Makes the text invisible of all menus with an icon.
+ */
+scout.MenuBoxLayout.prototype.shrinkMenus = function(menus) {
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    if (menu.textVisibleOrig !== undefined) {
+      // already done
+      return;
+    }
+    if (menu.iconId) {
+      menu.textVisibleOrig = menu.textVisible;
+      menu.htmlComp.suppressInvalidate = true;
+      menu.setTextVisible(false);
+      menu.htmlComp.suppressInvalidate = false;
+    }
+  }, this);
+};
+
+scout.MenuBoxLayout.prototype.undoShrink = function(menus) {
+  this.undoShrinkMenus(menus);
+};
+
+scout.MenuBoxLayout.prototype.undoShrinkMenus = function(menus) {
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    if (menu.textVisibleOrig === undefined) {
+      return;
+    }
+    // Restore old text visible state
+    menu.htmlComp.suppressInvalidate = true;
+    menu.setTextVisible(menu.textVisibleOrig);
+    menu.htmlComp.suppressInvalidate = false;
+    menu.textVisibleOrig = undefined;
+  }, this);
+};
+
+scout.MenuBoxLayout.prototype.collapse = function(menus, containerSize, menusWidth) {
+  this._createAndRenderEllipsis(this.menuBox.$container);
+  this._moveOverflowMenusIntoEllipsis(containerSize, menusWidth);
+};
+
+/**
+ * Undoes the collapsing by removing ellipsis and rendering non rendered menus.
+ */
+scout.MenuBoxLayout.prototype.undoCollapse = function(menus) {
+  menus = menus || this.visibleMenus();
+  this._destroyEllipsis();
+  this._removeMenusFromEllipsis(menus, this.menuBox.$container);
+};
+
+scout.MenuBoxLayout.prototype._createAndRenderEllipsis = function($parent) {
+  var ellipsis = scout.menus.createEllipsisMenu({
+    parent: this.menuBox,
+    horizontalAlignment: 1,
+    compact: this.menuBox.compact
+  });
+  ellipsis._customCssClasses = this.menuBox.customMenuCssClasses;
+  ellipsis.render($parent);
+  this._ellipsis = ellipsis;
+};
+
+scout.MenuBoxLayout.prototype._destroyEllipsis = function() {
+  if (this._ellipsis) {
+    this._ellipsis.destroy();
+    this._ellipsis = null;
+  }
+};
+
+/**
+ * Moves every menu which doesn't fit into the container into the ellipsis menu
+ */
+scout.MenuBoxLayout.prototype._moveOverflowMenusIntoEllipsis = function(containerSize, menusWidth) {
+  var ellipsisSize = scout.graphics.getSize(this._ellipsis.$container, true);
+  menusWidth += ellipsisSize.width;
+  this.visibleMenus().slice().reverse().forEach(function(menu) {
+    var menuSize;
+    if (menusWidth > containerSize.width) {
+      // Menu does not fit -> move to ellipsis menu
+      menuSize = scout.graphics.getSize(menu.$container, true);
+      menusWidth -= menuSize.width;
+      scout.menus.moveMenuIntoEllipsis(menu, this._ellipsis);
+    }
+  }, this);
+};
+
+scout.MenuBoxLayout.prototype._removeMenusFromEllipsis = function(menus) {
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    scout.menus.removeMenuFromEllipsis(menu, this.menuBox.$container);
+  }, this);
+};
+
+scout.MenuBoxLayout.prototype.actualPrefSize = function(menus) {
+  var menusWidth, prefSize;
+
+  menus = menus || this.visibleMenus();
+  menusWidth = this._menusWidth(menus);
+  prefSize = scout.graphics.prefSize(this.menuBox.$container, true, {
+    useCssSize: true
+  });
+  prefSize.width = menusWidth + this.menuBox.htmlComp.getInsets().horizontal();
+
+  return prefSize;
+};
+
+/**
+ * @return the current width of all menus incl. the ellipsis
+ */
+scout.MenuBoxLayout.prototype._menusWidth = function(menus) {
+  var menusWidth = 0;
+  menus = menus || this.visibleMenus();
+  menus.forEach(function(menu) {
+    if (menu.rendered) {
+      menusWidth += menu.$container.outerWidth(true);
+    }
+  }, this);
+  if (this._ellipsis) {
+    menusWidth += this._ellipsis.$container.outerWidth(true);
+  }
+  return menusWidth;
+};
+
+scout.MenuBoxLayout.prototype.compactPrefSize = function(menus) {
+  menus = menus || this.visibleMenus();
+
+  this.undoCollapse(menus);
+  this.undoShrink(menus);
+  this.compact(menus);
+
+  return this.actualPrefSize();
+};
+
+scout.MenuBoxLayout.prototype.shrinkPrefSize = function(menus) {
+  menus = menus || this.visibleMenus();
+
+  this.undoCollapse(menus);
+  this.compact(menus);
+  this.shrink(menus);
+
+  return this.actualPrefSize();
+};
+
+scout.MenuBoxLayout.prototype.visibleMenus = function() {
+  return this.menuBox.menus.filter(function(menu) {
+    return menu.visible;
+  }, this);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menus.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menus.js
index f4f9f63..cf08fa3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menus.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menus.js
@@ -125,11 +125,6 @@
     }
   },
 
-  isButton: function(obj) {
-    // FIXME awe: check this too, move to Menu.js#isButton
-    return obj instanceof scout.Menu && obj.actionStyle === scout.Action.ActionStyle.BUTTON;
-  },
-
   showContextMenuWithWait: function(session, func) {
     var argumentsArray = Array.prototype.slice.call(arguments);
     argumentsArray.shift(); // remove argument session
@@ -144,6 +139,30 @@
     function onEventsProcessed() {
       func.apply(this, argumentsArray);
     }
+  },
+
+  createEllipsisMenu: function(options) {
+    var defaults = {
+      iconId: scout.icons.ELLIPSIS_V,
+      tabbable: false
+    };
+    options = $.extend({}, defaults, options);
+    return scout.create('Menu', options);
+  },
+
+  moveMenuIntoEllipsis: function(menu, ellipsis) {
+    menu.remove();
+    menu.overflow = true;
+    menu.overflowMenu = ellipsis;
+    ellipsis.childActions.push(menu);
+  },
+
+  removeMenuFromEllipsis: function(menu, $parent) {
+    menu.overflow = false;
+    menu.overflowMenu = null;
+    if (!menu.rendered) {
+      menu.render($parent);
+    }
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBox.css
index cb75fda..eadc26e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBox.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBox.css
@@ -30,7 +30,7 @@
   }
 
   &.shown {
-    #scout.animation-name(fade-slidein-top);
+    #scout.animation-name(fade-short-drop);
     #scout.animation-duration(0.5s);
   }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBoxController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBoxController.js
index 30218b9..5ee2e97 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBoxController.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/messagebox/MessageBoxController.js
@@ -21,8 +21,7 @@
 /**
  * Adds the given message box to this controller and renders it.
  */
-scout.MessageBoxController.prototype.registerAndRender = function(messageBoxAdapterId) {
-  var messageBox = this.session.getOrCreateModelAdapter(messageBoxAdapterId, this.displayParent);
+scout.MessageBoxController.prototype.registerAndRender = function(messageBox) {
   messageBox._setProperty('displayParent', this.displayParent);
   this.displayParent.messageBoxes.push(messageBox);
   this._render(messageBox);
@@ -31,8 +30,7 @@
 /**
  * Removes the given message box from this controller and DOM. However, the message box's adapter is not destroyed. That only happens once the message box is closed.
  */
-scout.MessageBoxController.prototype.unregisterAndRemove = function(messageBoxAdapterId) {
-  var messageBox = this.session.getModelAdapter(messageBoxAdapterId);
+scout.MessageBoxController.prototype.unregisterAndRemove = function(messageBox) {
   if (messageBox) {
     scout.arrays.remove(this.displayParent.messageBoxes, messageBox);
     this._remove(messageBox);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/Planner.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/Planner.js
index 33ce034..61b686b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/Planner.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/Planner.js
@@ -30,7 +30,6 @@
     return t;
   };
 
-  // additional modes; should be stored in model
   this.yearPanelVisible = false;
   this._addAdapterProperties(['menus']);
 };
@@ -46,7 +45,6 @@
  * @see IPlannerDisplayMode.java
  */
 scout.Planner.DisplayMode = $.extend({
-  INTRADAY: 0,
   CALENDAR_WEEK: 5,
   YEAR: 6
 }, scout.Calendar.DisplayMode);
@@ -74,6 +72,11 @@
   this._header.on('previousClick', this._onPreviousClick.bind(this));
   this._header.on('nextClick', this._onNextClick.bind(this));
   this._header.on('displayModeClick', this._onDisplayModeClick.bind(this));
+  this.menuBar = scout.create('MenuBar', {
+    parent: this,
+    menuOrder: new scout.PlannerMenuItemsOrder(this.session, 'Planner')
+  });
+  this.menuBar.bottom();
   for (var i = 0; i < this.resources.length; i++) {
     this._initResource(this.resources[i]);
   }
@@ -82,17 +85,13 @@
   this._syncViewRange(this.viewRange);
   this._syncSelectedResources(this.selectedResources);
   this._syncSelectionRange(this.selectionRange);
+  this._syncMenus(this.menus);
 
   this._tooltipSupport = new scout.TooltipSupport({
     parent: this,
     arrowPosition: 50
   });
 
-  this.menuBar = scout.create('MenuBar', {
-    parent: this,
-    menuOrder: new scout.PlannerMenuItemsOrder(this.session, 'Planner')
-  });
-  this.menuBar.bottom();
 };
 
 scout.Planner.prototype._initResource = function(resource) {
@@ -153,7 +152,6 @@
 
   this._renderViewRange();
   this._renderHeaderVisible();
-  this._renderMenus();
   this._renderYearPanelVisible(false);
   this._renderResources();
   this._renderSelectedResources();
@@ -913,13 +911,23 @@
   }
 };
 
-scout.Planner.prototype._renderMenus = function() {
+scout.Planner.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
   this._updateMenuBar();
 };
 
 scout.Planner.prototype._updateMenuBar = function() {
   var menuItems = this._filterMenus(['Planner.EmptySpace', 'Planner.Resource', 'Planner.Activity', 'Planner.Range'], true);
-  this.menuBar.updateItems(menuItems);
+  this.menuBar.setMenuItems(menuItems);
+};
+
+scout.Planner.prototype._renderMenus = function() {
+  // NOP
+};
+
+scout.Planner.prototype._removeMenus = function() {
+  // menubar takes care about removal
 };
 
 scout.Planner.prototype._filterMenus = function(allowedTypes, enableDisableKeyStroke) {
@@ -944,8 +952,6 @@
 
 scout.Planner.prototype._renderLastHourOfDay = function() {};
 
-scout.Planner.prototype._renderIntradayInterval = function() {};
-
 scout.Planner.prototype._renderAvailableDisplayModes = function() {
   // done by PlannerHeader.js
 };
@@ -979,10 +985,12 @@
     from: scout.dates.parseJsonDate(selectionRange.from),
     to: scout.dates.parseJsonDate(selectionRange.to)
   };
+  this._updateMenuBar();
 };
 
 scout.Planner.prototype._syncSelectedResources = function(selectedResources) {
   this.selectedResources = this._resourcesByIds(selectedResources);
+  this._updateMenuBar();
 };
 
 scout.Planner.prototype._renderSelectedResources = function(newIds, oldSelectedResources) {
@@ -995,11 +1003,6 @@
   this.selectedResources.forEach(function(resource) {
     resource.$resource.select(true);
   });
-
-  // Only call update menubar on property change, not necessary to call it when initializing
-  if (this.rendered) {
-    this._updateMenuBar();
-  }
 };
 
 scout.Planner.prototype._renderSelectionRange = function() {
@@ -1040,18 +1043,10 @@
       $item.addClass('selected');
     }
   }
-
-  // Only call update menubar on property change, not necessary to call it when initializing
-  if (this.rendered) {
-    this._updateMenuBar();
-  }
 };
 
 scout.Planner.prototype._renderSelectedActivity = function() {
-  // Only call update menubar on property change, not necessary to call it when initializing
-  if (this.rendered) {
-    this._updateMenuBar();
-  }
+  this._updateMenuBar();
 };
 
 scout.Planner.prototype._renderLabel = function() {
@@ -1134,6 +1129,7 @@
   if (this.rendered) {
     this._renderSelectionRange();
   }
+  this._updateMenuBar();
 };
 
 scout.Planner.prototype.selectResources = function(resources, notifyServer) {
@@ -1149,6 +1145,7 @@
   if (this.rendered) {
     this._renderSelectedResources('', oldSelection);
   }
+  this._updateMenuBar();
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
index f0613f9..ad5d023 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
@@ -70,7 +70,6 @@
  */
 scout.PlannerLayout.prototype._updateMinWidth = function() {
   var minWidth = this._minWidth(),
-    $scale = this.planner.$scale,
     $scaleTitle = this.planner.$scaleTitle,
     $timeline = this.planner.$timeline;
 
@@ -99,8 +98,8 @@
     return;
   }
 
-  $smallScaleItems = $timelineSmall.children('.scale-item'),
-    $largeScaleItems = $timelineLarge.children('.scale-item');
+  $smallScaleItems = $timelineSmall.children('.scale-item');
+  $largeScaleItems = $timelineLarge.children('.scale-item');
 
   // First loop through every item and set height to 0 in order to get the correct scrollHeight
   $largeScaleItems.each(function() {
@@ -136,8 +135,7 @@
 };
 
 scout.PlannerLayout.prototype._minWidth = function() {
-  var $scale = this.planner.$scale,
-    $scaleItemsLarge = this.planner.$timelineLarge.children('.scale-item'),
+  var $scaleItemsLarge = this.planner.$timelineLarge.children('.scale-item'),
     $scaleItemsSmall = this.planner.$timelineSmall.children('.scale-item'),
     numScaleItemsLarge = $scaleItemsLarge.length,
     numScaleItemsSmall = $scaleItemsSmall.length,
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.css
new file mode 100644
index 0000000..2393fe4
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.css
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+ @mobile-popup-title-margin-right: 30px;
+
+.mobile-popup {
+  background-color: @background-color;
+  border-top: 5px solid @active-color;
+  border-top-left-radius: @border-radius;
+  border-top-right-radius: @border-radius;
+  margin-top: 30px;
+  #scout.drop-shadow(@x: 0px, @y: 0px, @blur: 30px, @spread: 5px, @alpha: 0.5);
+
+  &.shown {
+    #scout.animation-name(slidein-bottom);
+    #scout.animation-duration(0.5s);
+  }
+
+  &.removed {
+    #scout.animation-name(slideout-bottom);
+    #scout.animation-duration(0.5s);
+  }
+}
+
+.mobile-popup-header {
+  position: absolute;
+  width: 100%;
+
+  padding-top: 10px;
+  padding-left: 20px;
+
+  & > .title {
+    #scout.overflow-ellipsis-nowrap();
+    #scout.font-text-large();
+    color: @active-color;
+    width: 100%;
+  }
+
+  & > .closer {
+    position: absolute;
+    top: 0;
+    right: 5px;
+    padding: 8px;
+  }
+
+  .mobile-popup.closable > & > .title {
+    margin-right: @mobile-popup-title-margin-right;
+    width: calc(~'100%' - @mobile-popup-title-margin-right);
+  }
+}
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.js
new file mode 100644
index 0000000..d792d2d
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopup.js
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.MobilePopup = function() {
+  scout.MobilePopup.parent.call(this);
+  this.widget;
+
+};
+scout.inherits(scout.MobilePopup, scout.Popup);
+
+scout.MobilePopup.prototype._init = function(options) {
+  scout.MobilePopup.parent.prototype._init.call(this, options);
+
+  var defaults = {
+    boundToAnchor: false,
+    windowPaddingX: 0,
+    windowPaddingY: 0,
+    closable: true,
+    animateRemoval: true
+  };
+  $.extend(this, defaults, options);
+};
+
+scout.MobilePopup.prototype._createLayout = function() {
+  return new scout.MobilePopupLayout(this);
+};
+
+/**
+ * @override Popup.js
+ */
+scout.MobilePopup.prototype.prefLocation = function($container, openingDirectionY) {
+  var popupSize = this.htmlComp.getPreferredSize(),
+    windowHeight = $container.window().height(),
+    y = Math.max(windowHeight - popupSize.height, 0);
+  return new scout.Point(0, y);
+};
+
+scout.MobilePopup.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('popup mobile-popup');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.validateRoot = true;
+  this.htmlComp.setLayout(this._createLayout());
+
+  this.$header = this.$container.appendDiv('mobile-popup-header');
+  this.$title = this.$header.appendDiv('title');
+  this.widget.render(this.$container);
+  this.widget.setParent(this);
+  this.widget.htmlComp.pixelBasedSizing = true;
+  this._renderTitle();
+  this._renderClosable();
+};
+
+scout.MobilePopup.prototype._renderClosable = function() {
+  this.$container.toggleClass('closable');
+  if (this.closable) {
+    if (this.$close) {
+      return;
+    }
+    this.$close = this.$title
+      .afterDiv('closer')
+      .on('click', this.close.bind(this));
+  } else {
+    if (!this.$close) {
+      return;
+    }
+    this.$close.remove();
+    this.$close = null;
+  }
+};
+
+scout.MobilePopup.prototype._renderTitle = function() {
+  this.$title.textOrNbsp(this.title);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopupLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopupLayout.js
new file mode 100644
index 0000000..75288d1
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/MobilePopupLayout.js
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.MobilePopupLayout = function(popup) {
+  scout.MobilePopupLayout.parent.call(this, popup);
+};
+scout.inherits(scout.MobilePopupLayout, scout.PopupLayout);
+
+scout.MobilePopupLayout.prototype.layout = function($container) {
+  scout.MobilePopupLayout.parent.prototype.layout.call(this, $container);
+
+  var htmlPopup = this.popup.htmlComp,
+    popupSize = htmlPopup.getSize(),
+    htmlWidget = this.popup.widget.htmlComp,
+    widgetSize = 0,
+    $header = this.popup.$header,
+    headerSize = 0;
+
+  popupSize = popupSize.subtract(htmlPopup.getInsets());
+  headerSize = scout.graphics.prefSize($header, true);
+  scout.graphics.setLocation($header, new scout.Point(0, 0));
+
+  widgetSize = popupSize.clone();
+  widgetSize.height -= headerSize.height;
+  htmlWidget.setLocation(new scout.Point(0, headerSize.height));
+  htmlWidget.setSize(widgetSize.subtract(htmlWidget.getMargins()));
+
+  // The first time it gets layouted, add shown class to be able to animate
+  if (!htmlPopup.layouted) {
+    htmlPopup.$comp.addClassForAnimation('shown');
+  }
+};
+
+/**
+ * @override AbstractLayout.js
+ */
+scout.MobilePopupLayout.prototype.preferredLayoutSize = function($container) {
+  var $window = this.popup.$container.window(),
+    windowSize = new scout.Dimension($window.width(), $window.height());
+
+  return windowSize;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/Popup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/Popup.js
index 01b5915..07b48af 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/Popup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/Popup.js
@@ -16,7 +16,6 @@
   this._mouseDownHandler;
   this._scrollHandler;
   this._popupOpenHandler;
-  this.openEvent;
   this.anchorBounds;
   this.$anchor;
   this.windowPaddingX;
@@ -29,6 +28,12 @@
   // hints for the layout to control whether the size should be adjusted if the popup does not fit into the window
   this.trimWidth;
   this.trimHeight;
+  // If true, anchor is considered when computing the position and size of the popup
+  this.boundToAnchor;
+  // If true, the attached mouse down handler will NOT close the popup if the anchor was clicked, the anchor is responsible to close it.
+  // This is necessary because the mousedown listener is attached to the capture phase and therefore executed before any other.
+  // If anchor was clicked, popup would already be closed and then opened again -> popup could never be closed by clicking the anchor
+  this.closeOnAnchorMousedown;
 };
 scout.inherits(scout.Popup, scout.Widget);
 
@@ -58,6 +63,8 @@
   });
   this.focusableContainer = scout.nvl(options.focusableContainer, false);
   this.scrollType = options.scrollType || 'remove';
+  this.boundToAnchor = scout.nvl(options.boundToAnchor, true);
+  this.closeOnAnchorMousedown = scout.nvl(options.closeOnAnchorMousedown, true);
 };
 
 scout.Popup.prototype._initKeyStrokeContext = function(keyStrokeContext) {
@@ -68,10 +75,10 @@
   return new scout.PopupLayout(this);
 };
 
-scout.Popup.prototype.open = function($parent, event) {
+scout.Popup.prototype.open = function($parent) {
   this._triggerPopupOpenEvent();
 
-  this._open($parent, event);
+  this._open($parent);
 
   // Focus the popup
   // It is important that this happens after layouting and positioning, otherwise we'd focus an element
@@ -100,14 +107,13 @@
   return handledScrollables;
 };
 
-scout.Popup.prototype._open = function($parent, event) {
-  this.render($parent, event);
+scout.Popup.prototype._open = function($parent) {
+  this.render($parent);
   this.revalidateLayout();
   this.position();
 };
 
-scout.Popup.prototype.render = function($parent, event) {
-  this.openEvent = event;
+scout.Popup.prototype.render = function($parent) {
   var $popupParent = $parent || this.entryPoint(this.parent.$container);
   scout.Popup.parent.prototype.render.call(this, $popupParent);
 };
@@ -139,14 +145,9 @@
   scout.Popup.parent.prototype._remove.call(this);
 };
 
-scout.Popup.prototype.close = function(event) {
-  if ((event && this.openEvent && event.originalEvent !== this.openEvent.originalEvent) || !event || !this.openEvent) {
-    if (event && event.originalEvent) { //only add removed widget when event has a originalEvent-> mouse or key events. no custom events.
-      event.originalEvent.scoutOriginalTargetWidget = this;
-    }
-    this._trigger('close', event);
-    this.remove();
-  }
+scout.Popup.prototype.close = function() {
+  this.trigger('close');
+  this.remove();
 };
 
 /**
@@ -155,15 +156,16 @@
  */
 scout.Popup.prototype._attachCloseHandler = function() {
   // Install mouse close handler
+  // The listener needs to be executed in the capturing phase -> prevents that _onMouseDown will be executed right after the popup gets opened using mouse down, otherwise the popup would be closed immediately
   this._mouseDownHandler = this._onMouseDown.bind(this);
-  this.$container.document().on('mousedown', this._mouseDownHandler);
+  this.$container.document(true).addEventListener('mousedown', this._mouseDownHandler, true); // true=the event handler is executed in the capturing phase
 
   // Install popup open close handler
   this._popupOpenHandler = this._onPopupOpen.bind(this);
   this.session.desktop.on('popupopen', this._popupOpenHandler);
 
   // Install scroll close handler
-  if (this.$anchor && this.scrollType) {
+  if (this.$anchor && this.boundToAnchor && this.scrollType) {
     this._scrollHandler = this._onAnchorScroll.bind(this);
     scout.scrollbars.onScroll(this.$anchor, this._scrollHandler);
   }
@@ -184,7 +186,7 @@
 
   // Uninstall mouse close handler
   if (this._mouseDownHandler) {
-    this.$container.document().off('mousedown', this._mouseDownHandler);
+    this.$container.document(true).removeEventListener('mousedown', this._mouseDownHandler, true);
     this._mouseDownHandler = null;
   }
 };
@@ -206,26 +208,27 @@
 scout.Popup.prototype._isMouseDownOutside = function(event) {
   var $target = $(event.target),
     targetWidget;
-  //sometimes the Jquery object is removed due to layouting or similar operations in this cases the widget should be set in scoutOriginalTargetWidget to the
-  // original event to resolve hierarchy inside the popup.
-  if (event.originalEvent && event.originalEvent.scoutOriginalTargetWidget) {
-    targetWidget = event.originalEvent.scoutOriginalTargetWidget;
-  } else {
-    targetWidget = scout.Widget.getWidgetFor($target);
+
+  if (!this.closeOnAnchorMousedown && this.$anchor && this.$anchor.isOrHas(event.target)) {
+    // 1. Often times, click on the anchor opens and 2. click closes the popup
+    // If we were closing the popup here, it would not be possible to achieve the described behavior anymore -> let anchor handle open and close.
+    return false;
   }
 
+  targetWidget = scout.Widget.getWidgetFor($target);
+
   // close the popup only if the click happened outside of the popup and its children
   // It is not sufficient to check the dom hierarchy using $container.has($target)
   // because the popup may open other popups which probably is not a dom child but a sibling
   // Also ignore clicks if the popup is covert by a glasspane
-  return !this.isOrHasWidget(targetWidget) && !this.session.focusManager.isElementCovertByGlassPane(this.$container[0]);
+  return !this.isOrHas(targetWidget) && !this.session.focusManager.isElementCovertByGlassPane(this.$container[0]);
 };
 
 /**
  * Method invoked once a mouse down event occurs outside the popup.
  */
 scout.Popup.prototype._onMouseDownOutside = function(event) {
-  this.close(event);
+  this.close();
 };
 
 /**
@@ -242,7 +245,7 @@
     this.revalidateLayout();
     this.position();
   } else if (this.scrollType === 'remove') {
-    this.close(event);
+    this.close();
   }
 };
 
@@ -254,27 +257,16 @@
   // Use case: Opening of a context menu or cell editor in a form popup
   // Also, popups covered by a glass pane (a modal dialog is open) must never be closed
   // Use case: popup opens a modal dialog. User clicks on a smartfield on this dialog -> underlying popup must not get closed
-  if (!this.isOrHasWidget(event.popup) &&
-    !event.popup.isOrHasWidget(this) &&
+  if (!this.isOrHas(event.popup) &&
+    !event.popup.isOrHas(this) &&
     !this.session.focusManager.isElementCovertByGlassPane(this.$container[0])) {
-    this.close(event);
-  }
-};
-
-/**
- * Method invoked when a KeyStroke is consumed
- */
-scout.Popup.prototype._onKeyStrokeExecuted = function(event) {
-  // check if target of key stroke is inside popup. If not-> close
-  var $target = event.$target;
-  if ($target && !$.contains(this.$container, $target)) {
     this.close();
   }
 };
 
 scout.Popup.prototype.prefLocation = function($container, openingDirectionY) {
   var x, y, anchorBounds, height, openingDirectionX;
-  if (!this.anchorBounds && !this.$anchor) {
+  if (!this.boundToAnchor || (!this.anchorBounds && !this.$anchor)) {
     return;
   }
   openingDirectionX = 'right'; // always use right at the moment
@@ -335,8 +327,8 @@
     openingDirection = 'up';
     location = this.prefLocation($container, openingDirection);
   }
-  left = location.x,
-    top = location.y;
+  left = location.x;
+  top = location.y;
   if (overlap.x > 0) {
     // Move popup to the left until it gets fully visible
     left -= overlap.x;
@@ -384,7 +376,7 @@
  * Popups with an anchor must only be visible if the anchor is in view (prevents that the popup points at an invisible anchor)
  */
 scout.Popup.prototype._validateVisibility = function() {
-  if (!this.$anchor) {
+  if (!this.boundToAnchor || !this.$anchor) {
     return;
   }
   var inView = this._isInView();
@@ -396,7 +388,7 @@
 };
 
 scout.Popup.prototype._isInView = function() {
-  if (!this.$anchor) {
+  if (!this.boundToAnchor || !this.$anchor) {
     return;
   }
   var anchorBounds = this.getAnchorBounds();
@@ -411,7 +403,7 @@
  * Fire event that this popup is about to open.
  */
 scout.Popup.prototype._triggerPopupOpenEvent = function() {
-  this.session.desktop._trigger('popupopen', {
+  this.session.desktop.trigger('popupopen', {
     popup: this
   });
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupLayout.js
index 9e59d79..c1957f8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupLayout.js
@@ -15,10 +15,57 @@
 scout.inherits(scout.PopupLayout, scout.AbstractLayout);
 
 scout.PopupLayout.prototype.layout = function($container) {
-  var htmlComp = this.popup.htmlComp,
-    popupSize = new scout.Dimension(),
-    prefSize = this.preferredLayoutSize($container),
-    maxSizes = this._calcMaxSizes();
+  var popupSize,
+    htmlComp = this.popup.htmlComp,
+    prefSize = this.preferredLayoutSize($container);
+
+  if (this.popup.boundToAnchor) {
+    popupSize = this._adjustSizeWithAnchor(prefSize);
+  } else {
+    popupSize = this._adjustSize(prefSize);
+  }
+
+  scout.graphics.setSize(htmlComp.$comp, popupSize);
+};
+
+scout.PopupLayout.prototype._adjustSize = function(prefSize) {
+  var popupSize = new scout.Dimension(),
+    maxSize = this._calcMaxSize();
+
+  // Ensure the popup is not larger than max size
+  popupSize.width = Math.min(maxSize.width, prefSize.width);
+  popupSize.height = Math.min(maxSize.height, prefSize.height);
+
+  return popupSize;
+};
+
+/**
+ * Considers window boundaries.
+ *
+ * @returns {scout.Dimension}
+ */
+scout.PopupLayout.prototype._calcMaxSize = function() {
+  // Position the popup at the desired location before doing any calculations to consider the preferred bounds
+  this.popup.position(false);
+
+  var maxWidth, maxHeight,
+    htmlComp = this.popup.htmlComp,
+    windowPaddingX = this.popup.windowPaddingX,
+    windowPaddingY = this.popup.windowPaddingY,
+    popupMargins = htmlComp.getMargins(),
+    popupBounds = htmlComp.getBounds(),
+    $window = this.popup.$container.window(),
+    windowSize = new scout.Dimension($window.width(), $window.height());
+
+  maxWidth = (windowSize.width - popupMargins.horizontal() - popupBounds.x - windowPaddingX);
+  maxHeight = (windowSize.height - popupMargins.vertical() - popupBounds.y - windowPaddingY);
+
+  return new scout.Dimension(maxWidth, maxHeight);
+};
+
+scout.PopupLayout.prototype._adjustSizeWithAnchor = function(prefSize) {
+  var popupSize = new scout.Dimension(),
+    maxSize = this._calcMaxSizeAroundAnchor();
   // Decide whether the prefSize can be used or the popup needs to be shrinked so that it fits into the viewport
   // The decision is based on the preferred opening direction
   // Example: The popup would like to be opened right and down
@@ -30,33 +77,32 @@
   popupSize.width = prefSize.width;
   if (this.popup.trimWidth) {
     if (this.popup.openingDirectionX === 'right' &&
-      prefSize.width > maxSizes.right && prefSize.width > maxSizes.left) {
-      popupSize.width = Math.max(maxSizes.right, maxSizes.left);
+      prefSize.width > maxSize.right && prefSize.width > maxSize.left) {
+      popupSize.width = Math.max(maxSize.right, maxSize.left);
     } else if (this.popup.openingDirectionX === 'left' &&
-      prefSize.width > maxSizes.left && prefSize.width > maxSizes.right) {
-      popupSize.width = Math.max(maxSizes.right, maxSizes.left);
+      prefSize.width > maxSize.left && prefSize.width > maxSize.right) {
+      popupSize.width = Math.max(maxSize.right, maxSize.left);
     }
   }
   popupSize.height = prefSize.height;
   if (this.popup.trimHeight) {
     if (this.popup.openingDirectionY === 'down' &&
-      prefSize.height > maxSizes.bottom && prefSize.height > maxSizes.top) {
-      popupSize.height = Math.max(maxSizes.bottom, maxSizes.top);
+      prefSize.height > maxSize.bottom && prefSize.height > maxSize.top) {
+      popupSize.height = Math.max(maxSize.bottom, maxSize.top);
     } else if (this.popup.openingDirectionY === 'up' &&
-      prefSize.height > maxSizes.top && prefSize.height > maxSizes.bottom) {
-      popupSize.height = Math.max(maxSizes.bottom, maxSizes.top);
+      prefSize.height > maxSize.top && prefSize.height > maxSize.bottom) {
+      popupSize.height = Math.max(maxSize.bottom, maxSize.top);
     }
   }
-
-  scout.graphics.setSize(htmlComp.$comp, popupSize);
+  return popupSize;
 };
 
 /**
- * Calculates the available space around the anchor.
+ * Considers window boundaries.
  *
- * @returns {scout.Insets}
+ * @returns {scout.Dimension}
  */
-scout.PopupLayout.prototype._calcMaxSizes = function() {
+scout.PopupLayout.prototype._calcMaxSizeAroundAnchor = function() {
   var maxWidthLeft, maxWidthRight, maxHeightDown, maxHeightUp,
     htmlComp = this.popup.htmlComp,
     windowPaddingX = this.popup.windowPaddingX,
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHead.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHead.js
index 0d29d81..e68ecaf 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHead.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHead.js
@@ -81,28 +81,6 @@
 };
 
 /**
- * @override Popup.js
- */
-scout.PopupWithHead.prototype._attachCloseHandler = function() {
-  scout.PopupWithHead.parent.prototype._attachCloseHandler.call(this);
-  //The popup should be able to close when keystroke is consumed outside of popup.
-  this._popupKeyStrokeCloseHandler = this._onKeyStrokeExecuted.bind(this);
-  this.session.desktop.on('keystrokeConsumed', this._popupKeyStrokeCloseHandler);
-};
-
-/**
- * @override Popup.js
- */
-scout.PopupWithHead.prototype._detachCloseHandler = function() {
-  scout.PopupWithHead.parent.prototype._detachCloseHandler.call(this);
-  //Uninstall popup open close handler
-  if (this._popupKeyStrokeCloseHandler) {
-    this.session.desktop.off('keystrokeConsumed', this._popupKeyStrokeCloseHandler);
-    this._popupOpenHandler = null;
-  }
-};
-
-/**
  * Sets CSS classes or CSS-properties on the copied children in the head.
  */
 scout.PopupWithHead.prototype._modifyHeadChildren = function() {
@@ -133,18 +111,7 @@
 
 scout.PopupWithHead.prototype._onHeadMouseDown = function(event) {
   if (this.$head && this.$head.isOrHas(event.target)) {
-    this.close(event);
-  }
-};
-
-/**
- * Method invoked when a KeyStroke is consumed
- */
-scout.PopupWithHead.prototype._onKeyStrokeExecuted = function(event) {
-  // check if target of key stroke is inside popup. If not-> close
-  var $target = event.$target;
-  if ($target && !($target === this.$container || this.$container.find($target).length > 0)) {
-    this.close(event.keyStrokeEvent);
+    this.close();
   }
 };
 
@@ -176,7 +143,7 @@
     //when layouting menu bar menues are first removed and then newly added prevent this.$contaier = null;
     return;
   }
-  var openingDirectionX, openingDirectionY, left, top, overlap, pos;
+  var openingDirectionX, openingDirectionY, overlap, pos;
   if (!this._headVisible) {
     // If head is not visible, use default implementation and adjust $body to $container
     scout.PopupWithHead.parent.prototype._position.call(this, $container);
@@ -239,7 +206,7 @@
   this.$head.children().each(function(i) {
     var $headChild = $(this);
     var $blueprintChild = $blueprintChildren.eq(i);
-    $headChild.copyCss($blueprintChild, 'margin padding line-height border vertical-align font-size');
+    $headChild.copyCss($blueprintChild, 'margin padding line-height border vertical-align font-size display');
   });
 
   headSize = scout.graphics.getSize(this.$head, true);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHeadLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHeadLayout.js
index 04ead8b..6545d99 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHeadLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/PopupWithHeadLayout.js
@@ -40,7 +40,7 @@
 /**
  * @override
  */
-scout.PopupWithHeadLayout.prototype._calcMaxSizes = function() {
+scout.PopupWithHeadLayout.prototype._calcMaxSizeAroundAnchor = function() {
   // Position the popup at the desired location before doing any calculations,
   // but do no try to switch the position if there is not enough space
   this.popup.position(false);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopup.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopup.js
index e090b11..694e5ae 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopup.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopup.js
@@ -19,7 +19,6 @@
   this._widget;
   this._$widgetContainer;
   this._widgetContainerHtmlComp;
-
 };
 scout.inherits(scout.TouchPopup, scout.Popup);
 
@@ -31,16 +30,19 @@
 
   // clone original touch field
   // original and clone both point to the same _popup instance
-  this._field = this._touchField.cloneAdapter({
+  this._field = this._touchField.cloneAdapter(this._fieldOverrides());
+  this._initWidget(options);
+};
+
+scout.TouchPopup.prototype._fieldOverrides = function() {
+  return {
     parent: this,
     popup: this,
     labelPosition: scout.FormField.LABEL_POSITION_ON_FIELD,
     statusVisible: false,
     embedded: true,
     touch: false
-  });
-
-  this._initWidget(options);
+  };
 };
 
 scout.TouchPopup.prototype._initWidget = function(options) {
@@ -55,25 +57,31 @@
  * @override Popup.js
  */
 scout.TouchPopup.prototype.prefLocation = function($container, openingDirectionY) {
-  var popupSize = this.htmlComp._layout.preferredLayoutSize($container),
-    screenWidth = $container.document().width(),
-    x = Math.max(0, (screenWidth - popupSize.width) / 2);
+  var popupSize = this.htmlComp.getPreferredSize(),
+    windowWidth = $container.window().width(),
+    x = Math.max(this.windowPaddingX, (windowWidth - popupSize.width) / 2);
   return new scout.Point(x, scout.TouchPopup.TOP_MARGIN);
 };
 
 scout.TouchPopup.prototype._render = function($parent) {
   this.$container = $parent.appendDiv('touch-popup');
     //    .on('mousedown', this._onContainerMouseDown.bind(this)) // FIXME awe: (popups) is this line required?
-  this._field.render(this.$container);
 
   this._$widgetContainer = this.$container.appendDiv('widget-container');
   this._widgetContainerHtmlComp = new scout.HtmlComponent(this._$widgetContainer, this.session);
   this._widgetContainerHtmlComp.setLayout(new scout.SingleLayout());
 
+  // field may render something into the widget container -> render after widget container and move to correct place
+  this._field.render(this.$container);
+
+  // Move to top
+  this._field.$container.insertBefore(this._$widgetContainer);
+
   if (this._widget) {
     this._widget.render(this._$widgetContainer);
   }
 
   this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.validateRoot = true;
   this.htmlComp.setLayout(this._createLayout());
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopupLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopupLayout.js
index e396653..a8833dd 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopupLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/popup/TouchPopupLayout.js
@@ -16,9 +16,9 @@
 scout.TouchPopupLayout.prototype.layout = function($container) {
   scout.TouchPopupLayout.parent.prototype.layout.call(this, $container);
 
-  var field = this.popup._field,
+  var popupSize = this.popup.htmlComp.getSize(),
+    field = this.popup._field,
     fieldMargins = new scout.Insets(4, 6, 5, 4),
-    popupSize = this.popup.htmlComp.getSize(),
     fieldHeight = field.htmlComp.getPreferredSize().height,
     fieldWidth = popupSize.width - fieldMargins.horizontal(),
     widgetVerticalOffset = fieldHeight + fieldMargins.vertical();
@@ -32,16 +32,8 @@
  * @override AbstractLayout.js
  */
 scout.TouchPopupLayout.prototype.preferredLayoutSize = function($container) {
-  var $document = $container.document(),
-    screenWidth = $document.width(),
-    screenHeight = $document.height(),
-    minPopupWidth = scout.HtmlEnvironment.formColumnWidth / 2,
-    maxPopupHeight = scout.HtmlEnvironment.formRowHeight * 15,
-    popupWidth = scout.HtmlEnvironment.formColumnWidth,
-    popupHeight = screenHeight / 2 - scout.TouchPopup.TOP_MARGIN;
-
-  popupWidth = Math.max(popupWidth, minPopupWidth);
-  popupHeight = Math.min(popupHeight, maxPopupHeight);
+  var popupWidth = scout.HtmlEnvironment.formColumnWidth,
+    popupHeight = scout.HtmlEnvironment.formRowHeight * 15;
 
   return new scout.Dimension(popupWidth, popupHeight);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/Scrollbar.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/Scrollbar.css
index 38910cb..a33218d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/Scrollbar.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/Scrollbar.css
@@ -15,7 +15,7 @@
 
 .scrollbar {
   position: absolute;
-  z-index: 10;
+  z-index: 1;
   cursor: pointer;
 
   &.y-axis {
@@ -43,7 +43,6 @@
 
 .scrollbar-thumb {
   position: absolute;
-  z-index: 11;
   cursor: pointer;
   border-radius: 4px;
   background-color: fade(@scrollbar-thumb-color, 30%);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
index 0711a74..2405fd8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/scrollbar/scrollbars.js
@@ -87,7 +87,13 @@
       nativeScrollbars = scout.device.hasPrettyScrollbars();
     }
     if (nativeScrollbars) {
-      installNativeScrollbars();
+      if (scout.device.isIos()) {
+        // On ios, container sometimes is not scrollable when installing too early
+        // Happens often with nested scrollable containers (e.g. scrollable table inside a form inside a scrollable tree data)
+        setTimeout(installNativeScrollbars);
+      } else {
+        installNativeScrollbars();
+      }
     } else {
       installJsScrollbars();
     }
@@ -236,8 +242,7 @@
       elementBounds = scout.graphics.offsetBounds($element, false, false),
       scrollableBounds = scout.graphics.offsetBounds($scrollable, false, false),
       elementTop = elementBounds.y - scrollableBounds.y - scrollOffsetUp,
-      elementH = elementBounds.height + scrollOffsetDown,
-      scrollbars;
+      elementH = elementBounds.height + scrollOffsetDown;
 
     //There are some elements which has a hight of 0 (Checkboxes / Radiobuttons) -> try to get field and figure out its height and offset
     if (elementH === scrollOffsetDown && $element.data('valuefield') && $element.data('valuefield').$container) {
@@ -265,8 +270,7 @@
       scrollableW = $scrollable.width(),
       elementBounds = scout.graphics.bounds($element, true, true),
       elementLeft = elementBounds.x,
-      elementW = elementBounds.width,
-      scrollbars;
+      elementW = elementBounds.width;
 
     if (elementLeft < 0) {
       scout.scrollbars.scrollLeft($scrollable, $scrollable.scrollLeft() + elementLeft);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/BusyIndicator.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/BusyIndicator.js
index 77d24c2..74965d8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/BusyIndicator.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/BusyIndicator.js
@@ -82,7 +82,7 @@
 };
 
 scout.BusyIndicator.prototype._onClickCancel = function(event) {
-  this.events.trigger('cancel', event);
+  this.trigger('cancel', event);
 };
 
 scout.BusyIndicator.prototype._postRender = function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/ModelAdapter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/ModelAdapter.js
similarity index 92%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/ModelAdapter.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/session/ModelAdapter.js
index 3a77d42..7da593a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/ModelAdapter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/ModelAdapter.js
@@ -98,21 +98,13 @@
  * @param coalesceFunc (optional) coalesce function added to event-object
  */
 scout.ModelAdapter.prototype._send = function(type, data, delay, coalesceFunc) {
-  var adapter = this,
-    adapterId = this.id;
-
   // If adapter is a clone, get original adapter and get its id
-  while (adapter.cloneOf) {
-    adapter = adapter.cloneOf;
-    adapterId = adapter.id;
-  }
-
-  var event = new scout.Event(adapterId, type, data);
+  var adapter = this.original();
+  var event = new scout.Event(adapter.id, type, data);
   if (coalesceFunc) {
     event.coalesce = coalesceFunc;
   }
   adapter.remoteHandler(event, delay);
-  this.trigger('send', event);
 };
 
 /**
@@ -344,50 +336,6 @@
   this._fireBulkPropertyChange(oldProperties, event.properties);
 };
 
-scout.ModelAdapter.prototype._fireBulkPropertyChange = function(oldProperties, newProperties) {
-  var propertyChangeEvent = {
-    newProperties: newProperties,
-    oldProperties: oldProperties,
-    changedProperties: []
-  };
-  // To allow a listener to react only to properties that have really changed their value, we
-  // calculate the list of "changedProperties". This may be relevant, when the value on the model
-  // changes from A to B and back to A, which emits a property change event when in fact, the
-  // property has not really changed for the UI.
-  for (var prop in newProperties) {
-    if (newProperties[prop] !== oldProperties[prop]) {
-      propertyChangeEvent.changedProperties.push(prop);
-    }
-  }
-  this.trigger('propertyChange', propertyChangeEvent);
-};
-
-/**
- * Fires a property change for a single property.
- */
-scout.ModelAdapter.prototype._firePropertyChange = function(propertyName, oldValue, newValue) {
-  if (!propertyName) {
-    return;
-  }
-  var oldProperties = {},
-    newProperties = {};
-  oldProperties[propertyName] = oldValue;
-  newProperties[propertyName] = newValue;
-  this._fireBulkPropertyChange(oldProperties, newProperties);
-};
-
-/**
- * Sets the value of the property 'propertyName' to 'newValue' and then fires a propertyChange event for that property.
- */
-scout.ModelAdapter.prototype._setProperty = function(propertyName, newValue) {
-  if (!propertyName) {
-    return;
-  }
-  var oldValue = this[propertyName];
-  this[propertyName] = newValue;
-  this._firePropertyChange(propertyName, oldValue, newValue);
-};
-
 /**
  * The default impl. only logs a warning that the event is not supported.
  */
@@ -403,6 +351,7 @@
 
     if (isAdapterProp) {
       if (oldValue) {
+        // TODO CGU this should actually be configurable, otherwise m_disposeOnChange=false on server doesn't work
         this._destroyAdapters(propertyName, oldValue, value);
       }
       if (value) {
@@ -441,7 +390,7 @@
       if (!this[renderFuncName]) {
         throw new Error('Render function ' + renderFuncName + ' does not exist in ' + this.toString());
       }
-      // FIXME awe, cgu: value and oldValue should be switched to conform with other functions.
+      // TODO awe, cgu: (model-adapter) value and oldValue should be switched to conform with other functions.
       // Or better create remove function as it is done with adapters? currently only "necessary" for AnalysisTableControl
       // Input von 08.04.15: z.Z. wird die _renderXxx Methode sehr uneinheitlich verwendet. Manche mit ohne Parameter, andere mit
       // 1 oder 2 Parameter. Dann gibt es noch Fälle (DateField.js) bei denen es nötig ist, render aufzurufen, aber mit einem
@@ -618,6 +567,17 @@
   return cloneAdapter;
 };
 
+/**
+ * @returns the original adapter from which this one was cloned. If it is not a clone, itself is returned.
+ */
+scout.ModelAdapter.prototype.original = function() {
+  var original = this;
+  while (original.cloneOf) {
+    original = original.cloneOf;
+  }
+  return original;
+};
+
 scout.ModelAdapter.prototype._isModelProperty = function(propertyName) {
   return this._modelProperties.indexOf(propertyName) > -1;
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/Session.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/Session.js
index 6782ca6..0f09785 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/Session.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/Session.js
@@ -22,10 +22,6 @@
  *     (which is the default case), the clientSessionId is taken from the browser's
  *     session storage (per browser window, survives F5 refresh of page). If no
  *     clientSessionId can be found, a new one is generated on the server.
- *   [forceNewClientSession]
- *     Optional, default is false. If this argument is true, any existing
- *     "clientSessionId" is ignored, which causes the server to always create a
- *     new client session.
  *   [userAgent]
  *     Default: DESKTOP
  *   [backgroundJobPollingEnabled]
@@ -36,9 +32,6 @@
  *     use setTimeout(), sometimes the Jasmine-Maven plug-in fails and aborts the
  *     build because there were console errors. These errors always happen in this
  *     class. That's why we can skip suppress error handling with this flag.
- *   [uiUseTaskbarLogo]
- *     If true, the desktop will add a small logo to the taskbar. It is styled with
- *     the CSS class ".taskbar-logo". Defaults to false.
  *   [focusManagerActive]
  *     Forces the focus manager to be active or not. If undefined, the value is
  *     auto detected by Device.js.
@@ -48,16 +41,20 @@
 
   // Prepare clientSessionId
   var clientSessionId = options.clientSessionId || sessionStorage.getItem('scout:clientSessionId');
-  if (options.forceNewClientSession) {
+
+  this.scoutUrl = new scout.URL();
+  if (this.scoutUrl.getParameter('forceNewClientSession')) {
     clientSessionId = null;
+    this._forceNewClientSession = true;
   }
 
+
   // Set members
   this.$entryPoint = $entryPoint;
   this.uiSessionId; // assigned by server on session init (OWASP recommendation, see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern).
   this.partId = scout.nvl(options.portletPartId, 0);
   this.clientSessionId = clientSessionId;
-  this.userAgent = options.userAgent || new scout.UserAgent(scout.device.type);
+  this.userAgent = options.userAgent || new scout.UserAgent(scout.device.type, scout.device.supportsTouch());
   this.suppressErrors = scout.nvl(options.suppressErrors, false);
   this.modelAdapterRegistry = {};
   this._clonedModelAdapterRegistry = {}; // key = adapter-ID, value = array of clones for that adapter
@@ -82,7 +79,6 @@
   this._backgroundJobPollingSupport = new scout.BackgroundJobPollingSupport(scout.nvl(options.backgroundJobPollingEnabled, true));
   this._fatalMessagesOnScreen = {};
   this._loggedOut = false;
-  this.uiUseTaskbarLogo = options.uiUseTaskbarLogo;
 
   this.rootAdapter = new scout.ModelAdapter();
   this.rootAdapter.init({
@@ -226,9 +222,7 @@
   if (this.clientSessionId) {
     request.clientSessionId = this.clientSessionId;
   }
-  if (this.userAgent.deviceType !== scout.Device.Type.DESKTOP) {
-    request.userAgent = this.userAgent;
-  }
+  request.userAgent = this.userAgent;
   request.sessionStartupParams = this._createSessionStartupParams();
 
   // Send request
@@ -255,11 +249,9 @@
  */
 scout.Session.prototype._createSessionStartupParams = function() {
   var params = {};
+  params.url = this.scoutUrl.baseUrlRaw;
 
-  var scoutUrl = new scout.URL();
-  params.url = scoutUrl.baseUrlRaw;
-
-  var urlParameterMap = scoutUrl.parameterMap;
+  var urlParameterMap = this.scoutUrl.parameterMap;
   for (var prop in urlParameterMap) {
     params[prop] = urlParameterMap[prop];
   }
@@ -322,8 +314,9 @@
       }
     }
 
-    // Ensure layout is valid
+    // Ensure layout is valid (explicitly layout immediately and don't wait for setTimeout to run to make layouting invisible to the user)
     this.layoutValidator.validate();
+    this.focusManager.validateFocus();
 
     // Start poller
     this._resumeBackgroundJobPolling();
@@ -1169,6 +1162,7 @@
 
 scout.Session.prototype._renderDesktop = function() {
   this.desktop.render(this.$entryPoint);
+  this.desktop.invalidateLayoutTree(false);
   this._setApplicationLoading(false);
 };
 
@@ -1178,14 +1172,18 @@
 
 scout.Session.prototype.logout = function(logoutUrl) {
   this._loggedOut = true;
-  // remember current url to not lose query parameters
-  sessionStorage.setItem('scout:loginUrl', window.location.href);
-  // Clear everything and reload the page. We wrap that in setTimeout() to allow other events to be executed normally before.
-  setTimeout(function() {
-    scout.reloadPage({
-      redirectUrl: logoutUrl
-    });
-  }.bind(this));
+  if (this._forceNewClientSession) {
+    this.desktop.$container.window(true).close();
+  } else {
+    // remember current url to not lose query parameters
+    sessionStorage.setItem('scout:loginUrl', window.location.href);
+    // Clear everything and reload the page. We wrap that in setTimeout() to allow other events to be executed normally before.
+    setTimeout(function() {
+      scout.reloadPage({
+        redirectUrl: logoutUrl
+      });
+    }.bind(this));
+  }
 };
 
 scout.Session.prototype._onDisposeAdapter = function(event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/UserAgent.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/UserAgent.js
index 9efe8c8..a6e5d8e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/UserAgent.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/session/UserAgent.js
@@ -8,9 +8,10 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.UserAgent = function(deviceType) {
+scout.UserAgent = function(deviceType, touch) {
   if (!deviceType) {
     throw new Error('deviceType needs to be defined');
   }
   this.deviceType = deviceType;
+  this.touch = scout.nvl(touch, false);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.css
new file mode 100644
index 0000000..c0473e9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.css
@@ -0,0 +1,32 @@
+.slider-input {
+  display: inline-block;
+  vertical-align: middle;
+  border: none;
+
+  &:focus {
+    &::-webkit-slider-runnable-track {
+      background: @active-color;
+    }
+    border: none;
+    box-shadow: none;
+  }
+
+  &::-webkit-slider-runnable-track {
+    height: 3px;
+    cursor: pointer;
+    background: @slider-track-color;
+  }
+
+  &::-webkit-slider-thumb {
+    margin-top: -8px;
+  }
+}
+
+.slider-value {
+  display: inline-block;
+  vertical-align: middle;
+  color: @control-color;
+  padding-left: 6px;
+  padding-top: @borderless-field-padding-y;
+  padding-bottom: @borderless-field-padding-y;
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.js
new file mode 100644
index 0000000..3831798
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/Slider.js
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.Slider = function() {
+  scout.Slider.parent.call(this);
+
+  this.value;
+  this.minValue;
+  this.maxValue;
+  this.step;
+
+  this._addEventSupport();
+};
+scout.inherits(scout.Slider, scout.Widget);
+
+scout.Slider.prototype._init = function(options) {
+  scout.Slider.parent.prototype._init.call(this, options);
+  this.value = options.value;
+  this.minValue = options.minValue;
+  this.maxValue = options.maxValue;
+  this.step = options.step;
+};
+
+scout.Slider.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('slider');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.SliderLayout(this));
+  this.$sliderInput = this.$container.appendElement('<input>', 'slider-input')
+    .attr('type', 'range')
+    .on('change', this._onValueChange.bind(this));
+
+  this.$sliderValue = this.$container
+    .appendSpan('slider-value', this.value);
+};
+
+scout.Slider.prototype._renderProperties = function() {
+  this._renderValue();
+  this._renderMinValue();
+  this._renderMaxValue();
+  this._renderStep();
+};
+
+scout.Slider.prototype._renderValue = function() {
+  var value = scout.nvl(this.value, 0);
+  this.$sliderInput.val(value);
+  this.$sliderValue.text(value);
+};
+
+scout.Slider.prototype._renderMinValue = function() {
+  if (this.minValue) {
+    this.$sliderInput.attr('min', this.minValue);
+  } else {
+    this.$sliderInput.removeAttr('min');
+  }
+};
+
+scout.Slider.prototype._renderMaxValue = function() {
+  if (this.maxValue) {
+    this.$sliderInput.attr('max', this.maxValue);
+  } else {
+    this.$sliderInput.removeAttr('max');
+  }
+};
+
+scout.Slider.prototype._renderStep = function() {
+  if (this.step) {
+    this.$sliderInput.attr('step', this.step);
+  } else {
+    this.$sliderInput.removeAttr('step');
+  }
+};
+
+scout.Slider.prototype._onValueChange = function(event) {
+  this.setValue(this.$sliderInput.val());
+};
+
+scout.Slider.prototype.setValue = function(value) {
+  if (value === this.value) {
+    return;
+  }
+  this._setProperty('value', value);
+  if (this.rendered) {
+    this._renderValue();
+  }
+};
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/SliderLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/SliderLayout.js
new file mode 100644
index 0000000..aee61b2
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/slider/SliderLayout.js
@@ -0,0 +1,11 @@
+scout.SliderLayout = function(slider) {
+  scout.SliderLayout.parent.call(this);
+  this.slider = slider;
+};
+scout.inherits(scout.SliderLayout, scout.AbstractLayout);
+
+scout.SliderLayout.prototype.layout = function($container) {
+  var size = scout.graphics.getSize($container);
+  this.slider.$sliderInput.css('height', size.height);
+  this.slider.$sliderValue.css('height', size.height);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.css
index 8671b52..7d03f19 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.css
@@ -9,14 +9,38 @@
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
 .splitter {
+  @splitter-line-size: 2px;
+  @splitter-size: 16px;
+
   position: absolute;
-  z-index: 1;
 
   /* | */
   &.x-axis {
     top: 0px;
     height: 100%;
-    width: 16px;
+    width: @splitter-size;
     cursor: col-resize;
+
+    &.line {
+    padding-right: floor((@splitter-size - @splitter-line-size) / 2);
+    padding-left: ceil((@splitter-size - @splitter-line-size) / 2);
+    }
+  }
+   &.y-axis {
+    left: 0px;
+    width: 100%;
+    height: @splitter-size;
+    cursor: row-resize;
+    &.line {
+        padding-top: floor((@splitter-size - @splitter-line-size) / 2);
+    padding-bottom: ceil((@splitter-size - @splitter-line-size) / 2);
+    }
+  }
+  &.line{
+    background-clip: content-box;
+    background-color: @border-color;
+    &:hover {
+      background-color: @hover-color;
+    }
   }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.js
index eb37aa7..dbc6ed4 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/splitter/Splitter.js
@@ -10,24 +10,21 @@
  ******************************************************************************/
 scout.Splitter = function() {
   scout.Splitter.parent.call(this);
-
   this.splitHorizontal;
   this.$anchor;
   this._$root;
-  this._maxRatio;
-  this._oldRatio;
+  this.ratio;
   this.position; // current splitter position in pixels, updated by updatePosition()
+  this._cursorOffset = 0; // distance from cursor to splitter, makes resizing smoother by preventing initial 'jump'
   this._addEventSupport();
 };
 scout.inherits(scout.Splitter, scout.Widget);
 
 scout.Splitter.prototype._init = function(options) {
   scout.BusyIndicator.parent.prototype._init.call(this, options);
-
   this.splitHorizontal = scout.nvl(options.splitHorizontal, true);
   this.$anchor = options.$anchor;
   this._$root = options.$root;
-  this._maxRatio = options.maxRatio;
 };
 
 scout.Splitter.prototype._render = function($parent) {
@@ -38,14 +35,23 @@
   this._$body = $parent.body();
 };
 
+scout.Splitter.prototype.getPosition = function() {
+  return this.position;
+};
+
+scout.Splitter.prototype.getRatio = function() {
+  return this.ratio;
+};
 /**
  * Sets the splitter position to the specified newSize (in pixels). If the newSize is
  * not specified, the size is calculated automatically by reading the this.$anchor
  * element's bounds.
  *
+ * @returns the effective position in pixel.
  * Note: This function does not fire any events.
  */
-scout.Splitter.prototype.updatePosition = function(newPosition) {
+scout.Splitter.prototype.setPosition = function(newPosition, updateRatio, firePositionChanged) {
+
   if (!$.isNumeric(newPosition)) {
     // Get size automatically from $anchor element's bounds
     var anchorBounds = scout.graphics.offsetBounds(this.$anchor);
@@ -55,67 +61,101 @@
       newPosition = anchorBounds.y + anchorBounds.height;
     }
   }
-
-  // Set the new position (center splitter around 'newPosition')
-  var splitterSize = scout.graphics.getVisibleSize(this.$container, true);
-  if (this.splitHorizontal) {
-    this.$container.cssLeft(newPosition - (splitterSize.width / 2));
-  } else {
-    this.$container.cssTop(newPosition - (splitterSize.height / 2));
+  if (newPosition === this.position) {
+    return;
   }
-  this.position = newPosition;
+
+  this._setPosition(newPosition, updateRatio, firePositionChanged);
+  return newPosition;
 };
 
+scout.Splitter.prototype._setPosition = function(newPosition, updateRatio, firePositionChanged) {
+  firePositionChanged = scout.nvl(firePositionChanged, true);
+  if (!$.isNumeric(newPosition)) {
+    return;
+  }
+  if (newPosition === this.position) {
+    return;
+  }
+  if (updateRatio) {
+    if (this.splitHorizontal) {
+      this.ratio = newPosition / this._$root.outerWidth(true);
+    } else {
+      this.ratio = newPosition / this._$root.outerHeight(true);
+    }
+  }
+  this.position = newPosition;
+  var positionChangedEvent = {
+    position: newPosition
+  };
+  if (firePositionChanged) {
+    this.trigger('positionChanged', positionChangedEvent);
+  }
+  if (this.rendered) {
+    // Set the new position (center splitter around 'newPosition')
+    var splitterSize = scout.graphics.getVisibleSize(this.$container, true);
+    if (this.splitHorizontal) {
+      this.$container.cssLeft(newPosition - (splitterSize.width / 2));
+    } else {
+      this.$container.cssTop(newPosition - (splitterSize.height / 2));
+    }
+  }
+};
 scout.Splitter.prototype._onMouseDown = function(event) {
+  var splitterCenter = scout.graphics.offsetBounds(this.$container, true).center();
+
   // Add listeners (we add them to the window to make sure we get the mouseup event even when the cursor it outside the window)
   this._$window
     .on('mousemove.splitter', this._onMouseMove.bind(this))
     .one('mouseup', this._onMouseUp.bind(this));
   // Ensure the correct cursor is always shown while moving
   this._$body.addClass(this.splitHorizontal ? 'col-resize' : 'row-resize');
-  this.trigger('resizestart', event);
+  this._cursorOffset = {
+    left: splitterCenter.x - event.pageX,
+    top: splitterCenter.y - event.pageY
+  };
+  this.trigger('moveStart', {
+    position: this._getSplitterPosition(event)
+  });
   // Prevent text selection in a form
   event.preventDefault();
 };
 
-scout.Splitter.prototype._ratio = function(event) {
-  var splitterBounds = scout.graphics.offsetBounds(this.$container),
-    rootBounds = scout.graphics.offsetBounds(this._$root);
-  var ratio, rootSize;
+scout.Splitter.prototype._getSplitterPosition = function(event) {
+  var rootBounds = scout.graphics.offsetBounds(this._$root);
   if (this.splitHorizontal) {
-    rootSize = rootBounds.width;
-    ratio = (event ? event.pageX : splitterBounds.x) / rootBounds.width;
+    return event.pageX + this._cursorOffset.left - rootBounds.x;
   } else {
-    rootSize = rootBounds.height;
-    ratio = (event ? event.pageY : splitterBounds.y) / rootBounds.height;
+    return event.pageY + this._cursorOffset.top - rootBounds.y;
   }
-  return {
-    ratio: ratio,
-    rootSize: rootSize
-  };
 };
 
 scout.Splitter.prototype._onMouseMove = function(event) {
-  var obj = this._ratio(event),
-    ratio = obj.ratio;
-  if (ratio >= this._maxRatio) {
-    ratio = this._maxRatio;
+  var splitterPosition = this._getSplitterPosition(event);
+  // fire event
+  var positionChangeEvent = {
+    position: splitterPosition,
+    defaultPrevented: false,
+    preventDefault: function() {
+      this.defaultPrevented = true;
+    },
+    setPosition: function (newPosition) {
+      this.position = newPosition;
+    }
+
+  };
+  this.trigger('move', positionChangeEvent);
+  if (positionChangeEvent.defaultPrevented) {
+    return;
   }
-  if (ratio !== this._oldRatio) {
-    var newPosition = Math.floor(ratio * obj.rootSize);
-    this.updatePosition(newPosition);
-    this.trigger('resize', {
-      data: newPosition
-    });
-    this._oldRatio = ratio;
-  }
+  this._setPosition(positionChangeEvent.position, true);
 };
 
 scout.Splitter.prototype._onMouseUp = function(event) {
   // Remove listeners and reset cursor
   this._$window.off('mousemove.splitter');
   this._$body.removeClass((this.splitHorizontal ? 'col-resize' : 'row-resize'));
-  this.trigger('resizeend', {
-    data: this.position
+  this.trigger('moveEnd', {
+    position: this.position
   });
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/animations.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/animations.css
index 42f85a1..828672a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/animations.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/animations.css
@@ -10,6 +10,9 @@
  ******************************************************************************/
 #scout {
 
+  /* Hint: YUI replaces 0% with 0 when compressing the css. This breaks the animations.
+  Workaround: Don't use 0%, always use 00%. */
+
   /* args = keyframeName, timingFunction, iterationCount */
   .animation(@args) {
     -webkit-animation: @args;
@@ -95,10 +98,10 @@
   @-webkit-keyframes fadeOut { .keyframes-fade-out(); }
   @keyframes fadeOut { .keyframes-fade-out(); }
 
-  /*** Fade In Top ***/
+  /*** Fade with Short Drop ***/
 
-  .keyframes-fade-slidein-top() {
-    0% {
+  .keyframes-fade-short-drop() {
+    00% {
       margin-top: -40px;
       opacity: 0;
     }
@@ -112,13 +115,49 @@
     }
   }
 
-  @-webkit-keyframes fade-slidein-top { .keyframes-fade-slidein-top(); }
-  @keyframes fade-slidein-top { .keyframes-fade-slidein-top(); }
+  @-webkit-keyframes fade-short-drop { .keyframes-fade-short-drop(); }
+  @keyframes fade-short-drop { .keyframes-fade-short-drop(); }
+
+  /*** Slide In Bottom ***
+       Moves the element into screen from bottom up */
+
+  .keyframes-slidein-bottom() {
+    00% {
+      #scout.transform(translateY(100%));
+    }
+  }
+
+  @-webkit-keyframes slidein-bottom { .keyframes-slidein-bottom(); }
+  @keyframes slidein-bottom { .keyframes-slidein-bottom(); }
+
+  /*** Slide Out Bottom ***
+       Moves the element out of bottom screen border */
+
+  .keyframes-slideout-bottom() {
+    100% {
+      #scout.transform(translateY(100%));
+    }
+  }
+
+  @-webkit-keyframes slideout-bottom { .keyframes-slideout-bottom(); }
+  @keyframes slideout-bottom { .keyframes-slideout-bottom(); }
+
+  /*** Slide Out Right ***
+       Moves the element out of right screen border */
+
+  .keyframes-slideout-right() {
+    100% {
+      #scout.transform(translateX(100%));
+    }
+  }
+
+  @-webkit-keyframes slideout-right { .keyframes-slideout-right(); }
+  @keyframes slideout-right { .keyframes-slideout-right(); }
 
   /*** Zoom Bounce ***/
 
   .keyframes-zoom-bounce() {
-    0% {
+    00% {
       #scout.transform(scale(0.75, 0.75));
     }
     25% {
@@ -135,7 +174,7 @@
   /*** Rotation ***/
 
   .keyframes-rotation () {
-    0% {
+    00% {
       #scout.transform(rotate(0deg));
     }
     100% {
@@ -149,7 +188,7 @@
   /*** Rotation-Reverse ***/
 
   .keyframes-rotation-reverse () {
-    0% {
+    00% {
       #scout.transform(rotate(-0deg));
     }
     100% {
@@ -163,7 +202,7 @@
   /*** Pulse Opacity ***/
 
   .keyframes-pulse-opacity () {
-    0% {
+    00% {
       opacity: 1.0;
     }
     50% {
@@ -180,7 +219,7 @@
   /*** Pulsate ***/
 
   .keyframes-pulsate () {
-    0% {
+    00% {
       #scout.transform(scale(0.1));
       opacity: 0.0;
     }
@@ -199,7 +238,7 @@
   /*** Attention ***/
 
   .keyframes-attention () {
-    0% {
+    00% {
       #scout.transform(scale3d(1, 1, 1));
     }
     10% {
@@ -219,7 +258,7 @@
   /*** Rotate-X ***/
 
   .keyframes-rotate-x () {
-    0% {
+    00% {
       #scout.transform(perspective(120px) rotateY(0deg));
     }
     50% {
@@ -236,7 +275,7 @@
   /*** Animate Dot ***/
 
   .keyframes-animate-dot () {
-    0%   { color: @text-color;     bottom:0px; }
+    00%   { color: @text-color;     bottom:0px; }
     25%  { color: @palette-gray-5; bottom:4px; }
     50%  { color: @text-color;     bottom:0px; }
     100% { color: @text-color;     bottom:0px; }
@@ -256,7 +295,7 @@
   }
 
   .keyframes-shake() {
-    0% { #scout.transform(translate(2px, 1px) rotate(0deg)); }
+    00% { #scout.transform(translate(2px, 1px) rotate(0deg)); }
     10% { #scout.transform(translate(-1px, -2px) rotate(-1deg)); }
     20% { #scout.transform(translate(-3px, 0px) rotate(1deg)); }
     30% { #scout.transform(translate(0px, 2px) rotate(0deg)); }
@@ -282,7 +321,7 @@
   }
 
   .keyframes-flash-gray() {
-    0% { background-color: @palette-white; }
+    00% { background-color: @palette-white; }
     25% { background-color: @palette-gray-5; }
     50% { background-color: @palette-white; }
     75% { background-color: @palette-gray-5; }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/colors.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/colors.css
index 0bc7aa7..03e35ea 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/colors.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/colors.css
@@ -143,6 +143,10 @@
 @calendar-weekend-out-background-color: none;
 @calendar-weekend-out-color: @palette-blue-2;
 @checkbox-disabled-color: @palette-gray-6;
+@collapse-handle-active-background-color: @palette-blue-1;
+@collapse-handle-background-color: @palette-white;
+@collapse-handle-border-color: @active-color;
+@collapse-handle-color: @active-color;
 @column-background-effect-gradient1-start-background-color: @palette-red-2;
 @column-background-effect-gradient1-end-background-color: @palette-green-1;
 @column-background-effect-gradient2-start-background-color: @palette-green-1;
@@ -156,11 +160,19 @@
 @default-button-background-color: @palette-blue-4;
 @default-button-color: @palette-white;
 @default-button-hover-background-color: @default-button-background-color;
-@desktop-table-header-background-color: @table-header-background-color;
-@desktop-taskbar-background-color: @palette-white;
+@desktop-navigation-handle-active-background-color: @outline-group-background-color;
+@desktop-navigation-handle-background-color: @navigation-background-color;
+@desktop-navigation-handle-border-color: @desktop-navigation-handle-color;
+@desktop-navigation-handle-color: @navigation-color;
+@desktop-header-background-color: @palette-white;
+@detail-table-header-background-color: @table-header-background-color;
 @form-background-color: @background-color;
-@form-tool-popup-main-menubar-background-color: @menubar-background-color;
+@form-menu-popup-main-menubar-background-color: @menubar-background-color;
 @group-box-title-border-color: @border-color;
+@header-view-button-tab-active-background-color: @view-tab-active-background-color;
+@header-view-button-tab-active-color: @view-tab-active-color;
+@header-view-button-tab-background-color: @navigation-background-color;
+@header-view-button-tab-color: @view-button-tab-active-color;
 @key-box-background-color: @palette-orange-2;
 @key-box-border-color: @key-box-background-color;
 @key-box-color: @palette-black;
@@ -181,10 +193,12 @@
 @navigate-up-button-color: @menubar-button-color;
 @navigation-background-color: @palette-bluegray-4;
 @navigation-color: @palette-gray-3;
+@outline-breadcrumb-border-color: @outline-selection-background-color;
 @outline-group-background-color: @palette-bluegray-3;
 @outline-in-background-selection-background-color: @palette-bluegray-2;
 @outline-selection-background-color: @background-color;
 @outline-selection-color: @text-color;
+@outline-title-border-color: @outline-selection-background-color;
 @planner-mode-active-text-color: @palette-blue-7;
 @planner-timeline-background-color: @panel-background-color;
 @popup-border-color: @palette-blue-6;
@@ -223,6 +237,7 @@
 @table-row-checked-background-color: @palette-blue-5;
 @table-row-checked-selected-focus-background-color: lighten(@palette-blue-5, 22%);
 @table-row-checked-selected-background-color: greyscale(@table-row-checked-selected-focus-background-color);
+@slider-track-color: @palette-gray-5;
 @text-field-icon-color: @palette-gray-6;
 @text-field-icon-error-color: @error-border-color;
 @text-field-icon-focus-color: @focus-border-color;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/mixins.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/mixins.css
index 47d997e..640d6a9 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/mixins.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/mixins.css
@@ -154,6 +154,10 @@
     &:hover::before {
       color: @icon-color;
     }
+
+    &:active::before {
+      color: @icon-color;
+    }
   }
 
   .tooltip-status,
@@ -169,6 +173,10 @@
     &:hover::before {
       color: @status-info-hover-color;
     }
+
+    &:active::before {
+      color: @status-info-hover-color;
+    }
   }
 
   .warning-status {
@@ -183,6 +191,10 @@
     &:hover::before {
       color: @status-warning-hover-color;
     }
+
+    &:active::before {
+      color: @status-warning-hover-color;
+    }
   }
 
   .error-status {
@@ -197,6 +209,10 @@
     &:hover::before {
       color: @status-error-hover-color;
     }
+
+    &:active::before {
+      color: @status-error-hover-color;
+    }
   }
 
   .user-select(@mode) {
@@ -362,4 +378,29 @@
       #scout.vertical-align-helper();
     }
   }
+
+  .loading-indicator() {
+    @loading-animation-size: 30px;
+    display: inline-block;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -(@loading-animation-size / 2);
+    margin-left: -(@loading-animation-size / 2);
+    #scout.animation(fadeIn 0.15s);
+
+    &::before {
+      #scout.animation(rotation 0.9s linear infinite);
+      content: '';
+      display: inline-block;
+      vertical-align: middle;
+      border-radius: 50%;
+      border: 2px solid rgba(0, 0, 0, 0);
+      border-top-color: @border-color;
+      border-left-color: @border-color;
+      border-bottom-color: @border-color;
+      width: @loading-animation-size;
+      height: @loading-animation-size;
+    }
+  }
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/sizes.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/sizes.css
index 094b00a..b2883e1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/sizes.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/style/sizes.css
@@ -8,10 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-@size-desktop-navigation: 290px;
-@size-desktop-navigation-breadcrumb: 240px;
-@desktop-taskbar-height: 51px;
+@desktop-navigation-width: 290px;
+@desktop-navigation-min-width: 49px; /* not 50px because last pixel is the border (would not look good)*/
+@desktop-navigation-breadcrumb-width: 240px;
+@desktop-header-height: 51px;
 @bench-padding-x: 20px;
+@bench-view-min-width: 50px;
+@bench-view-min-height: 50px;
 
 @text-field-padding-y: 7px;
 @text-field-padding-x: 10px;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTab.js
new file mode 100644
index 0000000..83b715c
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTab.js
@@ -0,0 +1,130 @@
+/*******************************************************************************
+
+* Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SimpleTab = function() {
+  scout.SimpleTab.parent.call(this);
+
+  this.title;
+  this.subTitle;
+  this.iconId;
+
+  this._mouseListener;
+
+  // Container for the _Tab_ (not for the view).
+  this.$container;
+
+  this._addEventSupport();
+};
+scout.inherits(scout.SimpleTab, scout.Widget);
+
+scout.SimpleTab.prototype._init = function(options) {
+  scout.SimpleTab.parent.prototype._init.call(this, options);
+  this.title = options.title;
+  this.subTitle = options.subTitle;
+  this.iconId = options.iconId;
+  this.selected = false;
+
+};
+
+scout.SimpleTab.prototype.renderAfter = function($parent, sibling) {
+  this.render($parent);
+  if (sibling) {
+    this.$container.insertAfter(sibling.$container);
+  }
+};
+
+scout.SimpleTab.prototype._render = function($parent) {
+  this.$container = $parent.prependDiv('desktop-view-tab');
+  this._mouseListener = this._onMouseDown.bind(this);
+  this.$container.on('mousedown', this._mouseListener);
+  this._$title = this.$container.appendDiv('title');
+  this._$subTitle = this.$container.appendDiv('sub-title');
+  this._titlesUpdated();
+  this._renderSelection();
+  this._cssClassUpdated(this.view.cssClass, null);
+};
+
+
+
+scout.SimpleTab.prototype._renderSelection = function() {
+  if (this.$container) {
+    if (this.$container.select() === this.selected) {
+      return;
+    }
+    this.$container.select(this.selected);
+  }
+};
+
+scout.SimpleTab.prototype.select = function() {
+  this.selected = true;
+  this._renderSelection();
+};
+
+scout.SimpleTab.prototype.deselect = function() {
+  this.selected = false;
+  this._renderSelection();
+};
+
+
+scout.SimpleTab.prototype._onMouseDown = function(event) {
+  this.trigger('tabClicked');
+};
+
+scout.SimpleTab.prototype.setTitle = function(title) {
+  if (this.title === title) {
+    return;
+  }
+  this.title = title;
+  this._titlesUpdated();
+};
+
+scout.SimpleTab.prototype.setSubTitle = function(subTitle) {
+  if (this.subTitle === subTitle) {
+    return;
+  }
+  this.subTitle = subTitle;
+  this._titlesUpdated();
+};
+
+scout.SimpleTab.prototype.setIconId = function(iconId) {
+  if (this.iconId === iconId) {
+    return;
+  }
+  this.iconId = iconId;
+  this._titlesUpdated();
+};
+
+scout.SimpleTab.prototype._titlesUpdated = function() {
+  if (!this.$container) {
+    return;
+  }
+
+  // Titles
+  setTitle(this._$title, this.title);
+  setTitle(this._$subTitle, this.subTitle);
+
+  // Icon
+  this.$container.icon(this.view.iconId);
+
+  // ----- Helper functions -----
+
+  function setTitle($titleElement, title) {
+    $titleElement.textOrNbsp(title);
+  }
+};
+
+scout.SimpleTab.prototype.getMenuText = function() {
+  var text = this.title;
+  if (this.subTitle) {
+    text += ' (' + this.subTitle + ')';
+  }
+  return text;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.css
new file mode 100644
index 0000000..7e50831
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.css
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+.simple-tab-area {
+  position: absolute;
+  top: 0;
+
+  & > .overflow-tab-item {
+    border-right: 1px solid @border-color;
+    display: inline-block;
+    height: 50px;
+    width: 30px;
+    padding-top: 17px;
+    text-align: center;
+    cursor: pointer;
+    vertical-align: top;
+
+    &::before {
+      #scout.font-icon();
+      color: @icon-color;
+      content: @icon-chevron-right;
+    }
+
+    & .num-tabs {
+      color: @disabled-color;
+      font-size: 10px;
+      margin-top: -4px;
+    }
+
+    &.modality-highlight {
+      #scout.animation-flash-gray();
+    }
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js
new file mode 100644
index 0000000..9cdb4d6
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SimpleTabArea = function() {
+  scout.SimpleTabArea.parent.call(this);
+  this.tabs = [];
+};
+scout.inherits(scout.SimpleTabArea, scout.Widget);
+
+scout.SimpleTabArea.prototype._init = function(model) {
+  scout.SimpleTabArea.parent.prototype._init.call(this, model);
+  this.visible = true;
+  this._selectedViewTab;
+
+  this._viewTabSelectionHandler = this._onTabSelection.bind(this);
+
+  this._addEventSupport();
+};
+
+scout.SimpleTabArea.prototype.render = function($parent) {
+  scout.SimpleTabArea.parent.prototype.render.call(this, $parent);
+  this._renderVisible();
+};
+
+scout.SimpleTabArea.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('simple-tab-area');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(new scout.SimpleTabAreaLayout(this));
+
+};
+
+scout.SimpleTabArea.prototype._renderProperties = function() {
+  scout.SimpleTabArea.parent.prototype._renderProperties.call(this);
+  this._renderTabs();
+};
+
+scout.SimpleTabArea.prototype._renderTabs = function() {
+  // reverse since tabs rendered without a sibling will be prepended.
+  this.tabs.reverse()
+    .forEach(function(tab) {
+      this._renderTab(tab);
+    }.bind(this));
+};
+
+scout.SimpleTabArea.prototype._renderTab = function(tab) {
+  tab.renderAfter(this.$container);
+};
+
+scout.SimpleTabArea.prototype._renderVisible = function() {
+  if (this.visible && this.tabs.length > 0) {
+    if (!this.attached) {
+      this.attach();
+    }
+  } else {
+    if (this.attached) {
+      this.detach();
+    }
+  }
+};
+
+scout.SimpleTabArea.prototype._attach = function() {
+  this._$parent.prepend(this.$container);
+  this.session.detachHelper.afterAttach(this.$container);
+  // If the parent was resized while this view was detached, the view has a wrong size.
+  this.invalidateLayoutTree(false);
+  scout.SimpleTabArea.parent.prototype._attach.call(this);
+};
+
+/**
+ * @override Widget.js
+ */
+scout.SimpleTabArea.prototype._detach = function() {
+  this.session.detachHelper.beforeDetach(this.$container);
+  this.$container.detach();
+  scout.SimpleTabArea.parent.prototype._detach.call(this);
+  this.invalidateLayoutTree(false);
+};
+
+scout.SimpleTabArea.prototype._onTabSelection = function(event) {
+  this.selectTab(event.source);
+};
+
+scout.SimpleTabArea.prototype.setVisible = function(visible) {
+  this.visible = visible;
+  if (this.rendered) {
+    this._renderVisible();
+    this.invalidateLayoutTree();
+  }
+};
+
+scout.SimpleTabArea.prototype.getTabs = function() {
+  return this.tabs;
+};
+
+scout.SimpleTabArea.prototype.selectTab = function(viewTab) {
+  if (this._selectedViewTab === viewTab) {
+    return;
+  }
+  this.deselectTab(this._selectedViewTab);
+
+  this._selectedViewTab = viewTab;
+  if (viewTab) {
+    // Select the new view tab.
+    viewTab.select();
+  }
+  this.trigger('tabSelected', {
+    viewTab: viewTab
+  });
+};
+
+scout.SimpleTabArea.prototype.deselectTab = function(viewTab) {
+  if (!viewTab) {
+    return;
+  }
+  if (this._selectedViewTab !== viewTab) {
+    return;
+  }
+  this._selectedViewTab.deselect();
+
+};
+
+scout.SimpleTabArea.prototype.getSelectedTab = function() {
+  return this._selectedViewTab;
+};
+
+scout.SimpleTabArea.prototype.addTab = function(tab, sibling) {
+  var insertPosition = -1;
+  if (sibling) {
+    insertPosition = this.tabs.indexOf(sibling);
+  }
+  this.tabs.splice(insertPosition + 1, 0, tab);
+  tab.on('tabClicked', this._viewTabSelectionHandler);
+  if (this.rendered) {
+    this._renderVisible();
+    tab.renderAfter(this.$container, sibling);
+    this.invalidateLayoutTree();
+  }
+};
+
+scout.SimpleTabArea.prototype.removeTab = function(tab) {
+  var index = this.tabs.indexOf(tab);
+  if (index > -1) {
+    this.tabs.splice(index, 1);
+    tab.remove();
+    tab.off('tabClicked', this._viewTabSelectionHandler);
+    this._renderVisible();
+    this.invalidateLayoutTree();
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabAreaLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabAreaLayout.js
new file mode 100644
index 0000000..f3c5807
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabAreaLayout.js
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SimpleTabAreaLayout = function(tabArea) {
+  scout.SimpleTabAreaLayout.parent.call(this);
+
+  this.tabArea = tabArea;
+  this._$overflowTab;
+  this._overflowTabsIndizes = [];
+};
+scout.inherits(scout.SimpleTabAreaLayout, scout.AbstractLayout);
+
+scout.SimpleTabAreaLayout.TAB_WIDTH_LARGE = 220;
+scout.SimpleTabAreaLayout.TAB_WIDTH_SMALL = 130;
+scout.SimpleTabAreaLayout.OVERFLOW_MENU_WIDTH = 30;
+
+/**
+ * @override AbstractLayout.js
+ */
+scout.SimpleTabAreaLayout.prototype.layout = function($container) {
+  var tabWidth,
+    htmlContainer = this.tabArea.htmlComp,
+    containerSize = htmlContainer.getSize(),
+    $tabs = htmlContainer.$comp.find('.desktop-view-tab'),
+    numTabs = this.tabArea.getTabs().length,
+    smallPrefSize = this.smallPrefSize();
+
+  containerSize = containerSize.subtract(htmlContainer.getInsets());
+
+  // reset tabs and tool-items
+  if (this._$overflowTab) {
+    this._$overflowTab.remove();
+  }
+
+  $tabs.setVisible(true);
+  this._overflowTabsIndizes = [];
+
+  // All tabs in container
+  if (smallPrefSize.width <= containerSize.width) {
+    tabWidth = Math.min(scout.SimpleTabAreaLayout.TAB_WIDTH_LARGE, Math.floor(containerSize.width / numTabs));
+    // 2nd - all Tabs fit when they have small size
+    $tabs.each(function() {
+      $(this).outerWidth(tabWidth);
+    });
+    return;
+  }
+
+  // Not all tabs fit in container -> put tabs into overflow menu
+  containerSize.width -= scout.SimpleTabAreaLayout.OVERFLOW_MENU_WIDTH;
+
+  // check how many tabs fit into remaining containerSize.width
+  var numVisibleTabs = Math.floor(containerSize.width / scout.SimpleTabAreaLayout.TAB_WIDTH_SMALL),
+    numOverflowTabs = numTabs - numVisibleTabs;
+
+  var i = 0,
+    selectedIndex = 0;
+  $tabs.each(function() {
+    if ($(this).hasClass('selected')) {
+      selectedIndex = i;
+    }
+    i++;
+  });
+
+  // determine visible range
+  var rightEnd, leftEnd = selectedIndex - Math.floor(numVisibleTabs / 2);
+  if (leftEnd < 0) {
+    leftEnd = 0;
+    rightEnd = numVisibleTabs - 1;
+  } else {
+    rightEnd = leftEnd + numVisibleTabs - 1;
+    if (rightEnd > numTabs - 1) {
+      rightEnd = numTabs - 1;
+      leftEnd = rightEnd - numVisibleTabs + 1;
+    }
+  }
+
+  this._$overflowTab = htmlContainer.$comp
+    .appendDiv('overflow-tab-item')
+    .on('mousedown', this._onMouseDownOverflow.bind(this));
+  if (numOverflowTabs > 1) {
+    this._$overflowTab.appendDiv('num-tabs').text(numOverflowTabs);
+  }
+
+  var that = this;
+  tabWidth = scout.SimpleTabAreaLayout.TAB_WIDTH_SMALL;
+  i = 0;
+  $tabs.each(function() {
+    if (i >= leftEnd && i <= rightEnd) {
+      $(this).outerWidth(tabWidth);
+    } else {
+      $(this).setVisible(false);
+      that._overflowTabsIndizes.push(i);
+    }
+    i++;
+  });
+};
+
+scout.SimpleTabAreaLayout.prototype.smallPrefSize = function() {
+  var numTabs = this.tabArea.getTabs().length;
+  return new scout.Dimension(numTabs * scout.SimpleTabAreaLayout.TAB_WIDTH_SMALL, this.tabArea.htmlComp.$comp.outerHeight(true));
+};
+
+scout.SimpleTabAreaLayout.prototype.preferredLayoutSize = function($container) {
+  var numTabs = this.tabArea.getTabs().length;
+  return new scout.Dimension(numTabs * scout.SimpleTabAreaLayout.TAB_WIDTH_LARGE, scout.graphics.prefSize(this.tabArea.htmlComp.$comp, true, {
+    useCssSize: true
+  }).height);
+};
+
+scout.SimpleTabAreaLayout.prototype._onMouseDownOverflow = function(event) {
+  var menu, tab, popup,
+    tabArea = this.tabArea,
+    overflowMenus = [];
+
+  this._overflowTabsIndizes.forEach(function(i) {
+    // FIXME awe: fix bugs in overflow-menu:
+    // - 1. menu schliesst nicht
+    // - 2. manchmal verschwindet ein (noch offener) Tab - wenn nur einer sichtbar ist
+    // - 3. add selenium tests
+    tab = this.tabArea.getTabs()[i];
+    menu = scout.create('Menu', {
+      parent: this.tabArea,
+      text: tab.getMenuText(),
+      tab: tab
+    });
+    menu.remoteHandler = function(event) {
+      if ('doAction' === event.type) {
+        $.log.debug('(SimpleTabAreaLayout#_onMouseDownOverflow) tab=' + this);
+        tabArea.selectTab(this);
+      }
+    }.bind(tab);
+    overflowMenus.push(menu);
+  }, this);
+
+  popup = scout.create('ContextMenuPopup', {
+    parent: this.tabArea,
+    menuItems: overflowMenus,
+    cloneMenuItems: false,
+    location: {
+      x: event.pageX,
+      y: event.pageY
+    }
+  });
+  popup.open();
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.css
new file mode 100644
index 0000000..9e321ea
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.css
@@ -0,0 +1,26 @@
+.view-tab-box {
+  position: absolute;
+  min-width: @bench-view-min-width;
+  min-height: @bench-view-min-height;
+
+  > .simple-tab-area{
+    position: relative;
+    height: @desktop-header-height;
+
+    /* Has the same effect as "border-bottom: 1px solid @border-color", but is over-drawable by child */
+    /* elements (such as the selected view-tab). The border would not be, because of "overflow: hidden". */
+    &::before {
+      content: '';
+      background-color: @border-color;
+      width: 100%;
+      height: 1px;
+      position: absolute;
+      top: calc(~'100% - 1px');
+      left: 0;
+    }
+  }
+
+  > .tab-content {
+    height: 100%;
+  }
+}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js
new file mode 100644
index 0000000..a50e8ea
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SimpleTabBox = function() {
+  scout.SimpleTabBox.parent.call(this);
+  this.$body;
+  this.$title;
+  this.htmlComp;
+  this.tabArea;
+  this.viewStack = [];
+  this.currentView;
+
+  this._addEventSupport();
+};
+scout.inherits(scout.SimpleTabBox, scout.Widget);
+
+scout.SimpleTabBox.prototype._init = function(model) {
+  scout.SimpleTabBox.parent.prototype._init.call(this, model);
+
+  // create view tabs
+  this.tabArea = scout.create('SimpleTabArea', {
+    parent: this
+  });
+  // link
+  this.controller = new scout.SimpleTabBoxController(this, this.tabArea);
+};
+
+/**
+ * Returns a $container used as a bind target for the key-stroke context of the group-box.
+ * By default this function returns the container of the form, or when group-box is has no
+ * form as a parent the container of the group-box.
+ */
+scout.SimpleTabBox.prototype._keyStrokeBindTarget = function() {
+  return this.$container;
+};
+
+scout.SimpleTabBox.prototype._render = function($parent) {
+  var htmlBody, i,
+    env = scout.HtmlEnvironment;
+
+  this.$container = $parent.appendDiv('view-tab-box');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.validateRoot = true;
+  this.htmlComp.setLayout(new scout.SimpleTabBoxLayout(this));
+
+  // render content
+  this.$viewContent = this.$container.appendDiv('tab-content');
+  this.viewContent = new scout.HtmlComponent(this.$viewContent, this.session);
+
+};
+
+scout.SimpleTabBox.prototype._renderProperties = function() {
+  scout.SimpleTabBox.parent.prototype._renderProperties.call(this);
+  // render tabArea
+  this._renderTabArea();
+  this._renderView(this.currentView);
+
+};
+
+scout.SimpleTabBox.prototype._renderTabArea = function() {
+  this.tabArea.render(this.$container);
+  this.$tabArea = this.tabArea.$container;
+  if (this.tabArea.attached) {
+    this.$tabArea.insertBefore(this.$viewContent);
+  }
+};
+
+scout.SimpleTabBox.prototype._renderView = function(view) {
+  if (!view) {
+    return;
+  }
+  if (view.rendered) {
+    return;
+  }
+  view.render(this.$viewContent);
+  view.setParent(this);
+  view.$container.addClass('view');
+  if (view.uiCssClasses) {
+    scout.arrays.ensure(view.uiCssClasses).forEach(function(cssClass) {
+      view.$container.addClass(cssClass);
+    }.bind(this));
+  }
+  view.validateRoot = true;
+};
+
+scout.SimpleTabBox.prototype.postRender = function() {
+  if (this.viewStack.length > 0 && !this.currentView) {
+    this.activateView(this.viewStack[this.viewStack.length - 1]);
+  }
+};
+
+scout.SimpleTabBox.prototype._remove = function() {
+  scout.SimpleTabBox.parent.prototype._remove.call(this);
+  if (this.scrollable) {
+    scout.scrollbars.uninstall(this.$body);
+  }
+};
+
+scout.SimpleTabBox.prototype.activateView = function(view) {
+  if (view === this.currentView) {
+    return;
+  }
+
+  if (this.currentView) {
+    this.currentView.detach();
+    this.trigger('viewDeactivated', {
+      view: this.currentView
+    });
+    this.currentView = null;
+  }
+  // ensure rendered
+  if (this.rendered) {
+    this._renderView(view);
+  }
+  if (!view.attached) {
+    view.attach();
+  }
+  this.currentView = view;
+
+  this.trigger('viewActivated', {
+    view: view
+  });
+
+  if (this.rendered) {
+    this.viewContent.invalidateLayoutTree();
+    // Layout immediate to prevent 'laggy' form visualization,
+    // but not initially while desktop gets rendered because it will be done at the end anyway
+    this.viewContent.validateLayoutTree();
+  }
+};
+
+scout.SimpleTabBox.prototype.addView = function(view, activate) {
+  activate = scout.nvl(activate, true);
+  // add to view stack
+  var siblingView = this._addToViewStack(view);
+  this.trigger('viewAdded', {
+    view: view,
+    siblingView: siblingView
+  });
+
+  if (activate) {
+    this.activateView(view);
+  }
+};
+
+/**
+ *
+ * @param view
+ * @return the view which is gonna be the sibling to insert the new view tab after.
+ */
+scout.SimpleTabBox.prototype._addToViewStack = function(view) {
+  var sibling;
+  var index = this.viewStack.indexOf(view);
+  if (index > -1) {
+    return this.viewStack[index - 1];
+  }
+
+  if (!scout.SimpleTabBoxController.hasViewTab(view)) {
+    // first
+    this.viewStack.unshift(view);
+    return sibling;
+  }
+  if (!this.currentView) {
+    // end
+    sibling = this.viewStack[this.viewStack.length - 1];
+    this.viewStack.push(view);
+    return;
+  }
+  var currentIndex = this.viewStack.indexOf(this.currentView);
+  sibling = this.viewStack[currentIndex];
+  // it does not matter when index is -1 will be inserted at first position
+  this.viewStack.splice(currentIndex + 1, 0, view);
+  return sibling;
+};
+
+scout.SimpleTabBox.prototype.removeView = function(view, showSiblingView) {
+
+  if (!view) {
+    return;
+  }
+  showSiblingView = scout.nvl(showSiblingView, true);
+  var index = this.viewStack.indexOf(view);
+  if (index > -1) {
+    // activate previous
+    if (showSiblingView) {
+      if (index - 1 >= 0) {
+        this.activateView(this.viewStack[index - 1]);
+      } else if (index + 1 < this.viewStack.length) {
+        this.activateView(this.viewStack[index + 1]);
+      }
+    }
+
+    // remove
+    this.viewStack.splice(index, 1);
+    if (view.rendered) {
+      view.remove();
+    }
+    this.trigger('viewRemoved', {
+      view: view
+    });
+
+    if (this.rendered) {
+
+      this.viewContent.invalidateLayoutTree();
+      this.viewContent.validateLayoutTree();
+    }
+  }
+};
+scout.SimpleTabBox.prototype.getController = function() {
+  return this.controller;
+};
+
+scout.SimpleTabBox.prototype.viewCount = function() {
+  return this.viewStack.length;
+};
+
+scout.SimpleTabBox.prototype.hasViews = function() {
+  return this.viewStack.length > 0;
+};
+
+scout.SimpleTabBox.prototype.getViews = function(displayViewId) {
+  return this.viewStack.filter(function(view) {
+    if (!displayViewId) {
+      return true;
+    }
+    return displayViewId === view.displayViewId;
+  });
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxController.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxController.js
new file mode 100644
index 0000000..7fa5615
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxController.js
@@ -0,0 +1,119 @@
+/*******************************************************************************
+
+* Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+
+/**
+ * The {@link {@link scout.SimpleTabBoxController}} is used to link a {@link {@link scout.SimpleTabBox}} with a {@link {@link scout.SimpleTabArea}}.
+ * There are {@link {@link scout.SimpleTabBox}} with more than one {@link {@link scout.SimpleTabArea}} to actualized.
+ * Therefore the linking is separated in a controller.
+ * The controller basically listens to 'viewAdded', 'viewRemoved', 'viewActivated', 'viewDeactivated' on the {@link {@link scout.SimpleTabBox}} and
+ * updates the {@link {@link scout.SimpleTabArea}}.
+ */
+scout.SimpleTabBoxController = function(tabBox, tabArea) {
+  this.tabBox = tabBox;
+  this.tabArea = tabArea;
+
+  this._viewAddedHandler = this._onViewAdded.bind(this);
+  this._viewRemovedHandler = this._onViewRemoved.bind(this);
+  this._viewActivatedHandler = this._onViewActivated.bind(this);
+  this._viewDeactivatedHandler = this._onViewDeactivated.bind(this);
+
+  this._viewTabSelectedHandler = this._onViewTabSelected.bind(this);
+
+  this._installListeners();
+
+};
+
+scout.SimpleTabBoxController.prototype._installListeners = function() {
+  this.tabBox.on('viewAdded', this._viewAddedHandler);
+  this.tabBox.on('viewRemoved', this._viewRemovedHandler);
+  this.tabBox.on('viewActivated', this._viewActivatedHandler);
+  this.tabBox.on('viewDeactivated', this._viewDeactivatedHandler);
+
+  this.tabArea.on('tabSelected', this._viewTabSelectedHandler);
+};
+
+scout.SimpleTabBoxController.prototype._onViewAdded = function(event) {
+  var view = event.view,
+  siblingView = event.siblingView,
+  viewTab,
+  // the sibling to insert the tab after.
+  siblingViewTab;
+
+  if (!scout.SimpleTabBoxController.hasViewTab(view)) {
+    return;
+  }
+  viewTab = this._getTab(view);
+  if(!viewTab){
+    siblingViewTab = this._getTab(siblingView);
+    viewTab = scout.create('DesktopTab', {
+      parent: this.tabArea,
+      view: view
+    });
+    this.tabArea.addTab(viewTab, siblingViewTab);
+  }
+
+};
+
+scout.SimpleTabBoxController.prototype._onViewRemoved = function(event) {
+  var view = event.view;
+  if (!view) {
+    return;
+  }
+  var viewTab = this._getTab(view);
+  if (viewTab) {
+    this.tabArea.removeTab(viewTab);
+  }
+};
+
+scout.SimpleTabBoxController.prototype._onViewActivated = function(event) {
+  var viewTab = this._getTab(event.view);
+  // also reset selection if no view tab of the view is found.
+  this.tabArea.selectTab(viewTab);
+};
+
+scout.SimpleTabBoxController.prototype._onViewDeactivated = function(event) {
+  var viewTab = this._getTab(event.view);
+  // also reset selection if no view tab of the view is found.
+  this.tabArea.deselectTab(viewTab);
+};
+
+scout.SimpleTabBoxController.prototype._onViewTabSelected = function(event) {
+  if (!event.viewTab) {
+    return;
+  }
+  var view = event.viewTab.view;
+  this.tabBox.activateView(view);
+};
+
+scout.SimpleTabBoxController.prototype._getTab = function(view) {
+  if (!view) {
+    return;
+  }
+  var viewTab;
+  this.tabArea.getTabs().some(function(tab) {
+    if (tab.view === view) {
+      viewTab = tab;
+      return true;
+    }
+    return false;
+  });
+  return viewTab;
+};
+
+scout.SimpleTabBoxController.prototype.getTabs = function() {
+  return this.tabArea.getTabs();
+};
+
+/** static functions **/
+scout.SimpleTabBoxController.hasViewTab = function(view) {
+  return scout.objects.someProperties(view, ['title', 'subTitle', 'iconId']);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js
new file mode 100644
index 0000000..4a23f6e
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.SimpleTabBoxLayout = function(tabBox) {
+  scout.SimpleTabBoxLayout.parent.call(this);
+  this.tabBox = tabBox;
+};
+scout.inherits(scout.SimpleTabBoxLayout, scout.AbstractLayout);
+
+scout.SimpleTabBoxLayout.prototype.layout = function($container) {
+  var containerSize, viewContentSize,
+    htmlContainer = scout.HtmlComponent.get($container),
+
+    htmlViewContent = scout.HtmlComponent.get(this.tabBox.$viewContent),
+    tabAreaSize ;
+
+  containerSize = htmlContainer.getAvailableSize()
+    .subtract(htmlContainer.getInsets());
+
+  tabAreaSize = this._layoutTabArea(containerSize);
+
+  viewContentSize = containerSize.subtract(htmlViewContent.getMargins());
+  viewContentSize.height -= tabAreaSize.height;
+  htmlViewContent.setSize(viewContentSize);
+
+};
+
+/**
+ *
+ * @param containerSize
+ * @returns {@link {@link scout.Dimension}} used of the tab area
+ */
+scout.SimpleTabBoxLayout.prototype._layoutTabArea = function(containerSize) {
+  if (!this.tabBox.rendered) {
+    return new scout.Dimension(0,0);
+  }
+  // exprected the tab area is layouted dynamically only
+  var htmlViewTabs = scout.HtmlComponent.get(this.tabBox.$tabArea),
+    prefSize = htmlViewTabs.getPreferredSize(),
+    margins = htmlViewTabs.getMargins();
+  var size = new scout.Dimension(containerSize.width, prefSize.height + margins.top + margins.bottom);
+  htmlViewTabs.setSize(size);
+  return  size;
+};
+
+/**
+ * Preferred size of the tab-box aligns every tab-item in a single line, so that each item is visible.
+ */
+scout.SimpleTabBoxLayout.prototype.preferredLayoutSize = function($container) {
+  var htmlContainer = scout.HtmlComponent.get($container),
+    htmlViewContent = scout.HtmlComponent.get(this._tabBox._$tabContent),
+    htmlViewTabs = scout.HtmlComponent.get(this._tabBox._$tabArea),
+    viewTabsSize = new scout.Dimension(),
+    viewContentSize = new scout.Dimension();
+
+  if (htmlViewTabs.isVisible()) {
+    viewTabsSize = htmlViewTabs.getPreferredSize()
+      .add(htmlViewTabs.getMargins());
+  }
+
+  viewContentSize = htmlViewContent.getPreferredSize()
+    .add(htmlContainer.getInsets())
+    .add(htmlViewContent.getMargins());
+
+  return new scout.Dimension(
+    Math.max(viewTabsSize.width, viewContentSize.width),
+    viewContentSize.height + viewTabsSize.height);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/FilterFieldsGroupBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/FilterFieldsGroupBox.js
index 9c0fbb6..793e11a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/FilterFieldsGroupBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/FilterFieldsGroupBox.js
@@ -18,7 +18,7 @@
   this.filter.modifyFilterFields();
 };
 
-// FIXME AWE: (filter) es braucht wahrscheinlich auch eine range-validierung? z.B. from muss kleiner sein als to
+// TODO awe: (filter) es braucht wahrscheinlich auch eine range-validierung? z.B. from muss kleiner sein als to
 // Prüfen ob wir eine sequence-box dafür verwenden wollen und dafür eine client-seitige validierung impl., diese
 // geschieht heute auf dem UI server. Evtl. wäre auch ein from/to validator für beliebige felder sinnvoll (auch
 // ausserhalb einer sequence-box)
@@ -38,8 +38,9 @@
   return field;
 };
 
-// FIXME AWE: see fix-me in TileContainerBox.js
+// TODO awe, cgu: (addField): see to-do in TileContainerBox.js
 // Added '0' to the name to avoid temporarily to avoid naming conflict with FormField#addField
 scout.FilterFieldsGroupBox.prototype.addField0 = function(field) {
   this.fields.push(field);
+  this._prepareFields();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.css
deleted file mode 100644
index ffe8d33..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.css
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/* Replaces table.css */
-
-.table {
-height: 100%;
-overflow: hidden;
-}
-
-.table-data {
-position: relative;
-height: ~'calc(100% - 95px)'; /*85px is table footer/control*/
-}
-
-.table-row {
-  position:relative;
-  padding: 4px 8px 4px 12px;
-  border-bottom: 1px solid @palette-gray-5;
-}
-
-.table-row-single {
-  padding-top: 8px;
-  padding-bottom: 8px;
-}
-
-.table-row:active {
-  /* touch feedback */
-  background-color: @palette-gray-5;
-}
-
-.table-row.selected {
-  background-color: @palette-gray-5;
-}
-
-.table-row > h3 {
-  font-size: 16px;
-  margin: 0 0;
-}
-
-.table-row > p {
-  margin: 0 0;
-  line-height: 24px;
-}
-
-.table-row > p::after {
-  #scout.font-icon();
-  content: @icon-chevron-right;
-  color: @palette-gray-5;
-  position: absolute;
-  display: block;
-  width: 22px;
-  height: 22px;
-  top: 50%;
-  margin-top: -11px;
-  right: 0px;
-}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.js
deleted file mode 100644
index 765f2d6..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/MobileTable.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-scout.MobileTable = function() {
-  scout.MobileTable.parent.call(this);
-  this.selectionHandler.mouseMoveSelectionEnabled = false;
-  this._headerColumns = [];
-};
-scout.inherits(scout.MobileTable, scout.Table);
-
-/**
- * @override
- */
-scout.MobileTable.prototype.init = function(model, session, register) {
-  // FIXME cgu: should be done by server, or should we add gui only property to control it? model may set it to true at any time later
-  model.headerVisible = false;
-  scout.MobileTable.parent.prototype.init.call(this, model, session, register);
-};
-
-/**
- * @override
- */
-scout.MobileTable.prototype._renderRows = function(rows, startRowIndex) {
-  this._headerColumns = this._computeHeaderColumns();
-  scout.MobileTable.parent.prototype._renderRows.call(this, rows, startRowIndex);
-};
-
-/**
- * @override
- */
-scout.MobileTable.prototype._buildRowDiv = function(row, rowSelected, previousRowSelected, followingRowSelected) {
-  //TODO [5.2] nbu: selection border
-  var rowClass,
-    cellContent = '',
-    columns = this.columns,
-    numColumnsUsed = 0,
-    column, value, headerText = '';
-
-  for (var c = 0; c < row.cells.length; c++) {
-    column = this.columns[c];
-    value = this.cellText(column, row);
-
-    if (c === 0) {
-      cellContent += '<p>';
-    }
-
-    if (this._headerColumns.indexOf(column) >= 0) {
-      headerText += value;
-      numColumnsUsed++;
-    } else {
-      if (this._isColumnNameNecessary(columns[c])) {
-        cellContent += columns[c].text + ': ';
-      }
-      cellContent += value;
-      numColumnsUsed++;
-      if (c < row.cells.length - 1) {
-        cellContent += '<br/>';
-      }
-    }
-
-    if (c === row.cells.length - 1) {
-      cellContent += '</p>';
-    }
-  }
-  if (headerText) {
-    cellContent = '<h3>' + headerText + '</h3>' + cellContent;
-  }
-
-  rowClass = 'table-row ';
-  if (numColumnsUsed === 1) {
-    rowClass += 'table-row-single ';
-  }
-  if (this.selectedRows.indexOf(row) > -1) {
-    rowClass += 'selected ';
-  }
-
-  return '<div id="' + row.id + '" class="' + rowClass + '">' + cellContent + '</div>';
-};
-
-scout.MobileTable.prototype._computeHeaderColumns = function() {
-  var columns = this.columns,
-    column,
-    headerColumns = [],
-    i;
-
-  for (i = 0; i < columns.length; i++) {
-    column = columns[i];
-
-    if (column.summary) {
-      headerColumns.push(column);
-    }
-  }
-
-  if (headerColumns.length > 0) {
-    return headerColumns;
-  }
-
-  for (i = 0; i < columns.length; i++) {
-    column = columns[i];
-
-    if (column.visible) { // FIXME cgu: also check for other criterias (checkboxcolum, see AbstractRowSummaryColumn);
-      headerColumns.push(column);
-      return headerColumns;
-    }
-  }
-
-  return headerColumns;
-};
-
-scout.MobileTable.prototype._isColumnNameNecessary = function(column) {
-  return true;
-};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
index 2a306e0..9d732ef 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/Table.js
@@ -13,6 +13,8 @@
   this.$container;
   this.$data;
   this.header;
+  this.footer;
+  this.footerVisible = false;
   this.selectionHandler;
   this.columns = [];
   this.tableControls = [];
@@ -25,7 +27,6 @@
   this.rowBorderRightWidth = 0; // read-only, set by _calculateRowBorderWidth(), also used in TableHeader.js
   this.staticMenus = [];
   this.selectionHandler = new scout.TableSelectionHandler(this);
-  this._keyStrokeSupport = new scout.KeyStrokeSupport(this);
   this._filterMap = {};
   this._filteredRows = [];
   this._filteredRowsDirty = true;
@@ -83,6 +84,7 @@
   this._syncFilters(this.filters);
   this._syncKeyStrokes(this.keyStrokes);
   this._syncMenus(this.menus);
+  this._syncTableControls(this.tableControls);
   this._syncTableStatus(this.tableStatus);
   this._applyFilters(this.rows);
   this._calculateValuesForBackgroundEffect();
@@ -158,9 +160,7 @@
       new scout.TableCopyKeyStroke(this),
       new scout.ContextMenuKeyStroke(this, this.onContextMenu, this),
       new scout.AppLinkKeyStroke(this, this.handleAppLinkAction)
-    ]
-    .concat(this.tableControls)
-    .concat(this.menus));
+    ]);
 
   // Prevent default action and do not propagate ↓ or ↑ keys if ctrl- or alt-modifier is not pressed.
   // Otherwise, an '↑-event' on the first row, or an '↓-event' on the last row will bubble up (because not consumed by table navigation keystrokes) and cause a superior table to move its selection.
@@ -240,6 +240,7 @@
     parent: this,
     axis: 'both'
   });
+  this._installImageListeners();
   this._installCellTooltipSupport();
   this.menuBar.render(this.$container);
 
@@ -266,7 +267,7 @@
 scout.Table.prototype._renderProperties = function() {
   scout.Table.parent.prototype._renderProperties.call(this);
   this._renderTableHeader();
-  this._renderTableFooter();
+  this._renderFooterVisible();
   this._renderMenus();
   this._renderEnabled();
   this._renderDropType();
@@ -275,14 +276,15 @@
 
 scout.Table.prototype._remove = function() {
   scout.scrollbars.uninstall(this.$data, this.session);
-  // FIXME CGU do not delete header and footer!
+  // FIXME CGU do not delete header, implement according to footer
   this.header = null;
-  this.footer = null;
   this._removeAggregateRows();
+  this._uninstallImageListeners();
   this._uninstallCellTooltipSupport();
   this._removeRows();
   this.$fillBefore = null;
   this.$fillAfter = null;
+  this.$data = null;
   scout.Table.parent.prototype._remove.call(this);
 };
 
@@ -290,17 +292,22 @@
 // reason: the property on this is already synced at this point, the argument may contain
 // just a data-model value (and not a adpater).
 scout.Table.prototype._renderTableControls = function() {
-  this._renderTableFooter();
   if (this.footer) {
     this.footer._renderControls();
   }
 };
 
-scout.Table.prototype._renderSortEnabled = function(dummy) {};
+scout.Table.prototype._renderSortEnabled = function() {
+  // nop
+};
 
-scout.Table.prototype._renderUiSortPossible = function(dummy) {};
+scout.Table.prototype._renderUiSortPossible = function() {
+  // nop
+};
 
-scout.Table.prototype._renderColumnAddable = function(dummy) {};
+scout.Table.prototype._renderColumnAddable = function() {
+  // nop
+};
 
 scout.Table.prototype._syncTableControls = function(controls) {
   var i;
@@ -309,10 +316,16 @@
   }
   this.tableControls = controls;
   for (i = 0; i < this.tableControls.length; i++) {
-    if (this.tableControls[i].enabled) {
-      this.keyStrokeContext.registerKeyStroke(this.tableControls[i]);
-    }
+    this.keyStrokeContext.registerKeyStroke(this.tableControls[i]);
   }
+  this._updateFooterVisibility();
+  this.tableControls.forEach(function(control) {
+    control.tableFooter = this.footer;
+  }, this);
+};
+
+scout.Table.prototype._onImageLoadOrError = function(event) {
+  this.invalidateLayoutTree();
 };
 
 scout.Table.prototype._onRowMouseDown = function(event) {
@@ -369,6 +382,7 @@
 scout.Table.prototype._onRowDoubleClick = function(event) {
   var $row = $(event.currentTarget),
     column = this._columnAtX(event.pageX);
+
   this.doRowAction($row.data('row'), column);
 };
 
@@ -396,7 +410,7 @@
           $anchor: this.$data,
           menuFilter: this._filterMenusHandler
         });
-        popup.open(null, event);
+        popup.open();
 
         // Set table style to focused, so that it looks as it still has the focus.
         // Must be called after open(), because opening the popup might cause another
@@ -433,17 +447,13 @@
 };
 
 scout.Table.prototype._renderTableStatusVisible = function() {
-  this._renderTableFooter();
+  // nop
 };
 
 scout.Table.prototype._renderTableStatus = function() {
   this.trigger('statusChanged');
 };
 
-scout.Table.prototype._isFooterVisible = function() {
-  return this.tableStatusVisible || this._hasVisibleTableControls();
-};
-
 scout.Table.prototype._hasVisibleTableControls = function() {
   return this.tableControls.some(function(control) {
     if (control.visible) {
@@ -586,6 +596,9 @@
     return true;
   }
 
+  // add all visible columns as fallback sorting to guarantee same sorting as in Java.
+  sortColumns = scout.arrays.union(sortColumns, this.columns);
+
   this._sortImpl(sortColumns);
   this._filteredRowsDirty = true; // order has been changed
   this._triggerRowOrderChanged();
@@ -617,13 +630,15 @@
   function compare(row1, row2) {
     for (var s = 0; s < sortColumns.length; s++) {
       var column = sortColumns[s];
-      var direction = column.sortActive && column.sortAscending ? -1 : 1;
-
       var result = column.compare(row1, row2);
-      if (result < 0) {
-        return direction;
-      } else if (result > 0) {
-        return -1 * direction;
+      if (column.sortActive && !column.sortAscending) {
+        // only consider sortAscending flag when sort is active
+        // columns with !sortActive are always sorted ascending (sortAscending represents last state for those, thus not considered)
+        result = -result;
+      }
+
+      if (result !== 0) {
+        return result;
       }
     }
 
@@ -886,8 +901,7 @@
 };
 
 scout.Table.prototype._addGroupColumn = function(column, direction, multiGroup) {
-  var deviation,
-    sortIndex = -1;
+  var sortIndex = -1;
 
   if (!this.isGroupingPossible(column)) {
     return;
@@ -1008,8 +1022,7 @@
   if (row.checked && this.checkableStyle === scout.Table.CheckableStyle.TABLE_ROW) {
     rowClass += ' checked';
   }
-  // FIXME AWE: remove attr('data-rowid')
-  var rowDiv = '<div class="' + rowClass + '" data-rowid="' + row.id + '" style="width: ' + rowWidth + 'px"' + scout.device.unselectableAttribute.string + '>';
+  var rowDiv = '<div class="' + rowClass + '" style="width: ' + rowWidth + 'px"' + scout.device.unselectableAttribute.string + '>';
   for (var c = 0; c < this.columns.length; c++) {
     rowDiv += this.columns[c].buildCellForRow(row);
   }
@@ -1391,18 +1404,17 @@
   return scout.menus.filterAccordingToSelection('Table', this.selectedRows.length, menus, destination, onlyVisible, enableDisableKeyStroke, notAllowedTypes);
 };
 
-scout.Table.prototype._renderMenus = function() {
+scout.Table.prototype.setStaticMenus = function(staticMenus) {
+  this.staticMenus = staticMenus;
   this._updateMenuBar();
-  if (this.header) {
-    this.header.updateMenuBar();
-  }
 };
 
-scout.Table.prototype._updateMenuBar = function() {
-  var notAllowedTypes = ['Header'];
-  var menuItems = this._filterMenus(this.menus, scout.MenuDestinations.MENU_BAR, false, true, notAllowedTypes);
-  menuItems = this.staticMenus.concat(menuItems);
-  this.menuBar.updateItems(menuItems);
+scout.Table.prototype._renderMenus = function() {
+  // NOP
+};
+
+scout.Table.prototype._removeMenus = function() {
+  // menubar takes care about removal
 };
 
 scout.Table.prototype.notifyRowSelectionFinished = function() {
@@ -1414,11 +1426,6 @@
   this._updateMenuBar();
 };
 
-// Only necessary if the table is a root html comp (outline table)
-scout.Table.prototype.onResize = function() {
-  this.htmlComp.revalidateLayoutTree();
-};
-
 scout.Table.prototype._sendRowClicked = function($row, mouseButton, columnId) {
   var data = {
     rowId: $row.data('row').id,
@@ -1958,6 +1965,12 @@
 };
 
 scout.Table.prototype.doRowAction = function(row, column) {
+  if (this.selectedRows.length !== 1 || this.selectedRows[0] !== row) {
+    // Only allow row action if the selected row was double clicked because the handler of the event expects a selected row.
+    // This may happen if the user modifies the selection using ctrl or shift while double clicking.
+    return;
+  }
+
   column = column || this.columns[0];
   if (column && column.guiOnly) {
     column = scout.arrays.find(this.columns, function(col) {
@@ -1975,8 +1988,7 @@
 };
 
 scout.Table.prototype.insertRows = function(rows, fromServer) {
-  var newHiddenRows = [],
-    wasEmpty = this.rows.length === 0;
+  var wasEmpty = this.rows.length === 0;
 
   // Update model
   rows.forEach(function(row) {
@@ -2378,12 +2390,12 @@
   }
   this._triggerRowsSelected();
 
+  this._updateMenuBar();
   if (this.rendered) {
     this._renderSelection();
     if (this.scrollToSelection) {
       this.revealSelection();
     }
-    this._updateMenuBar();
   }
 };
 
@@ -3004,12 +3016,26 @@
   this.selectionHandler.clearLastSelectedRowMarker();
 };
 
-scout.Table.prototype._syncMenus = function(newMenus, oldMenus) {
-  this._keyStrokeSupport.syncMenus(newMenus, oldMenus);
+scout.Table.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
+  this._updateMenuBar();
+
+  if (this.header) {
+    this.header.updateMenuBar();
+  }
 };
 
-scout.Table.prototype._syncKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
-  this._keyStrokeSupport.syncKeyStrokes(newKeyStrokes, oldKeyStrokes);
+scout.Table.prototype._updateMenuBar = function() {
+  var notAllowedTypes = ['Header'];
+  var menuItems = this._filterMenus(this.menus, scout.MenuDestinations.MENU_BAR, false, true, notAllowedTypes);
+  menuItems = this.staticMenus.concat(menuItems);
+  this.menuBar.setMenuItems(menuItems);
+};
+
+scout.Table.prototype._syncKeyStrokes = function(keyStrokes, oldKeyStrokes) {
+  this.updateKeyStrokes(keyStrokes, oldKeyStrokes);
+  this.keyStrokes = keyStrokes;
 };
 
 scout.Table.prototype._syncFilters = function(filters) {
@@ -3036,6 +3062,28 @@
   }
 };
 
+scout.Table.prototype._syncTableStatusVisible = function(tableStatusVisible) {
+  this.tableStatusVisible = tableStatusVisible;
+  this._updateFooterVisibility();
+};
+
+scout.Table.prototype._updateFooterVisibility = function() {
+  this.setFooterVisible(this.tableStatusVisible || this._hasVisibleTableControls());
+};
+
+scout.Table.prototype.setFooterVisible = function(visible) {
+  this.footerVisible = visible;
+  if (visible && !this.footer) {
+    this.footer = this._createFooter();
+  }
+  if (this.rendered) {
+    this._renderFooterVisible();
+  }
+  if (!visible && this.footer) {
+    this.footer = null;
+  }
+};
+
 /**
  * Renders the background effect of every column, if column.backgroundEffect is set
  */
@@ -3138,28 +3186,31 @@
   }
 };
 
-scout.Table.prototype._renderTableFooter = function() {
-  var footerVisible = this._isFooterVisible(),
-    changed = false;
-  if (footerVisible && !this.footer) {
-    this.footer = this._createFooter();
-    this.footer.render();
-    changed = true;
-  } else if (!footerVisible && this.footer) {
-    this._removeTableFooter();
-    changed = true;
+scout.Table.prototype._renderFooterVisible = function() {
+  if (!this.footer) {
+    return;
   }
-  if (changed) {
-    this.invalidateLayoutTree();
+  if (this.footerVisible) {
+    this._renderFooter();
+  } else {
+    this._removeFooter();
   }
+  this.invalidateLayoutTree();
 };
 
-scout.Table.prototype._removeTableFooter = function() {
-  if (this.footer) {
-    this.footer.remove();
-    this.removeChild(this.footer);
-    this.footer = null;
+scout.Table.prototype._renderFooter = function() {
+  if (this.footer.rendered) {
+    return;
   }
+
+  this.footer.render();
+};
+
+scout.Table.prototype._removeFooter = function() {
+  if (!this.footer.rendered) {
+    return;
+  }
+  this.footer.remove();
 };
 
 scout.Table.prototype._renderEnabled = function() {
@@ -3252,6 +3303,20 @@
 };
 
 /**
+ * This listener is used to invalidate table layout when an image icon has been loaded (which happens async in the browser).
+ */
+scout.Table.prototype._installImageListeners = function() {
+  this._imageLoadListener = this._onImageLoadOrError.bind(this);
+  this.$data[0].addEventListener('load', this._imageLoadListener, true);
+  this.$data[0].addEventListener('error', this._imageLoadListener, true);
+};
+
+scout.Table.prototype._uninstallImageListeners = function() {
+  this.$data[0].removeEventListener('load', this._imageLoadListener, true);
+  this.$data[0].removeEventListener('error', this._imageLoadListener, true);
+};
+
+/**
  * Calculates the optimal view range size (number of rows to be rendered).
  * It uses the default row height to estimate how many rows fit in the view port.
  * The view range size is this value * 2.
@@ -3526,7 +3591,6 @@
 };
 
 scout.Table.prototype._onRowOrderChanged = function(rowIds) {
-  var newPos, rows, row;
   if (rowIds.length !== this.rows.length) {
     throw new Error('Row order changed event may not be processed because lengths of the arrays differ.');
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.css
index 511031b..48dd430 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.css
@@ -172,8 +172,8 @@
     color: @hover-color;
   }
 
-  &:hover > .table-info-button {
-    color: @hover-color;
+  &:active > .table-info-button {
+    color: @active-color;
   }
 }
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
index 798b3e9..a441bbc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
@@ -17,6 +17,7 @@
   this._tableRemoveFilterHandler = this._onTableRemoveFilter.bind(this);
   this._tableRowsSelectedHandler = this._onTableRowsSelected.bind(this);
   this._tableStatusChangedHandler = this._onTableStatusChanged.bind(this);
+  this._tableColumnStructureChangedHandler = this._onColumnStructureChanged.bind(this);
 };
 scout.inherits(scout.TableFooter, scout.Widget);
 
@@ -103,6 +104,7 @@
   this.table.on('removeFilter', this._tableRemoveFilterHandler);
   this.table.on('rowsSelected', this._tableRowsSelectedHandler);
   this.table.on('statusChanged', this._tableStatusChangedHandler);
+  this.table.on('columnStructureChanged', this._tableColumnStructureChangedHandler);
 
   this.session.keyStrokeManager.installKeyStrokeContext(this.searchFieldKeyStrokeContext);
 };
@@ -110,6 +112,8 @@
 scout.TableFooter.prototype._remove = function() {
   this.session.keyStrokeManager.uninstallKeyStrokeContext(this.searchFieldKeyStrokeContext);
   this._hideTableStatusTooltip();
+  this.$resizer = null;
+  this.open = false;
 
   this.table.off('rowsInserted', this._tableRowsChangedHandler);
   this.table.off('rowsDeleted', this._tableRowsChangedHandler);
@@ -119,6 +123,7 @@
   this.table.off('removeFilter', this._tableRemoveFilterHandler);
   this.table.off('rowsSelected', this._tableRowsSelectedHandler);
   this.table.off('statusChanged', this._tableStatusChangedHandler);
+  this.table.off('columnStructureChanged', this._tableColumnStructureChangedHandler);
 
   scout.TableFooter.parent.prototype._remove.call(this);
 };
@@ -181,7 +186,6 @@
   var controls = this.table.tableControls;
   if (controls) {
     controls.forEach(function(control) {
-      control.tableFooter = this;
       control.setParent(this);
       control.render(this._$controls);
     }.bind(this));
@@ -601,3 +605,18 @@
   this._renderInfoTableStatus();
   this._updateInfoTableStatusVisibility();
 };
+
+scout.TableFooter.prototype._onColumnStructureChanged = function(event) {
+  var controls = this.table.tableControls;
+  if (controls) {
+    controls.forEach(function(control) {
+      if (control.selected) {
+        control.removeContent();
+        control.renderContent();
+      }
+    }.bind(this));
+  } else {
+    this._$controls.empty();
+  }
+
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooterLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooterLayout.js
index a40dc4b..0b91455 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooterLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooterLayout.js
@@ -79,7 +79,7 @@
 
   // Let table controls update their content according to the new footer size
   this._tableFooter.table.tableControls.forEach(function(control) {
-    control.onResize();
+    control.revalidateLayout();
   });
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.css
index eb7aca8..7bc438f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.css
@@ -102,11 +102,15 @@
     }
   }
 
-  &:not(.disabled):hover,
-  &.moving {
+  &:not(.disabled):hover {
     color: @hover-color;
   }
 
+  &:not(.disabled):active,
+  &.moving {
+    color: @active-color;
+  }
+
   &.moving > .table-header-item-state {
     display: none;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
index acaa28e..bfcf44b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
@@ -31,6 +31,7 @@
   });
   this.menuBar.tabbable = false;
   this.menuBar.bottom();
+  this.updateMenuBar();
 };
 
 scout.TableHeader.prototype._render = function($parent) {
@@ -48,8 +49,6 @@
   this._$window = this.$container.window();
   this._$body = this.$container.body();
 
-  this.updateMenuBar();
-
   this._renderColumns();
 
   this.table.$data.on('scroll', this._tableDataScrollHandler);
@@ -416,7 +415,7 @@
 
 scout.TableHeader.prototype.updateMenuBar = function() {
   var menuItems = this.table._filterMenus(this.table.menus, scout.MenuDestinations.HEADER);
-  this.menuBar.updateItems(menuItems);
+  this.menuBar.setMenuItems(menuItems);
 };
 
 scout.TableHeader.prototype._onTableColumnResized = function(event) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenu.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenu.css
index 8789278..e61e2f3 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenu.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenu.css
@@ -158,6 +158,11 @@
     border-color: @palette-blue-6;
   }
 
+  &:active {
+    color: @button-active-color;
+    background-color: @button-active-background-color;
+  }
+
   &.disabled {
     cursor: default;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenuButton.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenuButton.js
index cc73514..9cec6fe 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenuButton.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeaderMenuButton.js
@@ -31,6 +31,7 @@
 
 scout.TableHeaderMenuButton.prototype._render = function($parent) {
   this.$container = $parent.appendDiv('table-header-menu-command')
+    .unfocusable()
     .on('click', this._onClick.bind(this))
     .on('mouseenter click', this._onMouseOver.bind(this))
     .on('mouseleave', this._onMouseOut.bind(this));
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
index 4ee90e0..6c7c5fb 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
@@ -39,7 +39,7 @@
   }
   if (footer) {
     // Layout table footer and add size of footer (including the control content) to 'height'
-    footer.htmlComp.revalidateLayout();
+    footer.revalidateLayout();
     height += scout.graphics.getSize(footer.$container).height;
     height += scout.graphics.getSize(footer.$controlContainer).height;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableMatrix.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableMatrix.js
index ef05f7d..a4b9da1 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableMatrix.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableMatrix.js
@@ -420,5 +420,5 @@
 };
 
 scout.TableMatrix.prototype.isEmpty = function() {
-  return this._rows.length === 0;
+  return this._rows.length === 0 || this._columns.length === 0;
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.css
similarity index 72%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.css
index eaad555..1eac036 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/MobileOutline.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.css
@@ -8,11 +8,15 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-.outline.breadcrumb > .tree-data {
+.table-row-detail {
+  padding: @compact-outline-node-padding-v @compact-outline-node-padding-h;
+  line-height: 25px;
+}
 
-  & > .tree-node > .form {
-    /* reset alignment */
-    text-align: initial;
-  }
+.table-row-detail-name {
+  font-weight: bold;
+}
 
+.table-row-detail-value {
+  white-space: normal;
 }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.js
new file mode 100644
index 0000000..bb12ddd
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableRowDetail.js
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.TableRowDetail = function() {
+  scout.TableRowDetail.parent.call(this);
+  this.table;
+  this.tableRow;
+};
+scout.inherits(scout.TableRowDetail, scout.Widget);
+
+scout.TableRowDetail.prototype._init = function(model) {
+  scout.TableRowDetail.parent.prototype._init.call(this, model);
+  this.table = model.table;
+  this.tableRow = model.tableRow;
+};
+
+scout.TableRowDetail.prototype._render = function($parent) {
+  this.$container = $parent.appendDiv('table-row-detail');
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this._renderTableRow();
+};
+
+scout.TableRowDetail.prototype._renderTableRow = function() {
+  this.table.columns.forEach(function(column) {
+    var name = column.text;
+    var value = this.table.cellText(column, this.tableRow);
+    if (scout.strings.empty(value)) {
+      return;
+    }
+    var $field = this.$container.appendDiv('table-row-detail-field');
+    // FIXME CGU handle column without text or with icon, handle icon content, html content, bean content
+    $field.appendSpan('table-row-detail-name').text(name + ': ');
+    $field.appendSpan('table-row-detail-value').text(value);
+  }, this);
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/AggregateTableControl.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/AggregateTableControl.js
index d1a4bc5..1760c04 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/AggregateTableControl.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/AggregateTableControl.js
@@ -155,10 +155,6 @@
   }
 };
 
-scout.AggregateTableControl.prototype.isContentAvailable = function() {
-  return true;
-};
-
 scout.AggregateTableControl.prototype._syncEnabled = function(enabled) {
   this.enabled = enabled;
   this._updateEnabledAndSelectedState();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControl.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControl.js
new file mode 100644
index 0000000..8207887
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControl.js
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.FormTableControl = function() {
+  scout.FormTableControl.parent.call(this);
+  this._addAdapterProperties('form');
+};
+scout.inherits(scout.FormTableControl, scout.TableControl);
+
+scout.FormTableControl.prototype._init = function(model) {
+  scout.FormTableControl.parent.prototype._init.call(this, model);
+  this._syncForm(this.form);
+};
+
+scout.FormTableControl.prototype._createLayout = function() {
+  return new scout.FormTableControlLayout(this);
+};
+
+scout.FormTableControl.prototype._renderContent = function($parent) {
+  this.form.renderInitialFocusEnabled = false;
+  this.form.render($parent);
+
+  // Tab box gets a special style if it is the first field in the root group box
+  var rootGroupBox = this.form.rootGroupBox;
+  if (rootGroupBox.fields[0] instanceof scout.TabBox) {
+    rootGroupBox.fields[0].$container.addClass('in-table-control');
+  }
+
+  this.form.$container.height($parent.height());
+  this.form.$container.width($parent.width());
+  this.form.htmlComp.pixelBasedSizing = true;
+  this.form.htmlComp.validateRoot = true;
+  this.form.htmlComp.validateLayout();
+};
+
+scout.FormTableControl.prototype._removeContent = function() {
+  this.form.remove();
+};
+
+scout.FormTableControl.prototype._removeForm = function() {
+  this.removeContent();
+};
+
+scout.FormTableControl.prototype._renderForm = function(form) {
+  this.renderContent();
+};
+
+/**
+ * Returns true if the table control may be displayed (opened).
+ */
+scout.FormTableControl.prototype.isContentAvailable = function() {
+  return !!this.form;
+};
+
+scout.FormTableControl.prototype._syncForm = function(form) {
+  if (form) {
+    form.rootGroupBox.menuBar.bottom();
+  }
+  this.form = form;
+};
+
+scout.FormTableControl.prototype.onControlContainerOpened = function() {
+  // TODO [5.2] dwi: temporary solution; set focus to last known position
+  this.form.renderInitialFocus();
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControlLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControlLayout.js
new file mode 100644
index 0000000..3d260c1
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/FormTableControlLayout.js
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.FormTableControlLayout = function(control) {
+  scout.FormTableControlLayout.parent.call(this);
+  this.control = control;
+};
+scout.inherits(scout.FormTableControlLayout, scout.AbstractLayout);
+
+scout.FormTableControlLayout.prototype.layout = function($container) {
+  if (!this.control.contentRendered) {
+    return;
+  }
+
+  var formSize,
+    controlContentSize = scout.graphics.getSize(this.control.tableFooter.$controlContent);
+
+  if (this.control.form) {
+    var htmlForm = this.control.form.htmlComp;
+    formSize = controlContentSize.subtract(htmlForm.getMargins());
+    htmlForm.setSize(formSize);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControl.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControl.js
index 5f56d5b..61cb2e0 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControl.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControl.js
@@ -11,8 +11,6 @@
 scout.TableControl = function() {
   scout.TableControl.parent.call(this);
   this.tableFooter;
-  this.form;
-  this._addAdapterProperties('form');
   this.contentRendered = false;
   this.height = scout.TableControl.CONTAINER_SIZE;
   this.animateDuration = scout.TableControl.CONTAINER_ANIMATE_DURATION;
@@ -23,11 +21,6 @@
 scout.TableControl.CONTAINER_SIZE = 345;
 scout.TableControl.CONTAINER_ANIMATE_DURATION = 350;
 
-scout.TableControl.prototype._init = function(model) {
-  scout.TableControl.parent.prototype._init.call(this, model);
-  this._syncForm(this.form);
-};
-
 /**
  * @override ModelAdapter.js
  */
@@ -49,6 +42,10 @@
   return keyStrokeContext;
 };
 
+scout.TableControl.prototype._createLayout = function() {
+  return new scout.NullLayout();
+};
+
 scout.TableControl.prototype._render = function($parent) {
   var classes = 'table-control ';
   if (this.cssClass) {
@@ -57,6 +54,8 @@
   this.$container = $parent.appendDiv(classes)
     .on('mousedown', this._onMouseDown.bind(this))
     .data('control', this);
+  this.htmlComp = new scout.HtmlComponent(this.$container, this.session);
+  this.htmlComp.setLayout(this._createLayout());
 };
 
 scout.TableControl.prototype.remove = function() {
@@ -65,25 +64,11 @@
 };
 
 scout.TableControl.prototype._renderContent = function($parent) {
-  this.form.render($parent);
-
-  // Tab box gets a special style if it is the first field in the root group box
-  var rootGroupBox = this.form.rootGroupBox;
-  if (rootGroupBox.fields[0] instanceof scout.TabBox) {
-    rootGroupBox.fields[0].$container.addClass('in-table-control');
-  }
-
-  this.form.$container.height($parent.height());
-  this.form.$container.width($parent.width());
-  this.form.htmlComp.pixelBasedSizing = true;
-  this.form.htmlComp.validateRoot = true;
-  this.form.htmlComp.revalidateLayout();
-  this.session.keyStrokeManager.installKeyStrokeContext(this.tableControlKeyStrokeContext);
+  // to be implemented by subclass
 };
 
 scout.TableControl.prototype._removeContent = function() {
-  this.session.keyStrokeManager.uninstallKeyStrokeContext(this.tableControlKeyStrokeContext);
-  this.form.remove();
+  // to be implemented by subclass
 };
 
 scout.TableControl.prototype.removeContent = function() {
@@ -93,6 +78,7 @@
       this.tableFooter.$controlContainer.removeClass(this.cssClass + '-table-control-container');
       this.tableFooter.$controlContent.removeClass(this.cssClass + '-table-control-content');
     }
+    this.session.keyStrokeManager.uninstallKeyStrokeContext(this.tableControlKeyStrokeContext);
     this.contentRendered = false;
   }
 };
@@ -107,11 +93,6 @@
     return;
   }
 
-  // do not set initial focus as form, form is not visible during animation of control container, otherwise browser might scroll document
-  if (this.form) {
-    this.form.renderInitialFocusEnabled = false;
-  }
-
   if (!this.tableFooter.open) {
     this.tableFooter.openControlContainer(this);
   }
@@ -122,21 +103,17 @@
       this.tableFooter.$controlContent.addClass(this.cssClass + '-table-control-content');
     }
     this._renderContent(this.tableFooter.$controlContent);
+    this.session.keyStrokeManager.installKeyStrokeContext(this.tableControlKeyStrokeContext);
+    if (this.htmlComp) {
+      this.htmlComp.invalidateLayoutTree(false);
+    }
     this.contentRendered = true;
   }
 };
 
-scout.TableControl.prototype._removeForm = function() {
-  this.removeContent();
-};
-
-scout.TableControl.prototype._renderForm = function(form) {
-  this.renderContent();
-};
-
 scout.TableControl.prototype._renderSelected = function(selected, closeWhenUnselected) {
   selected = scout.nvl(selected, this.selected);
-  closeWhenUnselected = closeWhenUnselected !== undefined ? closeWhenUnselected : true;
+  closeWhenUnselected = scout.nvl(closeWhenUnselected, true);
 
   this.$container.select(selected);
 
@@ -165,7 +142,7 @@
  * Returns true if the table control may be displayed (opened).
  */
 scout.TableControl.prototype.isContentAvailable = function() {
-  return !!this.form;
+  return true;
 };
 
 scout.TableControl.prototype.toggle = function() {
@@ -173,31 +150,33 @@
     return;
   }
   if (this.tableFooter.selectedControl === this) {
-    this.setSelected(false, true);
+    this.setSelected(false);
   } else {
-    this.setSelected(true, true);
+    this.setSelected(true);
   }
 };
 
-scout.TableControl.prototype.setSelected = function(selected, closeWhenUnselected) {
+scout.TableControl.prototype.setSelected = function(selected, notifyServer, closeWhenUnselected) {
   if (selected && !this.visible) {
     return;
   }
   if (selected === this.selected) {
     return;
   }
-
-  if (this.tableFooter.selectedControl && this.tableFooter.selectedControl !== this) {
-    this.tableFooter.selectedControl.setSelected(false, false);
+//TODO cgu: this.tableFooter can be null
+  if (this.tableFooter && this.tableFooter.selectedControl && this.tableFooter.selectedControl !== this) {
+    this.tableFooter.selectedControl.setSelected(false, true, false);
   }
 
   // Instead of calling parent.setSelected(), we manually execute the required code. Otherwise
   // we would not be able to pass 'closeWhenUnselected' to _renderSelected().
-  this.selected = selected;
+  this._setProperty('selected', selected);
   if (this.rendered) {
     this._renderSelected(selected, closeWhenUnselected);
   }
-  this.sendSelected();
+  if (scout.nvl(notifyServer, true)) {
+    this.sendSelected();
+  }
 };
 
 scout.TableControl.prototype._configureTooltip = function() {
@@ -206,13 +185,6 @@
   return options;
 };
 
-scout.TableControl.prototype._syncForm = function(form) {
-  if (form) {
-    form.rootGroupBox.menuBar.bottom();
-  }
-  this.form = form;
-};
-
 scout.TableControl.prototype._goOffline = function() {
   if (!this.isContentAvailable()) {
     this._renderEnabled(false);
@@ -225,21 +197,12 @@
   }
 };
 
-scout.TableControl.prototype.onResize = function() {
-  if (this.form && this.form.rendered) {
-    this.form.onResize();
-  }
-};
-
 scout.TableControl.prototype._onMouseDown = function() {
   this.toggle();
 };
 
 scout.TableControl.prototype.onControlContainerOpened = function() {
-  if (this.form) {
-    // TODO [5.2] dwi: temporary solution; set focus to last known position
-    this.form.renderInitialFocus();
-  }
+  // nop
 };
 
 scout.TableControl.prototype.onControlContainerClosed = function() {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControlAdapterMenu.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControlAdapterMenu.js
new file mode 100644
index 0000000..b3941a0
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/controls/TableControlAdapterMenu.js
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.TableControlAdapterMenu = function() {
+  scout.TableControlAdapterMenu.parent.call(this);
+
+  this._tableControlPropertyChangeHandler = this._onTableControlPropertyChange.bind(this);
+  this._tableControlDestroyHandler = this._onTableControlDestroy.bind(this);
+};
+scout.inherits(scout.TableControlAdapterMenu, scout.FormMenu);
+
+/**
+ * @override Action.js
+ */
+scout.TableControlAdapterMenu.prototype._init = function(model) {
+  scout.TableControlAdapterMenu.parent.prototype._init.call(this, model);
+  if (!this.tableControl) {
+    throw new Error('Cannot adapt to undefined tableControl');
+  }
+  this._installListeners();
+};
+
+scout.TableControlAdapterMenu.prototype._installListeners = function() {
+  this.tableControl.on('propertyChange', this._tableControlPropertyChangeHandler);
+  this.tableControl.on('destroy', this._tableControlDestroyHandler);
+};
+
+scout.TableControlAdapterMenu.prototype._uninstallListeners = function() {
+  this.tableControl.off('propertyChange', this._tableControlPropertyChangeHandler);
+  this.tableControl.off('destroy', this._tableControlDestroyHandler);
+};
+
+scout.TableControlAdapterMenu.prototype._render = function($parent) {
+  scout.TableControlAdapterMenu.parent.prototype._render.call(this, $parent);
+  // Convenience: Add ID of original tableControl to DOM for debugging purposes
+  this.$container.attr('data-tableControlAdapter', this.tableControl.id);
+};
+
+scout.TableControlAdapterMenu.prototype._onTableControlPropertyChange = function(event) {
+  // Whenever a tableControl property changes, apply the changes to the menu
+  var changedProperties = {};
+  event.changedProperties.forEach(function(prop) {
+    changedProperties[prop] = event.newProperties[prop];
+  });
+  this.onModelPropertyChange({
+    properties: scout.TableControlAdapterMenu.adaptTableControlProperties(changedProperties)
+  });
+};
+
+scout.TableControlAdapterMenu.prototype._onTableControlDestroy = function(event) {
+  this.remove();
+  this._uninstallListeners();
+};
+
+/**
+ * @override Action.js
+ */
+scout.TableControlAdapterMenu.prototype.doAction = function() {
+  return this.tableControl.doAction();
+};
+
+scout.TableControlAdapterMenu.prototype._syncSelected = function(selected) {
+  // Don't call super, because super prevents rendering and instead delegates to setSelected. But in this case rendering is needed
+  this.selected = selected;
+};
+
+/**
+ * @override Action.js
+ */
+scout.TableControlAdapterMenu.prototype.setSelected = function(selected, notifyServer) {
+  this.tableControl.setSelected(selected, notifyServer);
+};
+
+/* --- STATIC HELPERS ------------------------------------------------------------- */
+
+/**
+ * @memberOf scout.TableControlAdapterMenu
+ */
+scout.TableControlAdapterMenu.adaptTableControlProperties = function(tableControlProperties, menuProperties) {
+  menuProperties = menuProperties || {};
+
+  // Plain properties: simply copy, no translation required
+  ['text', 'iconId', 'enabled', 'visible', 'selected', 'tooltipText', 'keyStroke', 'keyStrokes', 'modelClass', 'classId', 'form'].forEach(function(prop) {
+    menuProperties[prop] = tableControlProperties[prop];
+  });
+
+  // Cleanup: Remove all properties that have value 'undefined' from the result object,
+  // otherwise, they would be applied to the model adapter.
+  for (var prop in menuProperties) {
+    if (menuProperties[prop] === undefined) {
+      delete menuProperties[prop];
+    }
+  }
+  return menuProperties;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/editor/CellEditorPopupLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/editor/CellEditorPopupLayout.js
index 50c2413..4217436 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/editor/CellEditorPopupLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/editor/CellEditorPopupLayout.js
@@ -17,7 +17,7 @@
 scout.inherits(scout.CellEditorPopupLayout, scout.AbstractLayout);
 
 scout.CellEditorPopupLayout.prototype.layout = function($container) {
-  var size, prefSize, popupSize,
+  var size,
     htmlField = this._field.htmlComp;
 
   size = this._htmlContainer.getAvailableSize()
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/DateColumnUserFilter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/DateColumnUserFilter.js
index a876dde..6c5c82d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/DateColumnUserFilter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/DateColumnUserFilter.js
@@ -84,7 +84,7 @@
 };
 
 /**
- * FIXME AWE: (filter) refactor DateField.js -
+ * TODO awe, cgu: (value-field) refactor DateField.js -
  * rename timestampAsDate to value (also on JsonDateField)
  * use Date object everywhere and todays 'timestamp' date-string
  * only when we communicate with the UI server. Then remove the toJsonDate
@@ -95,11 +95,11 @@
  */
 scout.DateColumnUserFilter.prototype.addFilterFields = function(groupBox) {
   this.dateFromField = groupBox.addFilterField('DateField', 'ui.from', 0);
-  this.dateFromField.timestamp = toJsonDate(this.dateFrom);
+  this.dateFromField.setTimestamp(toJsonDate(this.dateFrom));
   this.dateFromField.on('timestampChanged', this._onDisplayTextChanged.bind(this));
 
   this.dateToField = groupBox.addFilterField('DateField', 'ui.to', 1);
-  this.dateToField.timestamp = toJsonDate(this.dateTo);
+  this.dateToField.setTimestamp(toJsonDate(this.dateTo));
   this.dateToField.on('timestampChanged', this._onDisplayTextChanged.bind(this));
 
   function toJsonDate(date) {
@@ -120,17 +120,22 @@
 };
 
 scout.DateColumnUserFilter.prototype._onInput = function(event) {
-  var datePrediction = this.dateFromField._predictDate(this.dateFromField.$dateField.val()); // this also updates the errorStatus
-  if (datePrediction) {
-    if (datePrediction.date) {
-      this.dateFrom = this.dateFromField._newTimestampAsDate(datePrediction.date, this.dateFromField.timestampAsDate);
-    }
+  if (!this.dateFromField.rendered) {
+    // popup has been closed in the mean time
+    return;
   }
-  var datePredictionTo = this.dateToField._predictDate(this.dateToField.$dateField.val()); // this also updates the errorStatus
-  if (datePredictionTo) {
-    if (datePredictionTo.date) {
-      this.dateTo = this.dateToField._newTimestampAsDate(datePredictionTo.date, this.dateToField.timestampAsDate);
-    }
-  }
+  this.dateFrom = this._readDate(this.dateFromField);
+  this.dateTo = this._readDate(this.dateToField);
   this.triggerFilterFieldsChanged(event);
 };
+
+scout.DateColumnUserFilter.prototype._readDate = function(dateField) {
+  var displayText = dateField.$dateField.val();
+  if (!displayText) {
+    return null;
+  }
+  var datePrediction = dateField._predictDate(displayText);
+  if (datePrediction && datePrediction.date) {
+    return dateField._newTimestampAsDate(datePrediction.date, dateField.timestampAsDate);
+  }
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/TextColumnUserFilter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/TextColumnUserFilter.js
index ac79c82..15eb4cc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/TextColumnUserFilter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/userfilter/TextColumnUserFilter.js
@@ -74,6 +74,5 @@
  * @override ColumnUserFilter.js
  */
 scout.TextColumnUserFilter.prototype.modifyFilterFields = function() {
-  this.freeTextField.$mandatory.remove();
-  this.freeTextField.$mandatory = null;
+  this.freeTextField.removeMandatoryIndicator();
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/Tooltip.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/Tooltip.js
index b48c623..a4f570d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/Tooltip.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/Tooltip.js
@@ -266,7 +266,7 @@
 
   // Only remove the tooltip if the click is outside of the container or the $anchor (= status icon)
   // Also ignore clicks if the tooltip is covert by a glasspane
-  return !this.isOrHasWidget(targetWidget) &&
+  return !this.isOrHas(targetWidget) &&
     (this.$anchor && !this.$anchor.isOrHas($target[0])) &&
     !this.session.focusManager.isElementCovertByGlassPane(this.$container[0]);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/tooltips.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/tooltips.js
similarity index 100%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/util/tooltips.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/tooltip/tooltips.js
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/CompactTree.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/CompactTree.js
index e00dfad..7bc730a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/CompactTree.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/CompactTree.js
@@ -1,6 +1,7 @@
 scout.CompactTree = function() {
   scout.CompactTree.parent.call(this);
   this.$nodesContainer;
+  this._scrolldirections = 'y';
 };
 scout.inherits(scout.CompactTree, scout.Tree);
 
@@ -35,13 +36,29 @@
   this.menuBar.render(this.$container);
 
   this.$nodesContainer = this.$data.appendDiv('nodes');
-  this._addNodes(this.nodes);
-
-  if (this.selectedNodes.length > 0) {
-    this._renderSelection();
-  }
+  this._updateNodeDimensions();
+  this._renderViewport();
+  this.invalidateLayoutTree();
 };
 
+/**
+ * @override
+ */
+scout.CompactTree.prototype._calculateCurrentViewRange = function() {
+  this.viewRangeSize = this.visibleNodesFlat.length;
+  return new scout.Range(0, Math.max(this.visibleNodesFlat.length, 0));
+};
+
+/**
+ * @override
+ */
+scout.CompactTree.prototype.calculateViewRangeSize = function() {
+  return this.visibleNodesFlat.length;
+};
+
+/**
+ * @override
+ */
 scout.CompactTree.prototype._remove = function() {
   scout.scrollbars.uninstall(this.$data, this.session);
   scout.CompactTree.parent.prototype._remove.call(this);
@@ -50,57 +67,51 @@
 /**
  * @override
  */
-scout.CompactTree.prototype._addNodes = function(nodes, $parent, $predecessor) {
-  if (!nodes || nodes.length === 0) {
-    return;
+scout.CompactTree.prototype._$buildNode = function(node) {
+  if (node.level === 0) {
+    //TODO [jgu] sections without child nodes are not visible, never build
+    // Sections (only draw if they have child nodes)
+    //    if (node.childNodes.length > 0) {
+    var $section = this.$container.makeDiv('section expanded')
+      .data('node', node);
+    $section.appendDiv('title')
+      .text(node.text);
+
+    node.$node = $section;
+    //    }
+  } else {
+    var $parent = node.parentNode.$node;
+    // Sections nodes
+    var $sectionNode = $parent.makeDiv('section-node')
+      .data('node', node)
+      .on('mousedown', this._onNodeMouseDown.bind(this))
+      .on('mouseup', this._onNodeMouseUp.bind(this));
+
+    node.$node = $sectionNode;
+
   }
-  for (var i = 0; i < nodes.length; i++) {
-    var node = nodes[i];
-    if (!$parent) {
-      // Sections (only draw if they have child nodes)
-      if (node.childNodes.length > 0) {
-        var $section = this.$container.makeDiv('section expanded')
-          .data('node', node);
-        $section.appendDiv('title')
-          .text(node.text);
 
-        node.$node = $section;
-        if ($predecessor) {
-          if ($predecessor.hasClass('section-node')) {
-            $predecessor = $predecessor.parent();
-          }
-          $section.insertAfter($predecessor);
-        } else {
-          $section.prependTo(this.$nodesContainer);
-        }
+  return node.$node;
+};
 
-        this._addNodes(node.childNodes, $section);
-        $predecessor = $section;
-      }
-    } else {
-      // Sections nodes
-      var $sectionNode = $parent.makeDiv('section-node')
-        .data('node', node)
-        .on('mousedown', this._onNodeMouseDown.bind(this))
-        .on('mouseup', this._onNodeMouseUp.bind(this));
-
-      node.$node = $sectionNode;
-      if ($predecessor) {
-        if ($predecessor.hasClass('section')) {
-          $predecessor = $predecessor.children('.title');
-        }
-        $sectionNode.insertAfter($predecessor);
-      } else {
-        $sectionNode.insertAfter($parent.children('.title'));
-      }
-      $predecessor = $sectionNode;
+/**
+ * @override
+ */
+scout.CompactTree.prototype._insertNodeInDOMAtPlace = function(node, index) {
+  var visibleNodeBefore = this.visibleNodesFlat[index - 1];
+  var n;
+  if (!visibleNodeBefore) {
+    node.$node.prependTo(this.$nodesContainer);
+  } else if (visibleNodeBefore.level < node.level) {
+    //insert after first child node (title from the level above)
+    node.$node.insertAfter(visibleNodeBefore.$node.children()[0]);
+  } else {
+    n = visibleNodeBefore.$node;
+    for (var i = 0; i < visibleNodeBefore.level - node.level; i++) {
+      n = n.parent();
     }
-    this._decorateNode(node);
+    node.$node.insertAfter(n);
   }
-  this.invalidateLayoutTree();
-
-  // return the last created node
-  return $predecessor;
 };
 
 /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/LazyNodeFilter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/LazyNodeFilter.js
new file mode 100644
index 0000000..85c17a9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/LazyNodeFilter.js
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.LazyNodeFilter = function(tree) { //
+  this.tree = tree;
+};
+
+scout.LazyNodeFilter.prototype.accept = function(node) {
+  if (!node.expanded && node.parentNode && node.parentNode.expandedLazy && node.parentNode.lazyExpandingEnabled && this.tree.lazyExpandingEnabled) {
+    // if this node is not expanded and parent is lazyExpanding.
+    for (var i = 0; i < this.tree.selectedNodes.length; i++) {
+      var selectedNode = this.tree.selectedNodes[i];
+      //not initialized selected nodes
+      if (typeof selectedNode === 'string') {
+        break;
+      }
+      if (selectedNode === node || selectedNode.isChildOf(node)) {
+        return true;
+      }
+    }
+    return false;
+  }
+  return true;
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.css b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.css
index fc70c00..2909e9a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.css
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.css
@@ -8,6 +8,8 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
+@tree-node-padding: 6px;
+
 .tree {
   position: relative;
   height: 100%;
@@ -22,7 +24,7 @@
       border-color: @item-selection-border-color;
     }
 
-    /*first child is the scrollbar*/
+    /* first child is the scrollbar */
     .tree-node:nth-of-type(1).selected {
       border-top-color: @item-selection-nonfocus-background-color;
     }
@@ -39,6 +41,12 @@
   position: relative;
   overflow: hidden;
   width: 100%; /* expand to outer container, needed for breadcrumb */
+  
+  &.scrollable-tree >.tree-node{
+  	overflow: visible;
+  	text-overflow: initial;
+  	whitespace: normal;  	
+  }
 }
 
 .navigation-breadcrumb .tree-data {
@@ -48,11 +56,11 @@
 .tree-node {
   display: block;
   position: relative;
-  #scout.overflow-ellipsis-nowrap();
   border: 1px solid transparent;
   border-left: 0px solid transparent;
   border-right: 0px solid transparent;
-  padding: 6px;
+  padding: @tree-node-padding;
+  #scout.overflow-ellipsis-nowrap();
 
   &.selected {
     background-color: @item-selection-nonfocus-background-color;
@@ -69,6 +77,11 @@
   &:nth-of-type(1).selected {
     border-top-color: @item-selection-nonfocus-background-color;
   }
+
+  & > .text {
+    width: 100%;
+    #scout.overflow-ellipsis-nowrap();
+  }
 }
 
 .tree-node-checkbox {
@@ -85,7 +98,7 @@
     cursor: pointer;
     display: inline-block;
     position: relative;
-    font-size: 13px;
+    font-size: @font-size-normal;
 
     &.disabled {
       cursor: default;
@@ -170,6 +183,111 @@
   }
 }
 
+/* bread crumb style */
+.tree.breadcrumb {
+
+  & > .tree-data {
+    & > .tree-node,
+    & > .animation-wrapper > .tree-node {
+      overflow: visible;
+      text-align: center;
+
+      display: none;
+      border-top: 0;
+      border-bottom: 1px solid @border-color;
+
+      /* !important is necessary here to override the element specific left-padding (calculated by Tree.js for level indentation). */
+      padding: 10px @tree-node-padding 8px @tree-node-padding !important;
+
+      &.ancestor-of-selected,
+      &.child-of-selected,
+      &.selected {
+        display: block;
+      }
+
+      &.selected {
+        color: @outline-selection-color;
+        cursor: default;
+      }
+
+      /* arrow is created using ::before and ::after*/
+      &.ancestor-of-selected::before,
+      &.ancestor-of-selected::after,
+      &.selected::before,
+      &.selected::after{
+        position: absolute;
+        left: 50%;
+        margin-left: -13px;
+        border: solid transparent;
+        content: '';
+        height: 0;
+        width: 0;
+        z-index: 1;
+      }
+
+      &.ancestor-of-selected::before,
+      &.selected::before {
+        border-color: @border-color transparent transparent transparent;
+        border-width: 6px 12px 0 12px;
+        bottom: -7px;
+      }
+
+      &.ancestor-of-selected::after,
+      &.selected::after {
+        border-color: @control-background-color transparent transparent transparent;
+        border-width: 6px 12px 0 12px;
+        bottom: -6px;
+      }
+
+      &.selected::after {
+        border-top-color: @item-selection-nonfocus-background-color;
+      }
+
+      &.ancestor-of-selected.leaf::before,
+      &.ancestor-of-selected.leaf::after,
+      &.selected.leaf::before,
+      &.selected.leaf::after {
+        display: none;
+      }
+
+      & > .tree-node-control {
+        display: none;
+      }
+
+      & > .text {
+        white-space: normal;
+      }
+    }
+  }
+
+  &:focus > .tree-data,
+  &.focused > .tree-data {
+    & > .tree-node,
+    & > .animation-wrapper > .tree-node {
+
+      &.parent-of-selected {
+        border-color: @item-selection-border-color;
+      }
+
+      &.parent-of-selected::before {
+        border-top-color: @item-selection-border-color;
+      }
+
+      &.selected {
+        border-color: @item-selection-border-color;
+      }
+
+      &.selected::before {
+        border-top-color: @item-selection-border-color;
+      }
+
+      &.selected::after {
+        border-top-color: @item-selection-background-color;
+      }
+    }
+  }
+}
+
 /* key handling */
 
 .tree-node .key-box {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
index 01cdc3d..c50313a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/Tree.js
@@ -12,6 +12,8 @@
   scout.Tree.parent.call(this);
   this.$data;
   this.nodes = []; // top-level nodes
+  this.visibleNodesFlat = [];
+  this.visibleNodesMap = {};
   this.nodesMap = {}; // all nodes by id
   this._addAdapterProperties(['menus', 'keyStrokes']);
   this._additionalContainerClasses = ''; // may be used by subclasses to set additional CSS classes
@@ -22,18 +24,54 @@
   this.menuBar;
   this.checkedNodes = [];
   this._filters = [];
-  this._animationNodeLimit = 25;
-  this._keyStrokeSupport = new scout.KeyStrokeSupport(this);
   this._doubleClickSupport = new scout.DoubleClickSupport();
   this._$animationWrapper; // used by _renderExpansion()
-  this.lazyExpandingEnabled = true;
+  this._$expandAnimationWrappers = [];
   this._filterMenusHandler = this._filterMenus.bind(this);
+  //contains all parents of a selected node, the selected node and the first level children
+  this._inSelectionPathList = {};
+  this.groupedNodes = {};
+
+  this.viewRangeRendered = new scout.Range(0, 0);
+  this.viewRangeSize = 20;
+
+  this.startAnimationFunc = function() {
+    this.runningAnimations++;
+  }.bind(this);
+  this.runningAnimations = 0;
+  this.runningAnimationsFinishFunc = function() {
+    this.runningAnimations--;
+    if (this.runningAnimations <= 0) {
+      this.runningAnimations = 0;
+      this._renderViewportBlocked = false;
+      this.invalidateLayoutTree();
+    }
+  }.bind(this);
+
+  this.nodeHeight = 0;
+  this.nodeWidth = 0;
+  this.maxNodeWidth = 0;
+  this.nodeWidthDirty = false;
+
+  this._scrolldirections = 'both';
 };
 scout.inherits(scout.Tree, scout.ModelAdapter);
 
+scout.Tree.DisplayStyle = {
+  DEFAULT: 'default',
+  BREADCRUMB: 'breadcrumb'
+};
+
 scout.Tree.prototype._init = function(model) {
   scout.Tree.parent.prototype._init.call(this, model);
+  this.addFilter(new scout.LazyNodeFilter(this), true);
+  this.breadcrumbFilter = new scout.TreeBreadcrumbFilter(this);
+  if (this.displayStyle === scout.Tree.DisplayStyle.BREADCRUMB) {
+    this.addFilter(this.breadcrumbFilter, true, true);
+  }
+  this.initialTraversing = true;
   this._visitNodes(this.nodes, this._initTreeNode.bind(this));
+  this.initialTraversing = false;
   this.selectedNodes = this._nodesByIds(this.selectedNodes);
   this.menuBar = scout.create('MenuBar', {
     parent: this,
@@ -41,7 +79,8 @@
     menuFilter: this._filterMenusHandler
   });
   this.menuBar.bottom();
-  this._syncBreadcrumbEnabled('', this.breadcrumbEnabled);
+  this._updateItemPath(true);
+  this._syncDisplayStyle(this.displayStyle);
   this._syncKeyStrokes(this.keyStrokes);
   this._syncMenus(this.menus);
 };
@@ -59,14 +98,14 @@
   var modifierBitMask = scout.keyStrokeModifier.NONE;
 
   keyStrokeContext.registerKeyStroke([
-      new scout.TreeSpaceKeyStroke(this),
-      new scout.TreeNavigationUpKeyStroke(this, modifierBitMask),
-      new scout.TreeNavigationDownKeyStroke(this, modifierBitMask),
-      new scout.TreeCollapseAllKeyStroke(this, modifierBitMask),
-      new scout.TreeCollapseOrDrillUpKeyStroke(this, modifierBitMask),
-      new scout.TreeExpandOrDrillDownKeyStroke(this, modifierBitMask)
-    ]
-    .concat(this.menus));
+    new scout.TreeSpaceKeyStroke(this),
+    new scout.TreeNavigationUpKeyStroke(this, modifierBitMask),
+    new scout.TreeNavigationDownKeyStroke(this, modifierBitMask),
+    new scout.TreeCollapseAllKeyStroke(this, modifierBitMask),
+    new scout.TreeCollapseOrDrillUpKeyStroke(this, modifierBitMask),
+    new scout.TreeNavigationEndKeyStroke(this, modifierBitMask),
+    new scout.TreeExpandOrDrillDownKeyStroke(this, modifierBitMask)
+  ]);
 
   // Prevent default action and do not propagate ↓ or ↑ keys if ctrl- or alt-modifier is not pressed.
   // Otherwise, an '↑-event' on the first node, or an '↓-event' on the last row will bubble up (because not consumed by tree navigation keystrokes) and cause a superior tree to move its selection;
@@ -80,23 +119,85 @@
   });
 };
 
-scout.Tree.prototype._syncMenus = function(newMenus, oldMenus) {
-  this._keyStrokeSupport.syncMenus(newMenus, oldMenus);
+scout.Tree.prototype._syncMenus = function(menus, oldMenus) {
+  this.updateKeyStrokes(menus, oldMenus);
+  this.menus = menus;
+  this._updateMenuBar();
 };
 
-scout.Tree.prototype._syncKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
-  this._keyStrokeSupport.syncKeyStrokes(newKeyStrokes, oldKeyStrokes);
+scout.Tree.prototype._updateMenuBar = function() {
+  var menuItems = this._filterMenus(this.menus, scout.MenuDestinations.MENU_BAR, false, true);
+  this.menuBar.setMenuItems(menuItems);
 };
 
-scout.Tree.prototype._syncBreadcrumbEnabled = function(oldValue, newValue) {
-  this.setBreadcrumbEnabled(newValue, false);
+scout.Tree.prototype._syncKeyStrokes = function(keyStrokes, oldKeyStrokes) {
+  this.updateKeyStrokes(keyStrokes, oldKeyStrokes);
+  this.keyStrokes = keyStrokes;
+};
+
+scout.Tree.prototype._syncDisplayStyle = function(newValue) {
+  this.setDisplayStyle(newValue, false);
+};
+
+scout.Tree.prototype._resetTreeNode = function(node, parentNode) {
+  node.rendered = false;
+  node.attached = false;
+  delete node.$node;
+};
+
+scout.Tree.prototype._isSelectedNode = function(node) {
+  if (this.initialTraversing) {
+    return this.selectedNodes.indexOf(node.id) > -1;
+  } else {
+    return this.selectedNodes.indexOf(node) > -1;
+  }
 };
 
 scout.Tree.prototype._initTreeNode = function(node, parentNode) {
   this.nodesMap[node.id] = node;
   if (parentNode) {
     node.parentNode = parentNode;
+    node.level = node.parentNode.level + 1;
+  } else {
+    node.level = 0;
   }
+  node.rendered = false;
+  node.attached = false;
+  //if this node is selected all parent nodes has to be added to selectionPath
+  if (this._isSelectedNode(node) && ((node.parentNode && !this.visibleNodesMap[node.parentNode.id]) || node.level === 0)) {
+    var p = node;
+    while (p) {
+      this._inSelectionPathList[p.id] = true;
+      p.filterDirty = true;
+
+      if (p !== node) {
+        //ensure node is expanded
+        node.expanded = true;
+        //if parent was filtered before, try refilter after adding to selection path.
+        if (p.level === 0) {
+          this._applyFiltersForNode(p);
+
+          //add visible nodes to visible nodes array when they are initialized
+          this._addToVisibleFlatList(p, false);
+
+          //process children
+          this._addChildrenToFlatList(p, this.visibleNodesFlat.length - 1, false, null, true);
+        }
+      }
+      p = p.parentNode;
+    }
+  } else if (node.parentNode && this._isSelectedNode(node.parentNode)) {
+    this._inSelectionPathList[node.id] = true;
+  }
+  //create function to check if node is in hierarchy of a parent. is used on removal from flat list.
+  node.isChildOf = function(parentNode) {
+    if (parentNode === this.parentNode) {
+      return true;
+    } else if (!this.parentNode) {
+      return false;
+    }
+    return this.parentNode.isChildOf(parentNode);
+  };
   if (node.checked) {
     this.checkedNodes.push(node);
   }
@@ -104,7 +205,28 @@
   if (node.childNodes === undefined) {
     node.childNodes = [];
   }
+  var that = this;
+
+  this._initTreeNodeInternal(node, parentNode);
+
+  node.isFilterAccepted = function(forceFilter) {
+    if (this.filterDirty || forceFilter) {
+      that._applyFiltersForNode(this);
+    }
+    return this.filterAccepted;
+  };
+  this._applyFiltersForNode(node);
+
+  //add visible nodes to visible nodes array when they are initialized
+  this._addToVisibleFlatList(node, false);
+
   this._updateMarkChildrenChecked(node, true, node.checked);
+
+  node.initialized = true;
+};
+
+scout.Tree.prototype._initTreeNodeInternal = function(node, parentNode) {
+  //override this if you want a custom node init before filtering.
 };
 
 scout.Tree.prototype.destroy = function() {
@@ -115,12 +237,16 @@
 scout.Tree.prototype._destroyTreeNode = function(node, parentNode) {
   delete this.nodesMap[node.id];
   scout.arrays.remove(this.selectedNodes, node); // ensure deleted node is not in selection list anymore (in case the model does not update the selection)
+  this._removeFromFlatList(node, false); //ensure node is not longer in visible nodes list.
 
   if (this._onNodeDeleted) { // Necessary for subclasses
     this._onNodeDeleted(node);
   }
 };
 
+/**
+ * if func returns true the children of the visited node are not visited.
+ */
 scout.Tree.prototype._visitNodes = function(nodes, func, parentNode) {
   var i, node;
   if (!nodes) {
@@ -129,8 +255,8 @@
 
   for (i = 0; i < nodes.length; i++) {
     node = nodes[i];
-    func(node, parentNode);
-    if (node.childNodes.length > 0) {
+    var doNotProcessChildren = func(node, parentNode);
+    if (!doNotProcessChildren && node.childNodes.length > 0) {
       this._visitNodes(node.childNodes, func, node);
     }
   }
@@ -154,15 +280,24 @@
     .on('dblclick', '.tree-node', this._onNodeDoubleClick.bind(this))
     .on('mousedown', '.tree-node-control', this._onNodeControlMouseDown.bind(this))
     .on('mouseup', '.tree-node-control', this._onNodeControlMouseUp.bind(this))
-    .on('dblclick', '.tree-node-control', this._onNodeControlDoubleClick.bind(this));
+    .on('dblclick', '.tree-node-control', this._onNodeControlDoubleClick.bind(this))
+    .on('scroll', this._onDataScroll.bind(this));
+  new scout.HtmlComponent(this.$data, this.session);
+
+  if (this.isHorizontalScrollingEnabled()) {
+    this.$data.toggleClass('scrollable-tree', true);
+  }
 
   scout.scrollbars.install(this.$data, {
     parent: this,
-    axis: 'y'
+    axis: this._scrolldirections
   });
   this._installNodeTooltipSupport();
   this.menuBar.render(this.$container);
-  this._addNodes(this.nodes);
+  this._updateNodeDimensions();
+  // render display style before viewport (not in renderProperties) to have a correct style from the beginning
+  this._renderDisplayStyle();
+  this._renderViewport();
 };
 
 scout.Tree.prototype._postRender = function() {
@@ -170,12 +305,20 @@
 };
 
 scout.Tree.prototype._remove = function() {
+  // stop all animations
+  if (this._$animationWrapper) {
+    this._$animationWrapper.stop(false, true);
+  }
   // Detach nodes from jQuery objects (because those will be removed)
-  this.nodes.forEach(function(node) {
-    delete node.$node;
-  });
+  this._visitNodes(this.nodes, this._resetTreeNode.bind(this));
+
   scout.scrollbars.uninstall(this.$data, this.session);
   this._uninstallNodeTooltipSupport();
+  this.$fillBefore = null;
+  this.$fillAfter = null;
+  this.$data = null;
+  // reset rendered view range because now range is rendered
+  this.viewRangeRendered = new scout.Range(0, 0);
   scout.Tree.parent.prototype._remove.call(this);
 };
 
@@ -183,47 +326,410 @@
   scout.Tree.parent.prototype._renderProperties.call(this);
   this._renderEnabled();
   this._renderMenus();
-  this._renderBreadcrumbEnabled();
   this._renderDropType();
 };
 
-scout.Tree.prototype._addNodes = function(nodes, $parent, $predecessor) {
-  if (!nodes || nodes.length === 0) {
+scout.Tree.prototype.isHorizontalScrollingEnabled = function() {
+  return this._scrolldirections === 'both' || this._scrolldirections === 'x';
+};
+
+scout.Tree.prototype._onDataScroll = function() {
+  var scrollToSelectionBackup = this.scrollToSelection;
+  this.scrollToSelection = false;
+  var scrollTop = this.$data[0].scrollTop;
+  if (this.scrollTop === scrollTop) {
+    return;
+  }
+  this._renderViewport();
+  this.scrollTop = scrollTop;
+  this.scrollToSelection = scrollToSelectionBackup;
+};
+
+scout.Table.prototype.setScrollTop = function(scrollTop) {
+  scout.scrollbars.scrollTop(this.$data, scrollTop);
+  this.scrollTop = scrollTop;
+
+  // call _renderViewport to make sure nodes are rendered immediately. The browser fires the scroll event handled by onDataScroll delayed
+  this._renderViewport();
+};
+
+scout.Tree.prototype._renderViewport = function() {
+  if (this.runningAnimations > 0 || this._renderViewportBlocked) {
+    //animation pending do not render view port because finishing should rerenderViewport
+    return;
+  }
+  var viewRange = this._calculateCurrentViewRange();
+  this._renderViewRange(viewRange);
+};
+
+scout.Tree.prototype._calculateCurrentViewRange = function() {
+  var node,
+    scrollTop = this.$data[0].scrollTop,
+    maxScrollTop = this.$data[0].scrollHeight - this.$data[0].clientHeight;
+
+  if (maxScrollTop === 0 && this.visibleNodesFlat.length > 0) {
+    // no scrollbars visible
+    node = this.visibleNodesFlat[0];
+  } else {
+    node = this._nodeAtScrollTop(scrollTop);
+  }
+
+  return this._calculateViewRangeForNode(node);
+};
+
+scout.Tree.prototype._rerenderViewport = function() {
+  if (this._renderViewportBlocked) {
+    return;
+  }
+  this._removeRenderedNodes();
+  this._renderFiller();
+  this._updateDomNodeWidth();
+  this._renderViewport();
+};
+
+scout.Tree.prototype._removeRenderedNodes = function() {
+  var $nodes = this.$data.find('.tree-node');
+  $nodes.each(function(i, elem) {
+    var $node = $(elem),
+      node = $node.data('node');
+    if ($node.hasClass('hiding')) {
+      // Do not remove nodes which are removed using an animation
+      return;
+    }
+    this._removeNode(node);
+  }.bind(this));
+  this.viewRangeRendered = new scout.Range(0, 0);
+};
+
+scout.Tree.prototype._renderViewRangeForNode = function(node) {
+  var viewRange = this._calculateViewRangeForNode(node);
+  this._renderViewRange(viewRange);
+};
+
+scout.Tree.prototype._renderNodesInRange = function(range) {
+  var prepend = false;
+
+  var nodes = this.visibleNodesFlat;
+  if (nodes.length === 0) {
     return;
   }
 
-  $predecessor = $predecessor || $parent;
-  var parentNode = ($parent ? $parent.data('node') : null);
+  var maxRange = new scout.Range(0, nodes.length);
+  range = maxRange.intersect(range);
+  if (!range.intersect(this.viewRangeRendered).equals(new scout.Range(0, 0))) {
+    throw new Error('New range must not intersect with existing.');
+  }
+  if (range.to <= this.viewRangeRendered.from) {
+    prepend = true;
+  }
+  var newRange = this.viewRangeRendered.union(range);
+  if (newRange.length === 2) {
+    throw new Error('Can only prepend or append rows to the existing range. Existing: ' + this.viewRangeRendered + '. New: ' + newRange);
+  }
+  this.viewRangeRendered = newRange[0];
 
-  for (var i = 0; i < nodes.length; i++) {
-    var node = nodes[i];
-    var $node = this._$buildNode(node, $parent);
+  var numNodesRendered = this.ensureRangeVisible(range);
 
-    // If parent node wants its children to be lazy added to the tree, hide the DOM element, except
-    // the node is expanded, in which case we never hide it. (The last check provides a cheap
-    // way to retain most of the state when the page is reloaded).
-    if (!node.expanded && parentNode && parentNode.expandedLazy) {
-      $node.addClass('hidden');
+  if ($.log.isTraceEnabled()) {
+    $.log.trace(numNodesRendered + ' new nodes rendered from ' + range);
+  }
+};
+
+scout.Tree.prototype.ensureRangeVisible = function(range) {
+  var nodes = this.visibleNodesFlat,
+    numNodesRendered = 0;
+  for (var r = range.from; r < range.to; r++) {
+    var node = nodes[r];
+    if (!node.attached) {
+      this._insertNodeInDOM(node);
+      numNodesRendered++;
     }
-    // append first node and successors
-    if ($predecessor) {
-      $node.insertAfter($predecessor);
-    } else {
-      $node.prependTo(this.$data);
-    }
+  }
+  return numNodesRendered;
+};
 
-    // if model demands children, create them
-    if (node.expanded && node.childNodes.length > 0) {
-      $predecessor = this._addNodes(node.childNodes, $node);
-    } else {
-      $predecessor = $node;
+scout.Tree.prototype._renderFiller = function() {
+  if (!this.$fillBefore) {
+    this.$fillBefore = this.$data.prependDiv('tree-data-fill');
+  }
+
+  var fillBeforeDimensions = this._calculateFillerDimension(new scout.Range(0, this.viewRangeRendered.from));
+  this.$fillBefore.cssHeight(fillBeforeDimensions.height);
+  if (this.isHorizontalScrollingEnabled()) {
+    this.$fillBefore.cssWidth(fillBeforeDimensions.width);
+    this.maxNodeWidth = Math.max(fillBeforeDimensions.width, this.maxNodeWidth);
+  }
+  $.log.trace('FillBefore height: ' + fillBeforeDimensions.height);
+
+  if (!this.$fillAfter) {
+    this.$fillAfter = this.$data.appendDiv('tree-data-fill');
+  }
+
+  var fillAfterDimensions = {
+    height: 0,
+    width: 0
+  };
+  fillAfterDimensions = this._calculateFillerDimension(new scout.Range(this.viewRangeRendered.to, this.visibleNodesFlat.length));
+  this.$fillAfter.cssHeight(fillAfterDimensions.height);
+  if (this.isHorizontalScrollingEnabled()) {
+    this.$fillAfter.cssWidth(fillAfterDimensions.width);
+    this.maxNodeWidth = Math.max(fillAfterDimensions.width, this.maxNodeWidth);
+  }
+  $.log.trace('FillAfter height: ' + fillAfterDimensions.height);
+};
+
+scout.Tree.prototype._calculateFillerDimension = function(range) {
+  var dimension = {
+    height: 0,
+    width: Math.max(this.$data.outerWidth(), this.maxNodeWidth)
+  };
+  for (var i = range.from; i < range.to; i++) {
+    var node = this.visibleNodesFlat[i];
+    dimension.height += this._heightForNode(node);
+    dimension.width = Math.max(dimension.width, this._widthForNode(node));
+  }
+  return dimension;
+};
+
+scout.Tree.prototype._removeNodesInRange = function(range) {
+  var fromNode, toNode, node, i,
+    numNodesRemoved = 0,
+    nodes = this.visibleNodesFlat;
+
+  var maxRange = new scout.Range(0, nodes.length);
+  range = maxRange.intersect(range);
+  fromNode = nodes[range.from];
+  toNode = nodes[range.to];
+
+  var newRange = this.viewRangeRendered.subtract(range);
+  if (newRange.length === 2) {
+    throw new Error('Can only remove nodes at the beginning or end of the existing range. ' + this.viewRangeRendered + '. New: ' + newRange);
+  }
+  this.viewRangeRendered = newRange[0];
+
+  for (i = range.from; i < range.to; i++) {
+    node = nodes[i];
+    this._removeNode(node);
+    numNodesRemoved++;
+  }
+
+  if ($.log.isTraceEnabled()) {
+    $.log.trace(numNodesRemoved + ' nodes removed from ' + range + '.');
+  }
+};
+
+/**
+ * Just removes the node, does NOT adjust this.viewRangeRendered
+ */
+scout.Tree.prototype._removeNode = function(node) {
+  var $node = node.$node;
+  if (!$node) {
+    return;
+  }
+  if ($node.hasClass('hiding')) {
+    // Do not remove nodes which are removed using an animation
+    return;
+  }
+  //only remove node
+  $node.detach();
+  node.attached = false;
+};
+
+/**
+ * Renders the rows visible in the viewport and removes the other rows
+ */
+scout.Tree.prototype._renderViewRange = function(viewRange) {
+  if (viewRange.from === this.viewRangeRendered.from && viewRange.to === this.viewRangeRendered.to && !this.viewRangeDirty) {
+    // Range already rendered -> do nothing
+    return;
+  }
+  var scrollTop = this.$data[0].scrollTop;
+  if (!this.viewRangeDirty) {
+    var rangesToRender = viewRange.subtract(this.viewRangeRendered);
+    var rangesToRemove = this.viewRangeRendered.subtract(viewRange);
+    var maxRange = new scout.Range(0, this.visibleNodesFlat.length);
+
+    rangesToRemove.forEach(function(range) {
+      this._removeNodesInRange(range);
+      if (maxRange.to < range.to) {
+        this.viewRangeRendered = viewRange;
+      }
+    }.bind(this));
+    rangesToRender.forEach(function(range) {
+      this._renderNodesInRange(range);
+    }.bind(this));
+  } else {
+    //expansion changed
+    this.viewRangeRendered = viewRange;
+    this.ensureRangeVisible(viewRange);
+  }
+
+  // check if at least last and first row in range got correctly rendered
+  if (this.viewRangeRendered.size() > 0) {
+    var nodes = this.visibleNodesFlat;
+    var firstNode = nodes[this.viewRangeRendered.from];
+    var lastNode = nodes[this.viewRangeRendered.to - 1];
+    if (this.viewRangeDirty) {
+      // cleanup nodes before range and after
+      var $nodesBeforFirstNode = firstNode.$node.prevAll('.tree-node');
+      var $nodesAfterLastNode = lastNode.$node.nextAll('.tree-node');
+      this._cleanupNodes($nodesBeforFirstNode);
+      this._cleanupNodes($nodesAfterLastNode);
+    }
+    if (!firstNode.attached || !lastNode.attached) {
+      throw new Error('Nodes not rendered as expected. ' + this.viewRangeRendered + '. First: ' + firstNode.$node + '. Last: ' + lastNode.$node);
     }
   }
 
-  this.invalidateLayoutTree();
+  this._postRenderViewRange();
+  this.$data[0].scrollTop = scrollTop;
+  this.viewRangeDirty = false;
+};
 
-  //return the last created node
-  return $predecessor;
+scout.Tree.prototype._postRenderViewRange = function() {
+  this._renderFiller();
+  this._updateDomNodeWidth();
+  this._renderSelection();
+};
+
+scout.Tree.prototype._updateDomNodeWidth = function($nodes) {
+  if (!this.isHorizontalScrollingEnabled()) {
+    return;
+  }
+  if (this.rendered && this.nodeWidthDirty) {
+    for (var i = this.viewRangeRendered.from; i < this.viewRangeRendered.to; i++) {
+      this.maxNodeWidth = Math.max(this.visibleNodesFlat[i].width, this.maxNodeWidth);
+    }
+    var width = Math.max(this.maxNodeWidth, this.$data.outerWidth());
+    this.$data.find('.tree-node').css('width', this.maxNodeWidth);
+    this.nodeWidthDirty = false;
+  }
+};
+
+scout.Tree.prototype._cleanupNodes = function($nodes) {
+  for (var i = 0; i < $nodes.length; i++) {
+    this._removeNode($nodes.eq(i).data('node'));
+  }
+};
+
+/**
+ * Returns the index of the node which is at position scrollTop.
+ */
+scout.Tree.prototype._nodeAtScrollTop = function(scrollTop) {
+  var height = 0,
+    nodeTop;
+  this.visibleNodesFlat.some(function(node, i) {
+    height += this._heightForNode(node);
+    if (scrollTop < height) {
+      nodeTop = node;
+      return true;
+    }
+  }.bind(this));
+  var visibleNodesLength = this.visibleNodesFlat.length;
+  if (!nodeTop && visibleNodesLength > 0) {
+    nodeTop = this.visibleNodesFlat[visibleNodesLength - 1];
+  }
+  return nodeTop;
+};
+
+scout.Tree.prototype._heightForNode = function(node) {
+  var height = 0;
+  if (node.height) {
+    height = node.height;
+  } else {
+    height = this.nodeHeight;
+  }
+  return height;
+};
+
+scout.Tree.prototype._widthForNode = function(node) {
+  var width = 0;
+  if (node.width) {
+    width = node.width;
+  } else {
+    width = this.nodeWidth;
+  }
+  return width;
+};
+
+/**
+ * Returns a range of size this.viewRangeSize. Start of range is rowIndex - viewRangeSize / 4.
+ * -> 1/4 of the nodes are before the viewport 2/4 in the viewport 1/4 after the viewport,
+ * assuming viewRangeSize is 2*number of possible nodes in the viewport (see calculateViewRangeSize).
+ */
+scout.Tree.prototype._calculateViewRangeForNode = function(node) {
+  var viewRange = new scout.Range(),
+    quarterRange = Math.floor(this.viewRangeSize / 4),
+    diff;
+
+  var nodeIndex = this.visibleNodesFlat.indexOf(node);
+  viewRange.from = Math.max(nodeIndex - quarterRange, 0);
+  viewRange.to = Math.min(viewRange.from + this.viewRangeSize, this.visibleNodesFlat.length);
+  if (!node || nodeIndex === -1) {
+    return viewRange;
+  }
+
+  // Try to use the whole viewRangeSize (extend from if necessary)
+  diff = this.viewRangeSize - viewRange.size();
+  if (diff > 0) {
+    viewRange.from = Math.max(viewRange.to - this.viewRangeSize, 0);
+  }
+  return viewRange;
+};
+
+/**
+ * Calculates the optimal view range size (number of nodes to be rendered).
+ * It uses the default node height to estimate how many nodes fit in the view port.
+ * The view range size is this value * 2.
+ */
+scout.Tree.prototype.calculateViewRangeSize = function() {
+  // Make sure row height is up to date (row height may be different after zooming)
+  this._updateNodeDimensions();
+
+  if (this.nodeHeight === 0) {
+    throw new Error('Cannot calculate view range with nodeHeight = 0');
+  }
+  return Math.ceil(this.$data.outerHeight() / this.nodeHeight) * 2;
+};
+
+scout.Tree.prototype.setViewRangeSize = function(viewRangeSize) {
+  if (this.viewRangeSize === viewRangeSize) {
+    return;
+  }
+  this.viewRangeSize = viewRangeSize;
+  if (this.rendered) {
+    this._renderViewport();
+  }
+};
+
+scout.Tree.prototype._updateNodeDimensions = function() {
+  var node = {
+    level: 0
+  };
+  var $emptyNode = this._$buildNode(node).appendTo(this.$data);
+  this._renderNodeText(node);
+  this.nodeHeight = $emptyNode.outerHeight(true);
+  if (this.isHorizontalScrollingEnabled()) {
+    var oldNodeWidth = this.nodeWidth;
+    this.nodeWidth = $emptyNode.outerWidth(true);
+    if (oldNodeWidth !== this.nodeWidth) {
+      this.viewRangeDirty = true;
+    }
+  }
+  $emptyNode.remove();
+};
+
+/**
+ * Updates the node heights for every visible node and clears the height of the others
+ */
+scout.Tree.prototype.updateNodeHeights = function() {
+  this.visibleNodesFlat.forEach(function(node) {
+    if (!node.attached) {
+      node.height = null;
+    } else {
+      node.height = node.$node.outerHeight(true);
+    }
+  });
 };
 
 /**
@@ -235,11 +741,17 @@
   }
 
   nodes.forEach(function(node) {
+    this._removeFromFlatList(node, true);
     if (node.childNodes.length > 0) {
       this._removeNodes(node.childNodes, node);
     }
     if (node.$node) {
+      if (this._$animationWrapper && this._$animationWrapper.find(node.$node).length > 0) {
+        this._$animationWrapper.stop(false, true);
+      }
       node.$node.remove();
+      node.rendered = false;
+      node.attached = false;
       delete node.$node;
     }
   }, this);
@@ -248,30 +760,27 @@
   //--> makes it consistent with addNodes and expand (expansion is not allowed if there are no child nodes)
   var $parentNode = (parentNode ? parentNode.$node : undefined);
   if ($parentNode) {
-    if (!parentNode) {
-      parentNode = $parentNode.data('node');
-    }
     var childNodesOfParent = parentNode.childNodes;
     if (!childNodesOfParent || childNodesOfParent.length === 0) {
       $parentNode.removeClass('expanded');
       $parentNode.removeClass('lazy');
     }
   }
-
-  this.invalidateLayoutTree();
+  if (this.rendered) {
+    this.viewRangeDirty = true;
+    this.invalidateLayoutTree();
+  }
 };
 
-scout.Tree.prototype._$buildNode = function(node, $parent) {
-  var level = $parent ? parseFloat($parent.attr('data-level')) + 1 : 0;
-
+scout.Tree.prototype._$buildNode = function(node) {
   var $node = this.$container.makeDiv('tree-node')
     .data('node', node)
     .attr('data-nodeid', node.id)
-    .attr('data-level', level)
-    .css('padding-left', this._computeTreeItemPaddingLeft(level));
+    .attr('data-level', node.level)
+    .css('padding-left', this._computeTreeItemPaddingLeft(node.level));
   node.$node = $node;
+  $node.appendSpan('text');
 
-  this._decorateNode(node);
   this._renderTreeItemControl($node);
 
   if (this.checkable) {
@@ -293,8 +802,11 @@
   if ($node.isSelected()) {
     formerClasses += ' selected';
   }
-  if ($node.hasClass('group')) {
-    formerClasses += ' group';
+  if ($node.hasClass('ancestor-of-selected')) {
+    formerClasses += ' ancestor-of-selected';
+  }
+  if ($node.hasClass('parent-of-selected')) {
+    formerClasses += ' parent-of-selected';
   }
   $node.removeClass();
   $node.addClass(formerClasses);
@@ -302,6 +814,7 @@
   $node.toggleClass('leaf', !!node.leaf);
   $node.toggleClass('expanded', (!!node.expanded && node.childNodes.length > 0));
   $node.toggleClass('lazy', $node.hasClass('expanded') && node.expandedLazy);
+  $node.toggleClass('group', !!this.groupedNodes[node.id]);
   $node.setEnabled(!!node.enabled);
   $node.children('.tree-node-checkbox')
     .children('.check-box')
@@ -314,40 +827,21 @@
     $node.addClass('child-of-selected');
   }
 
-  // Replace only the "text part" of the node, leave control and checkbox untouched
-  var preservedChildren = $node.children('.tree-node-control,.tree-node-checkbox').detach();
-  $node.empty();
-  if (node.htmlEnabled) {
-    $node.html(node.text);
-  } else {
-    $node.textOrNbsp(node.text);
-  }
-  $node.prepend(preservedChildren);
+  this._renderNodeText(node);
 
   scout.styles.legacyStyle(node, $node);
 
-  // apply node filter
-  if (this._applyFiltersForNode(node)) {
-    var newHiddenNodes = [];
-    if (!node.filterAccepted) {
-      newHiddenNodes.push(node);
-    }
-    this._nodesFiltered(newHiddenNodes);
-  }
-  this._renderNodeFilterAccepted(node);
-
   // TODO [5.2] bsh: More attributes...
   // iconId
 
-  // If parent node is marked as 'lazy', check if any hidden child nodes remain.
-  if (node.parentNode && node.parentNode.$node.hasClass('lazy')) {
-    var hasHiddenNodes = node.parentNode.childNodes.some(function(childNode) {
-      if (!childNode.$node || childNode.$node.hasClass('hidden')) {
+  // If parent node is marked as 'lazy', check if any visible child nodes remain.
+  if (node.parentNode && node.parentNode.expandedLazy) {
+    var hasVisibleNodes = node.parentNode.childNodes.some(function(childNode) {
+      if (this.visibleNodesMap[childNode.id]) {
         return true;
       }
-      return false;
-    });
-    if (!hasHiddenNodes) {
+    }.bind(this));
+    if (!hasVisibleNodes && node.parentNode.$node) {
       // Remove 'lazy' from parent
       node.parentNode.$node.removeClass('lazy');
     }
@@ -376,6 +870,16 @@
   }
 };
 
+scout.Tree.prototype._renderNodeText = function(node) {
+  var $node = node.$node,
+    $text = $node.children('.text');
+  if (node.htmlEnabled) {
+    $text.html(node.text);
+  } else {
+    $text.textOrNbsp(node.text);
+  }
+};
+
 scout.Tree.prototype._renderNodeChecked = function(node) {
   if (!node.$node) {
     // if node is not rendered, do nothing
@@ -388,17 +892,12 @@
     .toggleClass('checked', node.checked);
 };
 
-scout.Tree.prototype._renderNodeFilterAccepted = function(node, animated) {
-  if (node.filterAccepted) {
-    this.showNode(node.$node, animated);
-  } else {
-    this.hideNode(node.$node, animated);
-  }
+scout.Tree.prototype._renderMenus = function() {
+  // NOP
 };
 
-scout.Tree.prototype._renderMenus = function() {
-  var menuItems = this._filterMenus(this.menus, scout.MenuDestinations.MENU_BAR, false, true);
-  this.menuBar.updateItems(menuItems);
+scout.Tree.prototype._removeMenus = function() {
+  // menubar takes care about removal
 };
 
 scout.Tree.prototype._filterMenus = function(menus, destination, onlyVisible, enableDisableKeyStroke) {
@@ -467,12 +966,19 @@
   // NOP
 };
 
-scout.Tree.prototype._renderBreadcrumbEnabled = function() {
-  this.$container.toggleClass('breadcrumb', this.breadcrumbEnabled);
+scout.Tree.prototype._renderDisplayStyle = function() {
+  this.$container.toggleClass('breadcrumb', this.isBreadcrumbStyleActive());
+
+  // update scrollbar if mode has changed (from tree to bc or vice versa)
+  this.invalidateLayoutTree();
 };
 
-scout.Tree.prototype._renderExpansion = function(node, $predecessor, animate) {
-  animate = scout.nvl(animate, true);
+scout.Tree.prototype._renderExpansion = function(node, options) {
+  var opts = {
+    expandLazyChanged: false,
+    expansionChanged: false
+  };
+  $.extend(opts, options);
 
   var $node = node.$node,
     expanded = node.expanded;
@@ -487,80 +993,16 @@
     return true;
   }
 
-  // Render lazy expansion
-  if (expanded && $node.hasClass('expanded') && !node.expandedLazy && $node.hasClass('lazy')) {
-    // If node is already expanded but only lazy -> expand completely
-    this._showAllNodes(node);
-  }
   $node.toggleClass('lazy', expanded && node.expandedLazy);
-
-  if (expanded === $node.hasClass('expanded')) {
+  if (!opts.expansionChanged && !opts.expandLazyChanged) {
     // Expansion state has not changed -> return
     return;
   }
 
-  // If there is already an animation is already going on for this node, stop it immediately
-  if (this._$animationWrapper) {
-    // Note: Do _not_ use finish() here! Although documentation states that it is "similar" to stop(true, true),
-    // this does not seem to be the case. Implementations differ slightly in details. The effect is, that when
-    // calling stop() the animation stops and the 'complete' callback is executed immediately. However, when calling
-    // finish(), the callback is _not_ executed! (This may or may not be a bug in jQuery, I cannot tell...)
-    this._$animationWrapper.stop(false, true);
-  }
-
   if (expanded) {
-    this._addNodes(node.childNodes, $node, $predecessor);
-    this._updateItemPath();
-
-    // animate opening
-    animate = animate && this.rendered; // don't animate while rendering (not necessary, or may even lead to timing issues)
-    animate = animate && !$node.hasClass('leaf') && !$node.hasClass('expanded') && !this.breadcrumbEnabled;
-    if (animate) {
-      var $newNodes = scout.Tree.collectSubtree($node, false);
-      if ($newNodes.length) {
-        this._$animationWrapper = $newNodes.wrapAll('<div class="animation-wrapper">').parent();
-        var h = this._$animationWrapper.outerHeight();
-        this._$animationWrapper
-          .css('height', 0)
-          .animateAVCSD('height', h, onAnimationComplete.bind(this, true), this.revalidateLayoutTree.bind(this), 200);
-      }
-    }
     $node.addClass('expanded');
   } else {
     $node.removeClass('expanded');
-
-    // animate closing
-    if (this.rendered) { // don't animate while rendering (not necessary, or may even lead to timing issues)
-      var $existingNodes = scout.Tree.collectSubtree($node, false);
-      if ($existingNodes.length) {
-        $existingNodes.each(function() {
-          // unlink '$nodes' from 'nodes' before deleting them
-          var node = $(this).data('node');
-          if (node) { // FIXME bsh: Tree | This if should not be necessary! 'node' should not be undefined, but is sometimes... Check why!
-            delete node.$node;
-          }
-        });
-        if (animate) {
-          this._$animationWrapper = $existingNodes.wrapAll('<div class="animation-wrapper">)').parent();
-          this._$animationWrapper
-            .animateAVCSD('height', 0, onAnimationComplete.bind(this, false), this.revalidateLayoutTree.bind(this), 200);
-        } else {
-          $existingNodes.remove();
-          this.invalidateLayoutTree();
-        }
-      }
-    }
-  }
-
-  // ----- Helper functions -----
-
-  function onAnimationComplete(expanding) {
-    if (expanding) {
-      this._$animationWrapper.replaceWith(this._$animationWrapper.contents());
-    } else {
-      this._$animationWrapper.remove();
-    }
-    this._$animationWrapper = null;
   }
 };
 
@@ -568,75 +1010,97 @@
   // Add children class to root nodes if no nodes are selected
   if (this.selectedNodes.length === 0) {
     this.nodes.forEach(function(childNode) {
-      childNode.$node.addClass('child-of-selected');
+      if (childNode.rendered) {
+        childNode.$node.addClass('child-of-selected');
+      }
     }, this);
   }
 
   this.selectedNodes.forEach(function(node) {
-    var $node = node.$node;
-
-    // If $node is currently not displayed (due to a collapsed parent node), expand the parents
-    if (!$node) {
-      this._expandAllParentNodes(node);
-      $node = node.$node;
-      if (!$node || $node.length === 0) {
-        throw new Error('Still no node found. node=' + node);
-      }
+    if (!this.visibleNodesMap[node.id]) {
+      return;
     }
 
-    $node.select(true);
-
-    // If node was previously hidden, show it!
-    $node.removeClass('hidden');
-
     // Mark all ancestor nodes, especially necessary for bread crumb mode
     var parentNode = node.parentNode;
+    if (parentNode && parentNode.rendered) {
+      parentNode.$node.addClass('parent-of-selected');
+    }
     while (parentNode) {
-      parentNode.$node.addClass('ancestor-of-selected');
+      if (parentNode.rendered) {
+        parentNode.$node.addClass('ancestor-of-selected');
+      }
       parentNode = parentNode.parentNode;
     }
 
     // Mark all child nodes
     if (node.expanded) {
       node.childNodes.forEach(function(childNode) {
-        childNode.$node.addClass('child-of-selected');
+        if (childNode.rendered) {
+          childNode.$node.addClass('child-of-selected');
+        }
       }, this);
     }
+
+    if (node.rendered) {
+      node.$node.select(true);
+    }
   }, this);
 
-  this._updateItemPath();
   if (this.scrollToSelection) {
     // Execute delayed because tree may be not layouted yet
     setTimeout(this.revealSelection.bind(this));
   }
+  this._redecorateViewRange();
+};
+
+scout.Tree.prototype._redecorateViewRange = function() {
+  if (this.rendered) {
+    for (var i = this.viewRangeRendered.from; i < this.viewRangeRendered.to; i++) {
+      if (i >= this.visibleNodesFlat.length) {
+        break;
+      }
+      this._decorateNode(this.visibleNodesFlat[i]);
+    }
+  }
 };
 
 scout.Tree.prototype._removeSelection = function() {
   // Remove children class on root nodes if no nodes were selected
   if (this.selectedNodes.length === 0) {
     this.nodes.forEach(function(childNode) {
-      childNode.$node.removeClass('child-of-selected');
+      if (childNode.rendered) {
+        childNode.$node.removeClass('child-of-selected');
+      }
     }, this);
   }
 
-  this.selectedNodes.forEach(function(node) {
-    var $node = node.$node;
-    if ($node) { // TODO [5.2] bsh: Check if $node can be undefined
-      $node.select(false);
+  this.selectedNodes.forEach(this._removeNodeSelection, this);
+};
 
-      // remove ancestor and child classes
-      var parentNode = node.parentNode;
-      while (parentNode) {
-        parentNode.$node.removeClass('ancestor-of-selected');
-        parentNode = parentNode.parentNode;
+scout.Tree.prototype._removeNodeSelection = function(node) {
+  var $node = node.$node;
+  if (!$node) {
+    return;
+  }
+  $node.select(false);
+
+  // remove ancestor and child classes
+  var parentNode = node.parentNode;
+  if (parentNode) {
+    parentNode.$node.removeClass('parent-of-selected');
+  }
+  while (parentNode) {
+    parentNode.$node.removeClass('ancestor-of-selected');
+    parentNode = parentNode.parentNode;
+  }
+  if (node.expanded) {
+    node.childNodes.forEach(function(childNode) {
+      if (childNode.rendered) {
+        childNode.$node.removeClass('child-of-selected');
       }
-      if (node.expanded) {
-        node.childNodes.forEach(function(childNode) {
-          childNode.$node.removeClass('child-of-selected');
-        }, this);
-      }
-    }
-  }, this);
+    }, this);
+  }
 };
 
 scout.Tree.prototype._renderDropType = function() {
@@ -776,7 +1240,7 @@
   if (node.tooltipText) {
     return node.tooltipText;
   } else if (this._isTruncatedNodeTooltipEnabled() && $node.isContentTruncated()) {
-    return $node.text();
+    return $node.children('.text').text();
   }
 };
 
@@ -784,29 +1248,56 @@
   return true;
 };
 
-scout.Tree.prototype.setBreadcrumbEnabled = function(enabled, notifyServer) {
-  if (this.breadcrumbEnabled === enabled) {
+scout.Tree.prototype.setDisplayStyle = function(displayStyle, notifyServer) {
+  if (this.displayStyle === displayStyle) {
     return;
   }
-
-  // update scrollbar if mode has changed (from tree to bc or vice versa)
-  this.revalidateLayoutTree();
-
-  this.breadcrumbEnabled = enabled;
+  this._renderViewportBlocked = true;
+  this._setProperty('displayStyle', displayStyle);
+  notifyServer = scout.nvl(notifyServer, true);
   if (notifyServer) {
-    this._sendBreadCrumbEnabled();
+    this._sendProperty('displayStyle');
   }
 
-  if (enabled && this.selectedNodes.length > 0) {
+  if (displayStyle && this.selectedNodes.length > 0) {
     var selectedNode = this.selectedNodes[0];
     if (!selectedNode.expanded) {
       this.expandNode(selectedNode);
     }
   }
 
-  if (this.rendered) {
-    this._renderBreadcrumbEnabled();
+  if (this.displayStyle === scout.Tree.DisplayStyle.BREADCRUMB) {
+    this.addFilter(this.breadcrumbFilter, true, true);
+    this.filterVisibleNodes();
+  } else if (this.displayStyle !== scout.Tree.DisplayStyle.BREADCRUMB) {
+    this.removeFilter(this.breadcrumbFilter, true);
+    this.filter();
   }
+
+  if (this.rendered) {
+    this._renderDisplayStyle();
+  }
+  this._renderViewportBlocked = false;
+};
+
+scout.Tree.prototype.setBreadcrumbStyleActive = function(active, notifyServer) {
+  if (active) {
+    this.setDisplayStyle(scout.Tree.DisplayStyle.BREADCRUMB, notifyServer);
+  } else if (!active) {
+    this.setDisplayStyle(scout.Tree.DisplayStyle.DEFAULT, notifyServer);
+  }
+};
+
+scout.Tree.prototype.isNodeInBreadcrumbVisible = function(node) {
+  return this._inSelectionPathList[node.id] === undefined ? false : this._inSelectionPathList[node.id];
+};
+
+scout.Tree.prototype.isBreadcrumbStyleActive = function() {
+  return this.displayStyle === scout.Tree.DisplayStyle.BREADCRUMB;
+};
+
+scout.Tree.prototype.setBreadcrumbTogglingThreshold = function(width) {
+  this.breadcrumbTogglingThreshold = width;
 };
 
 scout.Tree.prototype.expandNode = function(node, opts) {
@@ -818,23 +1309,32 @@
 };
 
 scout.Tree.prototype.collapseAll = function() {
+  this.rebuildSuppressed = true;
   // Collapse all expanded child nodes (only model)
   this._visitNodes(this.nodes, function(node) {
     this.collapseNode(node);
   }.bind(this));
+
+  if (this.rendered) {
+    // ensure correct rendering
+    this._rerenderViewport();
+  }
+
+  this.rebuildSuppressed = false;
 };
 
 scout.Tree.prototype.setNodeExpanded = function(node, expanded, opts) {
   opts = opts || {};
   var lazy = scout.nvl(opts.lazy, node.lazyExpandingEnabled);
   var notifyServer = scout.nvl(opts.notifyServer, true);
+  var renderAnimated = scout.nvl(opts.renderAnimated, true);
 
   // Never do lazy expansion if it is disabled on the tree
   if (!this.lazyExpandingEnabled) {
     lazy = false;
   }
 
-  if (this.breadcrumbEnabled) {
+  if (this.isBreadcrumbStyleActive()) {
     // Do not allow to collapse a selected node
     if (!expanded && this.selectedNodes.indexOf(node) > -1) {
       this.setNodeExpanded(node, true, opts);
@@ -854,12 +1354,34 @@
       }
     }.bind(this));
   }
+  var renderExpansionOpts = {
+    expansionChanged: false,
+    expandLazyChanged: false
+  };
 
   // Set expansion state
   if (node.expanded !== expanded || node.expandedLazy !== lazy) {
+    renderExpansionOpts.expansionChanged = node.expanded !== expanded;
+    renderExpansionOpts.expandLazyChanged = node.expandedLazy !== lazy;
     node.expanded = expanded;
     node.expandedLazy = lazy;
+    if (this.groupedNodes[node.id]) {
+      this._updateItemPath(false, node);
+    }
+    var filterStateChanged = this._applyFiltersForNode(node);
+    if (filterStateChanged && renderExpansionOpts.expansionChanged) {
+      this._rebuildParent(node.parentNode, opts);
+    } else if (renderExpansionOpts.expandLazyChanged) {
+      node.childNodes.forEach(function(child) {
+        this._applyFiltersForNode(child);
+      }.bind(this));
+    }
 
+    if (node.expanded) {
+      this._addChildrenToFlatList(node, null, renderAnimated, null, true);
+    } else {
+      this._removeChildrenFromFlatList(node, renderAnimated);
+    }
     if (notifyServer) {
       this._send('nodeExpanded', {
         nodeId: node.id,
@@ -867,20 +1389,372 @@
         expandedLazy: lazy
       });
     }
+    this.viewRangeDirty = true;
   }
 
   // Render expansion
   if (this.rendered && scout.nvl(opts.renderExpansion, true)) {
-    this._renderExpansion(node, null, opts.animateExpansion);
+    this._renderExpansion(node, renderExpansionOpts);
+  }
+};
+
+scout.Tree.prototype._rebuildParent = function(node, opts) {
+  if (this.rebuildSuppressed) {
+    return;
+  }
+  if (node.expanded || node.expandedLazy) {
+    this._addChildrenToFlatList(node, null, false, null, true);
+  } else {
+    this._removeChildrenFromFlatList(node, false);
+  }
+  //Render expansion
+  if (this.rendered && scout.nvl(opts.renderExpansion, true)) {
+    var renderExpansionOpts = {
+      expansionChanged: true
+    };
+    this._renderExpansion(node, renderExpansionOpts);
+  }
+};
+
+scout.Tree.prototype._removeChildrenFromFlatList = function(parentNode, animatedRemove) {
+  //Only if a parent is available the children are available.
+  if (this.visibleNodesMap[parentNode.id]) {
+    var parentIndex = this.visibleNodesFlat.indexOf(parentNode);
+    var elementsToDelete = 0;
+    var parentLevel = parentNode.level;
+    var removedNodes = [];
+    animatedRemove = animatedRemove && this.rendered;
+    if (this._$animationWrapper) {
+      // Note: Do _not_ use finish() here! Although documentation states that it is "similar" to stop(true, true),
+      // this does not seem to be the case. Implementations differ slightly in details. The effect is, that when
+      // calling stop() the animation stops and the 'complete' callback is executed immediately. However, when calling
+      // finish(), the callback is _not_ executed! (This may or may not be a bug in jQuery, I cannot tell...)
+      this._$animationWrapper.stop(false, true);
+    }
+    this._$expandAnimationWrappers.forEach(function($wrapper) {
+      $wrapper.stop(false, true);
+    });
+    for (var i = parentIndex + 1; i < this.visibleNodesFlat.length; i++) {
+      if (this.visibleNodesFlat[i].level > parentLevel) {
+        var node = this.visibleNodesFlat[i];
+        if (this.isHorizontalScrollingEnabled()) {
+          //if node is the node which defines the widest width then recalculate width for render
+          if (node.width === this.maxNodeWidth) {
+            this.maxNodeWidth = 0;
+            this.nodeWidthDirty = true;
+          }
+        }
+        delete this.visibleNodesMap[this.visibleNodesFlat[i].id];
+        if (node.attached && animatedRemove) {
+          if (!this._$animationWrapper) {
+            this._$animationWrapper = $('<div class="animation-wrapper">').insertBefore(node.$node);
+            this._$animationWrapper.data('parentNode', parentNode);
+          }
+          if (node.isChildOf(this._$animationWrapper.data('parentNode'))) {
+            this._$animationWrapper.append(node.$node);
+          }
+          node.attached = false;
+          node.displayBackup = node.$node.css('display');
+          removedNodes.push(node);
+        } else if (node.attached && !animatedRemove) {
+          this.hideNode(node, false, false);
+        }
+        elementsToDelete++;
+      } else {
+        break;
+      }
+    }
+
+    this.visibleNodesFlat.splice(parentIndex + 1, elementsToDelete);
+    // animate closing
+    if (animatedRemove) { // don't animate while rendering (not necessary, or may even lead to timing issues)
+      this._renderViewportBlocked = true;
+      if (removedNodes.length > 0) {
+        this._$animationWrapper.animate({
+          height: 0
+        }, {
+          start: this.startAnimationFunc,
+          complete: onAnimationComplete.bind(this, removedNodes),
+          duration: 200,
+          queue: false
+        });
+      } else if (this._$animationWrapper) {
+        this._$animationWrapper.remove();
+        this._$animationWrapper = null;
+        onAnimationComplete.call(this, removedNodes);
+      } else {
+        this._renderViewportBlocked = false;
+      }
+    }
+    return removedNodes;
+  }
+
+  //----- Helper functions -----
+  function onAnimationComplete(affectedNodes) {
+    affectedNodes.forEach(function(node) {
+      node.$node.detach();
+      node.$node.css('display', node.displayBackup);
+      node.displayBackup = null;
+    });
+    if (this._$animationWrapper) {
+      this._$animationWrapper.remove();
+      this._$animationWrapper = null;
+    }
+    this.runningAnimationsFinishFunc();
+  }
+
+};
+
+scout.Tree.prototype._removeFromFlatList = function(node, animatedRemove) {
+  var removedNodes = [];
+  if (this.visibleNodesMap[node.id]) {
+    var index = this.visibleNodesFlat.indexOf(node);
+    this._removeChildrenFromFlatList(node, false);
+    if (this.isHorizontalScrollingEnabled()) {
+      //if node is the node which defines the widest width then recalculate width for render
+      if (node.width === this.maxNodeWidth) {
+        this.maxNodeWidth = 0;
+        this.nodeWidthDirty = true;
+      }
+    }
+    removedNodes = scout.arrays.ensure(this.visibleNodesFlat.splice(index, 1));
+    delete this.visibleNodesMap[node.id];
+    this.hideNode(node, animatedRemove);
+  }
+  removedNodes.push(node);
+  return removedNodes;
+};
+
+scout.Tree.prototype._addToVisibleFlatList = function(node, renderingAnimated) {
+  // if node already is in visible list don't do anything. If no parentNode is available this node is on toplevel, if a parent is available
+  // it has to be in visible list and also be expanded
+  if (!this.visibleNodesMap[node.id] && node.isFilterAccepted() && (!node.parentNode ||
+      (node.parentNode.expanded && this.visibleNodesMap[node.parentNode.id]))) {
+    if (this.initialTraversing) {
+      // for faster index calculation
+      this._addToVisibleFlatListNoCheck(node, this.visibleNodesFlat.length, renderingAnimated);
+    } else {
+      var insertIndex = this._findIndexToInsertNode(node);
+      this._addToVisibleFlatListNoCheck(node, insertIndex, renderingAnimated);
+    }
+  }
+};
+
+scout.Tree.prototype._findIndexToInsertNode = function(node) {
+  var findValidSiblingBefore = function(childNodeIndex, siblings) {
+    for (var i = childNodeIndex - 1; i >= 0; i--) {
+      if (siblings[i].isFilterAccepted()) {
+        return siblings[i];
+      }
+    }
+    // no sibling before
+    return null;
+  }.bind(this);
+  // function to traverse last child nodes to first child nodes of a parent.
+  var findLastVisibleNodeInParent = function(parent) {
+    if (parent.expanded) {
+      for (var i = parent.childNodes.length - 1; i >= 0; i--) {
+        if (parent.childNodes[i].isFilterAccepted()) {
+          if (parent.childNodes[i].expanded) {
+            return findLastVisibleNodeInParent(parent.childNodes[i]);
+          } else if (this.visibleNodesMap[parent.childNodes[i].id]) {
+            return parent.childNodes[i];
+          }
+        }
+      }
+    }
+    return parent;
+  }.bind(this);
+
+  var parentNode = node.parentNode,
+    siblingBefore, nodeBefore;
+  if (!parentNode) {
+    // use toplevel to find index
+    siblingBefore = findValidSiblingBefore(node.childNodeIndex, this.nodes);
+    if (!siblingBefore) {
+      return 0;
+    }
+    nodeBefore = findLastVisibleNodeInParent(siblingBefore);
+    return this.visibleNodesFlat.indexOf(nodeBefore) + 1;
+  } else {
+    siblingBefore = findValidSiblingBefore(node.childNodeIndex, node.parentNode.childNodes);
+    if (!siblingBefore) {
+      return this.visibleNodesFlat.indexOf(parentNode) + 1;
+    }
+    nodeBefore = findLastVisibleNodeInParent(siblingBefore);
+    return this.visibleNodesFlat.indexOf(nodeBefore) + 1;
+  }
+};
+
+scout.Tree.prototype._addChildrenToFlatList = function(parentNode, parentIndex, animatedRendering, insertBatch, forceFilter) {
+  //add nodes recursively
+  if (!this.visibleNodesMap[parentNode.id]) {
+    return 0;
+  }
+  var isSubAdding = !!insertBatch;
+  parentIndex = parentIndex ? parentIndex : this.visibleNodesFlat.indexOf(parentNode);
+  animatedRendering = animatedRendering && this.rendered; // don't animate while rendering (not necessary, or may even lead to timing issues)
+  if (this._$animationWrapper && !isSubAdding) {
+    // Note: Do _not_ use finish() here! Although documentation states that it is "similar" to stop(true, true),
+    // this does not seem to be the case. Implementations differ slightly in details. The effect is, that when
+    // calling stop() the animation stops and the 'complete' callback is executed immediately. However, when calling
+    // finish(), the callback is _not_ executed! (This may or may not be a bug in jQuery, I cannot tell...)
+    this._$animationWrapper.stop(false, true);
+  }
+  insertBatch = insertBatch ? insertBatch : this.setUpInsertBatch(parentIndex + 1);
+  parentNode.childNodes.forEach(function(node, index) {
+    var isAlreadyAdded = this.visibleNodesMap[node.id];
+    if (node.initialized && node.isFilterAccepted(forceFilter) && !isAlreadyAdded) {
+      insertBatch.insertNodes.push(node);
+      this.visibleNodesMap[node.id] = true;
+      insertBatch = this.checkAndHandleBatch(insertBatch, parentNode, animatedRendering);
+      if (node.expanded) {
+        insertBatch = this._addChildrenToFlatList(node, insertBatch.lastBatchInsertIndex(), animatedRendering, insertBatch, forceFilter);
+      }
+    } else if (node.initialized && node.isFilterAccepted(forceFilter) && isAlreadyAdded) {
+      this.insertBatchInVisibleNodes(insertBatch, this.viewRangeRendered.from + this.viewRangeSize >= insertBatch.lastBatchInsertIndex() && this.viewRangeRendered.from <= insertBatch.lastBatchInsertIndex(), animatedRendering);
+      this.checkAndHandleBatchAnimationWrapper(parentNode, animatedRendering, insertBatch);
+      var updateIndex = insertBatch.insertedAny() ? 2 : 1;
+      insertBatch = this.setUpInsertBatch(insertBatch.lastBatchInsertIndex() + updateIndex);
+      if (node.expanded) {
+        insertBatch = this._addChildrenToFlatList(node, insertBatch.lastBatchInsertIndex(), animatedRendering, insertBatch, forceFilter);
+      }
+      //do not animate following
+      animatedRendering = false;
+    }
+  }.bind(this));
+
+  if (!isSubAdding) {
+    // animation is not done yet and all added nodes are in visible range
+    this.insertBatchInVisibleNodes(insertBatch, this.viewRangeRendered.from + this.viewRangeSize >= insertBatch.lastBatchInsertIndex() && this.viewRangeRendered.from <= insertBatch.lastBatchInsertIndex(), animatedRendering);
+    this.invalidateLayoutTree();
+  }
+
+  return insertBatch;
+
+};
+
+scout.Tree.prototype.setUpInsertBatch = function(insertIndex) {
+  return {
+    insertNodes: [insertIndex, 0],
+    $animationWrapper: null,
+    lastBatchInsertIndex: function() {
+      if (this.insertNodes.length === 2) {
+        return this.insertNodes[0];
+      }
+      return this.insertNodes[0] + this.insertNodes.length - 3;
+    },
+    insertedAny: function() {
+      return this.insertNodes.length > 2;
+    }
+  };
+};
+
+scout.Tree.prototype.checkAndHandleBatchAnimationWrapper = function(parentNode, animatedRendering, insertBatch) {
+  if (animatedRendering && this.viewRangeRendered.from <= insertBatch.lastBatchInsertIndex() && this.viewRangeRendered.to >= insertBatch.lastBatchInsertIndex() && !insertBatch.$animationWrapper) {
+    //we are in visible area so we need a animation wrapper
+    //if parent is in visible area insert after parent else insert before first node.
+    var lastNodeIndex = insertBatch.lastBatchInsertIndex() - 1,
+      nodeBefore = this.viewRangeRendered.from === insertBatch.lastBatchInsertIndex() ? null : this.visibleNodesFlat[lastNodeIndex];
+    if (nodeBefore && lastNodeIndex >= this.viewRangeRendered.from && lastNodeIndex < this.viewRangeRendered.to && !nodeBefore.attached) {
+      //ensure node before is visible
+      this.showNode(nodeBefore, false, lastNodeIndex);
+    }
+    if (nodeBefore && nodeBefore.attached) {
+      insertBatch.$animationWrapper = $('<div class="animation-wrapper">').insertAfter(nodeBefore.$node);
+    } else if (parentNode.attached) {
+      insertBatch.$animationWrapper = $('<div class="animation-wrapper">').insertAfter(parentNode.$node);
+    } else if (this.$fillBefore) {
+      insertBatch.$animationWrapper = $('<div class="animation-wrapper">').insertAfter(this.$fillBefore);
+    } else {
+      var nodeAfter = this.visibleNodesFlat[insertBatch.lastBatchInsertIndex()];
+      insertBatch.$animationWrapper = $('<div class="animation-wrapper">').insertBefore(nodeAfter.$node);
+    }
+    insertBatch.animationCompleteFunc = onAnimationComplete;
+    this._$expandAnimationWrappers.push(insertBatch.$animationWrapper);
+  }
+  //----- Helper functions ----- //
+
+  function onAnimationComplete() {
+    insertBatch.$animationWrapper.replaceWith(insertBatch.$animationWrapper.contents());
+    scout.arrays.remove(this._$expandAnimationWrappers, insertBatch.$animationWrapper);
+    insertBatch.$animationWrapper = null;
+    this.runningAnimationsFinishFunc();
+  }
+};
+
+scout.Tree.prototype.checkAndHandleBatch = function(insertBatch, parentNode, animatedRendering) {
+  if (this.viewRangeRendered.from - 1 === insertBatch.lastBatchInsertIndex()) {
+    //do immediate rendering because list could be longer
+    this.insertBatchInVisibleNodes(insertBatch, false, false);
+    insertBatch = this.setUpInsertBatch(insertBatch.lastBatchInsertIndex() + 1);
+  }
+  this.checkAndHandleBatchAnimationWrapper(parentNode, animatedRendering, insertBatch);
+
+  if (this.viewRangeRendered.from + this.viewRangeSize - 1 === insertBatch.lastBatchInsertIndex()) {
+    //do immediate rendering because list could be longer
+    this.insertBatchInVisibleNodes(insertBatch, true, animatedRendering);
+    insertBatch = this.setUpInsertBatch(insertBatch.lastBatchInsertIndex() + 1);
+  }
+  return insertBatch;
+};
+
+scout.Tree.prototype.insertBatchInVisibleNodes = function(insertBatch, showNodes, animate) {
+  if (insertBatch.insertNodes < 3) {
+    //nothing to add
+    return;
+  }
+  this.visibleNodesFlat.splice.apply(this.visibleNodesFlat, insertBatch.insertNodes);
+  if (showNodes) {
+    var indexHint = insertBatch.insertNodes[0];
+    for (var i = 2; i < insertBatch.insertNodes.length; i++) {
+      var node = insertBatch.insertNodes[i];
+      this.showNode(node, false, indexHint);
+      if (insertBatch.$animationWrapper) {
+        insertBatch.$animationWrapper.append(node.$node);
+      }
+      indexHint++;
+    }
+    if (insertBatch.$animationWrapper) {
+      var h = insertBatch.$animationWrapper.outerHeight();
+      insertBatch.$animationWrapper
+        .css('height', 0)
+        .animate({
+          height: h
+        }, {
+          start: this.startAnimationFunc,
+          complete: insertBatch.animationCompleteFunc.bind(this),
+          duration: 200,
+          queue: false
+        });
+    }
+  }
+};
+
+scout.Tree.prototype._addToVisibleFlatListNoCheck = function(node, insertIndex, animatedRendering) {
+  scout.arrays.insert(this.visibleNodesFlat, node, insertIndex);
+  this.visibleNodesMap[node.id] = true;
+  if (this.rendered) {
+    this.showNode(node, animatedRendering, insertIndex);
   }
 };
 
 scout.Tree.prototype.scrollTo = function(node) {
+  if (this.viewRangeRendered.size() === 0) {
+    // Cannot scroll to a node if no node is rendered
+    return;
+  }
+  if (!node.attached) {
+    this._renderViewRangeForNode(node);
+  }
   scout.scrollbars.scrollTo(this.$data, node.$node);
 };
 
 scout.Tree.prototype.revealSelection = function() {
   if (this.selectedNodes.length > 0) {
+    if (!this.visibleNodesMap[this.selectedNodes[0].id]) {
+      this._expandAllParentNodes(this.selectedNodes[0]);
+    }
     this.scrollTo(this.selectedNodes[0]);
   }
 };
@@ -894,38 +1768,49 @@
 };
 
 scout.Tree.prototype.selectNodes = function(nodes, notifyServer, debounceSend) {
+  var scrollTop;
   nodes = scout.arrays.ensure(nodes);
   notifyServer = scout.nvl(notifyServer, true);
+
   if (scout.arrays.equalsIgnoreOrder(nodes, this.selectedNodes)) {
     return;
   }
 
   if (this.rendered) {
+    if (this.isBreadcrumbStyleActive()) {
+      scrollTop = this.$data[0].scrollTop;
+    }
     this._removeSelection();
   }
 
   // Make a copy so that original array stays untouched
   this.selectedNodes = nodes.slice();
+
   if (notifyServer) {
-    var eventData = {
-      nodeIds: this._nodesToIds(nodes)
-    };
+    this._sendNodesSelected(this.selectedNodes, debounceSend);
+  }
+  this._triggerNodesSelected(debounceSend);
 
-    // send delayed to avoid a lot of requests while selecting
-    // coalesce: only send the latest selection changed event for a field
-    this._send('nodesSelected', eventData, debounceSend ? 250 : 0, function(previous) {
-      return this.id === previous.id && this.type === previous.type;
-    });
+  if (this.selectedNodes.length > 0 && !this.visibleNodesMap[this.selectedNodes[0].id]) {
+    this._expandAllParentNodes(this.selectedNodes[0]);
   }
 
-  // In breadcrumb mode selected node has to expanded
-  if (this.breadcrumbEnabled && this.selectedNodes.length > 0 && !this.selectedNodes[0].expanded) {
-    this.expandNode(this.selectedNodes[0]);
+  this._updateItemPath(true);
+  if (this.isBreadcrumbStyleActive()) {
+    // In breadcrumb mode selected node has to expanded
+    if (this.selectedNodes.length > 0 && !this.selectedNodes[0].expanded) {
+      this.expandNode(this.selectedNodes[0]);
+      this.selectedNodes[0].filterDirty = true;
+    }
+    this.filter(true);
   }
-
+  this._updateMenuBar();
   if (this.rendered) {
     this._renderSelection();
-    this._renderMenus();
+    // restore scrollTop (removeSelection removes all the selection classes which makes a lot of elements invisible and therefore the scrollHeight smaller)
+    if (this.isBreadcrumbStyleActive()) {
+      this.$data[0].scrollTop = scrollTop;
+    }
   }
 };
 
@@ -941,6 +1826,10 @@
   }
 };
 
+scout.Tree.prototype.isNodeSelected = function(node) {
+  return this.selectedNodes.indexOf(node) > -1;
+};
+
 scout.Tree.prototype._computeTreeItemPaddingLeft = function(level, selected) {
   if (this.checkable) {
     return level * this._treeItemPaddingLevel + this._treeItemPaddingLeft + this._treeItemCheckBoxPaddingLeft;
@@ -953,21 +1842,29 @@
     parentNodes = [];
 
   currNode = node;
+  var nodesToInsert = [];
   while (currNode.parentNode) {
     parentNodes.push(currNode.parentNode);
+    if (!this.visibleNodesMap[currNode.id]) {
+      nodesToInsert.push(currNode);
+    }
     currNode = currNode.parentNode;
   }
 
   for (i = parentNodes.length - 1; i >= 0; i--) {
-    if (!parentNodes[i].expanded) {
-      $parentNode = parentNodes[i].$node;
-      if (!$parentNode) {
-        throw new Error('Illegal state, $parentNode should be displayed. Rendered: ' + this.rendered + ', parentNode: ' + parentNodes[i]);
-      }
-      this.expandNode(parentNodes[i], {
-        renderExpansion: true
-      }); // force render expansion
+    if (nodesToInsert.indexOf(parentNodes[i]) !== -1) {
+      this._addToVisibleFlatList(parentNodes[i], false);
     }
+    if (!parentNodes[i].expanded) {
+      this.expandNode(parentNodes[i], {
+        renderExpansion: false,
+        renderAnimated: false
+      });
+    }
+  }
+  if (nodesToInsert.length > 0) {
+    this._rerenderViewport();
+    this.invalidateLayoutTree();
   }
 };
 
@@ -978,13 +1875,10 @@
 };
 
 scout.Tree.prototype.insertNodes = function(nodes, parentNode) {
-  var $parentNode, $predecessor;
-
   // Append continuous node blocks
   nodes.sort(function(a, b) {
     return a.childNodeIndex - b.childNodeIndex;
   });
-  this._visitNodes(nodes, this._initTreeNode.bind(this), parentNode);
 
   // Update parent with new child nodes
   if (parentNode) {
@@ -994,26 +1888,20 @@
       }.bind(this));
       this._updateChildNodeIndex(parentNode.childNodes, nodes[0].childNodeIndex);
     } else {
-      scout.arrays.pushAll(parentNode.childNodes, nodes);
+      nodes.forEach(function(entry) {
+        parentNode.childNodes.push(entry);
+      }.bind(this));
     }
-
-    if (this.rendered && parentNode.$node) {
-      $parentNode = parentNode.$node;
-      if (nodes[0].childNodeIndex === 0) {
-        $predecessor = $parentNode;
-      } else {
-        $predecessor = calcPredecessor(parentNode.childNodes[nodes[0].childNodeIndex - 1]);
-      }
-      if (parentNode.expanded) {
-        // If parent is already expanded just add the nodes at the end.
-        // Otherwise render the expansion
-        if ($parentNode.hasClass('expanded')) {
-          this._addNodes(nodes, $parentNode, $predecessor);
-          this._updateItemPath();
-        } else {
-          this._renderExpansion(parentNode, $predecessor);
-        }
-      }
+    //initialize node and add to visible list if node is visible
+    this._visitNodes(nodes, this._initTreeNode.bind(this), parentNode);
+    if (this.groupedNodes[parentNode.id]) {
+      this._updateItemPath(false, parentNode);
+    }
+    if (this.rendered) {
+      var opts = {
+        expansionChanged: true
+      };
+      this._renderExpansion(parentNode, opts);
     }
   } else {
     if (this.nodes && this.nodes.length > 0) {
@@ -1021,42 +1909,20 @@
         scout.arrays.insert(this.nodes, entry, entry.childNodeIndex);
       }.bind(this));
       this._updateChildNodeIndex(this.nodes, nodes[0].childNodeIndex);
-
-      if (nodes[0].childNodeIndex !== 0) {
-        $predecessor = calcPredecessor(this.nodes[nodes[0].childNodeIndex - 1]);
-      }
     } else {
       scout.arrays.pushAll(this.nodes, nodes);
     }
-
-    if (this.rendered) {
-      this._addNodes(nodes, undefined, $predecessor);
-      this._updateItemPath();
-    }
+    //initialize node and add to visible list if node is visible
+    this._visitNodes(nodes, this._initTreeNode.bind(this), parentNode);
   }
-
+  if (this.rendered) {
+    this.viewRangeDirty = true;
+    this.invalidateLayoutTree();
+  }
   this.trigger('nodesInserted', {
     nodes: nodes,
     parentNode: parentNode
   });
-
-  // ----- Helper functions -----
-
-  function calcPredecessor(nodeBefore) {
-    if (!nodeBefore) {
-      return undefined;
-    }
-    if (nodeBefore && (!nodeBefore.childNodes || nodeBefore.childNodes.length === 0) && nodeBefore.$node) {
-      return nodeBefore.$node;
-    }
-    var $node = calcPredecessor(nodeBefore.childNodes[nodeBefore.childNodes.length - 1]);
-    if ($node) {
-      return $node;
-    } else if (nodeBefore.$node) {
-      return nodeBefore.$node;
-    }
-    return undefined;
-  }
 };
 
 scout.Tree.prototype.updateNodes = function(nodes) {
@@ -1069,16 +1935,22 @@
     scout.defaultValues.applyTo(updatedNode, 'TreeNode');
     var propertiesChanged = this._applyUpdatedNodeProperties(oldNode, updatedNode);
     anyPropertiesChanged = anyPropertiesChanged || propertiesChanged;
-
-    if (this.rendered && propertiesChanged) {
-      this._decorateNode(oldNode);
+    if (propertiesChanged) {
+      if (this._applyFiltersForNode(oldNode)) {
+        if (!oldNode.isFilterAccepted()) {
+          this._nodesFiltered([oldNode]);
+          this._removeFromFlatList(oldNode, false);
+        } else {
+          this._addToVisibleFlatList(oldNode, false);
+        }
+      }
+      this._updateItemPath(false, oldNode.parentNode);
+      if (this.rendered) {
+        this._decorateNode(oldNode);
+      }
     }
   }
 
-  if (this.rendered && anyPropertiesChanged) {
-    this._updateItemPath();
-  }
-
   this.trigger('nodesUpdated', {
     nodes: nodes
   });
@@ -1112,7 +1984,7 @@
   if (oldNode.lazyExpandingEnabled !== updatedNode.lazyExpandingEnabled) {
     oldNode.lazyExpandingEnabled = updatedNode.lazyExpandingEnabled;
     // Also make sure expandedLazy is resetted (same code as in AbstractTreeNode.setLazyExpandingEnabled)
-    oldNode.expandedLazy = updatedNode.lazyExpandingEnabled;
+    oldNode.expandedLazy = updatedNode.lazyExpandingEnabled && this.lazyExpandingEnabled;
     propertiesChanged = true;
   }
   return propertiesChanged;
@@ -1259,6 +2131,18 @@
   return updatedNodes;
 };
 
+scout.Tree.prototype._sendNodesSelected = function(nodes, debounceSend) {
+  var eventData = {
+    nodeIds: this._nodesToIds(nodes)
+  };
+
+  // send delayed to avoid a lot of requests while selecting
+  // coalesce: only send the latest selection changed event for a field
+  this._send('nodesSelected', eventData, debounceSend ? 250 : 0, function(previous) {
+    return this.id === previous.id && this.type === previous.type;
+  });
+};
+
 scout.Tree.prototype._sendNodesChecked = function(nodes) {
   var data = {
     nodes: []
@@ -1274,14 +2158,14 @@
   this._send('nodesChecked', data);
 };
 
-scout.Tree.prototype._sendBreadCrumbEnabled = function() {
-  this._send('breadcrumbEnabled', {
-    breadcrumbEnabled: this.breadcrumbEnabled
+scout.Tree.prototype._triggerNodesSelected = function(debounce) {
+  this.trigger('nodesSelected', {
+    debounce: debounce
   });
 };
 
 scout.Tree.prototype._showContextMenu = function(event) {
-  var func = function func(event) {
+  var func = function(event) {
     event.preventDefault();
 
     var filteredMenus = this._filterMenus(this.menus, scout.MenuDestinations.CONTEXT_MENU, true),
@@ -1299,7 +2183,7 @@
       $anchor: $part,
       menuFilter: this._filterMenusHandler
     });
-    popup.open(null, event);
+    popup.open();
 
     // Set table style to focused, so that it looks as it still has the focus.
     // Must be called after open(), because opening the popup might cause another
@@ -1364,119 +2248,65 @@
   return $(event.target).is('.check-box');
 };
 
-scout.Tree.prototype._showAllNodes = function(parentNode) {
-  var updateFunc = function() {
-    this.revalidateLayoutTree();
-    this.revealSelection();
-  }.bind(this);
+scout.Tree.prototype._updateItemPath = function(selectionChanged, ultimate) {
+  var selectedNodes, node, level;
+  if (selectionChanged) {
+    // first remove and select selected
+    this.groupedNodes = {};
 
-  var completeFunc = function() {
-    // "this" will be bound to the $node that completed the animation
-    var oldStyle = this.data('oldStyle');
-    if (oldStyle) {
-      this.removeData('oldStyle');
-      this.attrOrRemove('style', oldStyle);
-    }
-  };
-
-  // Show all nodes for this parent
-  for (var i = 0; i < parentNode.childNodes.length; i++) {
-    var childNode = parentNode.childNodes[i];
-
-    // skip if already visible
-    if (childNode.$node.css('display') !== 'none') {
-      continue;
-    }
-
-    childNode.$node.removeClass('hidden');
-
-    // only animate small trees
-    if (parentNode.childNodes.length < 100) {
-      var h = childNode.$node.outerHeight(),
-        p = childNode.$node.css('padding-top');
-
-      // Backup the current value of the 'style' attribute, so we can remove the animated
-      // properties again when the animation is complete (otherwise, the values might
-      // interfere with CSS definitions, e.g. in breadcrumb mode)
-      childNode.$node.data('oldStyle', childNode.$node.attr('style'));
-
-      // make height 0
-      childNode.$node
-        .outerHeight(0)
-        .css('padding-top', '0')
-        .css('padding-bottom', '0');
-
-      // animate to original height
-      childNode.$node
-        .animateAVCSD('padding-top', p, null, null, 200)
-        .animateAVCSD('padding-bottom', p, null, null, 200)
-        .animateAVCSD('height', h, null, updateFunc, 200)
-        .promise().done(completeFunc);
-    }
-
-    // only first animated element should handle scrollbar and visibility of selection
-    updateFunc = null;
+    this._inSelectionPathList = {};
   }
 
-  // without animation
-  this.revalidateLayoutTree();
-  this.revealSelection();
-};
+  if (!ultimate) {
+    // find direct children
+    selectedNodes = this.selectedNodes;
+    if (selectedNodes.length === 0) {
+      return;
+    }
+    node = selectedNodes[0];
 
-scout.Tree.prototype._updateItemPath = function() {
-  var $selectedNodes, $node, level;
-
-  // first remove and select selected
-  this.$data.find('.tree-node').removeClass('group');
-
-  // find direct children
-  $selectedNodes = this.$selectedNodes();
-  $node = $selectedNodes.next();
-  level = parseFloat($selectedNodes.attr('data-level'));
-
-  // find grouping end (ultimate parent)
-  var $ultimate;
-  if ($selectedNodes.parent().hasClass('animation-wrapper')) {
-    //If node expansion animation is in progress, the nodes are wrapped by a div
-    $node = $selectedNodes.parent().prev();
-  } else {
-    $node = $selectedNodes.prev();
-  }
-  while ($node.length > 0) {
-    var k = parseFloat($node.attr('data-level'));
-    if (k < level) {
-      if (this._isGroupingEnd($node.data('node'))) {
-        break;
+    if (selectionChanged) {
+      this._inSelectionPathList[node.id] = true;
+      if (node.childNodes) {
+        node.childNodes.forEach(function(child) {
+          this._inSelectionPathList[child.id] = true;
+        }.bind(this));
       }
+    }
+    level = node.level;
 
-      level = k;
-      $ultimate = $node;
+    // find grouping end (ultimate parent)
+    while (node.parentNode) {
+      var parent = node.parentNode;
+      if (this._isGroupingEnd(parent) && !ultimate) {
+        ultimate = node;
+        if (!selectionChanged) {
+          break;
+        }
+      }
+      if (selectionChanged) {
+        this._inSelectionPathList[parent.id] = true;
+      }
+      node = parent;
     }
-    if ($node.parent().hasClass('animation-wrapper')) {
-      $node = $node.parent();
-    }
-    $node = $node.prev();
+    // find group with same ultimate parent
+    ultimate = ultimate || selectedNodes[0];
+    this.groupedNodes[ultimate.id] = true;
   }
+  node = ultimate;
+  if (node && node.expanded && this.groupedNodes[node.id]) {
+    addToGroup.call(this, node.childNodes);
+  }
+  //------ helper function ------//
 
-  // find group with same ultimate parent
-  $ultimate = $ultimate || $selectedNodes;
-  $node = $ultimate;
-  level = $node.attr('data-level');
-  while ($node.length > 0) {
-    $node.addClass('group');
-    if ($node.next().length === 0 && $node.parent().hasClass('animation-wrapper')) {
-      // If there is no next node but we are inside an animationWrapper, step out the wrapper
-      $node = $node.parent();
-    }
-    $node = $node.next();
-    if ($node.hasClass('animation-wrapper')) {
-      $node = $node.children().first();
-    }
-
-    var m = parseFloat($node.attr('data-level'));
-    if (m <= level) {
-      break;
-    }
+  function addToGroup(nodes) {
+    nodes.forEach(function(node) {
+      this.groupedNodes[node.id] = true;
+      this._decorateNode(node);
+      if (node.expanded && node.isFilterAccepted()) {
+        addToGroup.call(this, node.childNodes);
+      }
+    }.bind(this));
   }
 };
 
@@ -1496,49 +2326,64 @@
 /**
  * @param filter object with createKey() and accept()
  */
-scout.Tree.prototype.addFilter = function(filter) {
+scout.Tree.prototype.addFilter = function(filter, doNotFilter, notAnimated) {
   if (this._filters.indexOf(filter) < 0) {
     this._filters.push(filter);
+    if (!doNotFilter) {
+      this.filter(notAnimated);
+    }
+    return true;
   }
+  return false;
 };
 
-scout.Tree.prototype.removeFilter = function(filter) {
+scout.Tree.prototype.removeFilter = function(filter, notAnimated) {
   scout.arrays.remove(this._filters, filter);
+  this.filter(notAnimated);
 };
 
-scout.Tree.prototype.filter = function() {
-  var useAnimation = false,
+scout.Tree.prototype.filter = function(notAnimated) {
+  var useAnimation = !!!notAnimated,
     changedNodes = [],
     newHiddenNodes = [];
-
   // Filter nodes
   this._visitNodes(this.nodes, function(node) {
-    if (!node.$node) {
-      // filter may only be called for rendered nodes because the filter may want to use the actual html content
-      // if a node is collapsed, it is not rendered -> filter is called when node gets expanded
-      //TODO CGU make filter not depend on $node -> filter must not be called in decorate rows, but in init, insert, update, delete instead (as done in table)
-      return;
-    }
-
     var changed = this._applyFiltersForNode(node);
     if (changed) {
       changedNodes.push(node);
-      if (!node.filterAccepted) {
-        newHiddenNodes.push(node);
+      if (!node.isFilterAccepted()) {
+        scout.arrays.pushAll(newHiddenNodes, this._removeFromFlatList(node, useAnimation));
+      } else {
+        this._addToVisibleFlatList(node, useAnimation);
       }
+      this.viewRangeDirty = true;
     }
+    if ((node.expanded || node.expandedLazy) && node.isFilterAccepted()) {
+      return false;
+    }
+    //don't process children->optimize performance
+    return true;
   }.bind(this));
 
-  if (changedNodes.length === 0) {
-    return;
-  }
+  this._nodesFiltered(newHiddenNodes);
+};
 
-  // Show / hide rows that changed their state during filtering
-  if (this.rendered) {
-    useAnimation = changedNodes.length <= this._animationNodeLimit;
-    changedNodes.forEach(function(node) {
-      this._renderNodeFilterAccepted(node, useAnimation);
-    }, this);
+/**
+ * use filtered nodes are removed from visible nodes
+ */
+scout.Tree.prototype.filterVisibleNodes = function(animated) {
+  // Filter nodes
+  var newHiddenNodes = [];
+  for (var i = 0; i < this.visibleNodesFlat.length; i++) {
+    var node = this.visibleNodesFlat[i];
+    var changed = this._applyFiltersForNode(node);
+    if (changed) {
+      if (!node.isFilterAccepted()) {
+        i--;
+        scout.arrays.pushAll(newHiddenNodes, this._removeFromFlatList(node, animated));
+      }
+      this.viewRangeDirty = true;
+    }
   }
 
   this._nodesFiltered(newHiddenNodes);
@@ -1563,58 +2408,187 @@
  * @returns {Boolean} true if node state has changed, false if not
  */
 scout.Tree.prototype._applyFiltersForNode = function(node) {
+  var changed = node.filterDirty;
   if (this._nodeAcceptedByFilters(node)) {
     if (!node.filterAccepted) {
       node.filterAccepted = true;
-      return true;
+      changed = true;
     }
   } else {
     if (node.filterAccepted) {
       node.filterAccepted = false;
-      return true;
+      changed = true;
     }
   }
+  if (changed) {
+    node.filterDirty = false;
+    node.childNodes.forEach(function(childNode) {
+      childNode.filterDirty = true;
+    });
+    return true;
+  }
   return false;
 };
 
-scout.Tree.prototype.showNode = function($node, useAnimation) {
-  var that = this;
-  if ($node.isVisible() && !$node.is(':animated')) {
+/**
+ * Just insert node in DOM. NO check if in viewRange
+ */
+scout.Tree.prototype._insertNodeInDOM = function(node, indexHint) {
+  if (!this.rendered && !this.rendering) {
     return;
   }
+  var index = indexHint === undefined ? this.visibleNodesFlat.indexOf(node) : indexHint;
+  if (index === -1 || !(this.viewRangeRendered.from + this.viewRangeSize >= index && this.viewRangeRendered.from <= index && this.viewRangeRendered.size() > 0) || node.attached) {
+    //node is not visible
+    return;
+  }
+  if (!node.$node) {
+    this._$buildNode(node);
+  }
+  this._decorateNode(node);
 
-  if (useAnimation) {
-    $node.removeClass('hidden');
-    $node.stop().slideDown({
-      duration: 250,
-      complete: function() {
-        that.invalidateLayoutTree();
-      }
-    });
-  } else {
-    $node.showFast();
-    $node.removeClass('hidden');
-    that.invalidateLayoutTree();
+  this._insertNodeInDOMAtPlace(node, index);
+
+  node.height = node.$node.outerHeight(true);
+  if (this.isHorizontalScrollingEnabled()) {
+    var widthBackup = node.width ? node.width : 0,
+      displayBackup = node.$node.css('display');
+    node.$node.css('width', 'auto');
+    node.$node.css('display', 'inline-block');
+    var newWidth = node.$node.outerWidth();
+    if (widthBackup === this.maxNodeWidth && newWidth < this.maxNodeWidth) {
+      this.maxNodeWidth = 0;
+      this.nodeWidthDirty = true;
+    } else if (newWidth > this.maxNodeWidth) {
+      this.maxNodeWidth = newWidth;
+      this.nodeWidthDirty = true;
+    }
+    if (!this.nodeWidthDirty) {
+      node.$node.css('width', this.maxNodeWidth);
+    }
+    node.$node.css('display', displayBackup);
+    node.width = newWidth;
+  }
+  node.rendered = true;
+  node.attached = true;
+};
+
+scout.Tree.prototype._ensureParentIsInDOM = function(node, useAnimation, indexHint) {
+  var parentNode = node.parentNode;
+  if (parentNode && !parentNode.attached && parentNode === this.visibleNodesFlat[indexHint] && indexHint >= this.viewRangeRendered.from && indexHint < this.viewRangeRendered.to) {
+    this.showNode(parentNode, useAnimation, indexHint);
   }
 };
 
-scout.Tree.prototype.hideNode = function($node, useAnimation) {
+scout.Tree.prototype._insertNodeInDOMAtPlace = function(node, index) {
+  var $node = node.$node,
+    added = false;
+  if (index === 0) {
+    if (this.$fillBefore) {
+      added = true;
+      $node.insertAfter(this.$fillBefore);
+    } else {
+      added = true;
+      this.$data.prepend($node);
+    }
+  } else {
+    //append after index
+    var nodeBefore = this.visibleNodesFlat[index - 1];
+    if (nodeBefore.attached) {
+      $node.insertAfter(nodeBefore.$node);
+      added = true;
+    } else if (index + 1 < this.visibleNodesFlat.length) {
+      var nodeAfter = this.visibleNodesFlat[index + 1];
+      if (nodeAfter.attached) {
+        added = true;
+        $node.insertBefore(nodeAfter.$node);
+      }
+    }
+
+    if (!added && this.$fillBefore) {
+      $node.insertAfter(this.$fillBefore);
+    } else if (!added) {
+      this.$data.prepend($node);
+    }
+  }
+};
+
+scout.Tree.prototype.showNode = function(node, useAnimation, indexHint) {
+  if (node.attached || !this.rendered) {
+    return;
+  }
+  this._ensureParentIsInDOM(node, useAnimation, indexHint - 1);
+  this._insertNodeInDOM(node, indexHint);
+  if (!node.rendered) {
+    return;
+  }
+  var $node = node.$node;
+  if ($node.is('.showing')) {
+    return;
+  }
+  $node.showFast();
+  $node.addClass('showing');
+  $node.removeClass('hiding');
   var that = this;
-  if (!$node.isVisible() && !$node.is(':animated')) {
+  if (useAnimation) {
+    $node.data('oldStyle', $node.attr('style'));
+    $node.setVisible(false);
+    $node.stop().slideDown({
+      duration: 250,
+      start: that.startAnimationFunc,
+      complete: function() {
+        that.runningAnimationsFinishFunc();
+        var oldStyle = $node.data('oldStyle');
+        if (oldStyle) {
+          $node.removeData('oldStyle');
+          $node.attrOrRemove('style', oldStyle);
+        }
+      }
+    });
+  }
+
+};
+
+scout.Tree.prototype.hideNode = function(node, useAnimation, suppressDetachHandling) {
+  if (!node.attached) {
+    return;
+  }
+  this.viewRangeDirty = true;
+  var that = this,
+    $node = node.$node;
+  if (!$node) {
+    //node is not rendered
     return;
   }
 
+  if ($node.is('.hiding')) {
+    return;
+  }
+
+  $node.addClass('hiding');
+  $node.removeClass('showing');
+
   if (useAnimation) {
+    this._renderViewportBlocked = true;
+    $node.data('oldStyle', $node.attr('style'));
     $node.stop().slideUp({
       duration: 250,
+      start: that.startAnimationFunc,
       complete: function() {
-        $node.addClass('hidden');
-        that.invalidateLayoutTree();
+        that.runningAnimationsFinishFunc();
+        $node.detach();
+        node.attached = false;
+        var oldStyle = $node.data('oldStyle');
+        if (oldStyle) {
+          $node.removeData('oldStyle');
+          $node.attrOrRemove('style', oldStyle);
+        }
       }
     });
-  } else {
+  } else if (!suppressDetachHandling) {
     $node.hideFast();
-    $node.addClass('hidden');
+    $node.detach();
+    node.attached = false;
     that.invalidateLayoutTree();
   }
 };
@@ -1640,7 +2614,7 @@
   var node = $node.data('node');
   var expanded = !$node.hasClass('expanded');
 
-  if (this.breadcrumbEnabled) {
+  if (this.isBreadcrumbStyleActive()) {
     return;
   }
 
@@ -1717,12 +2691,6 @@
   this.revealSelection();
 };
 
-scout.Tree.prototype.onResize = function() {
-  if (this.rendered) {
-    this.htmlComp.revalidateLayoutTree();
-  }
-};
-
 scout.Tree.prototype._onNodesInserted = function(nodes, parentNodeId) {
   var parentNode;
   if (parentNodeId !== null && parentNodeId !== undefined) {
@@ -1798,6 +2766,14 @@
   node.backgroundColor = cell.backgroundColor;
   node.font = cell.font;
 
+  if (this._applyFiltersForNode(node)) {
+    if (node.isFilterAccepted()) {
+      this._addToVisibleFlatList(node, false);
+    } else {
+      this._removeFromFlatList(node, false);
+    }
+  }
+
   if (this.rendered) {
     this._decorateNode(node);
   }
@@ -1842,17 +2818,14 @@
     newPositionsMap[childNodeIds[i]] = i;
   }
   parentNode.childNodes.sort(compare.bind(this));
+  this._removeChildrenFromFlatList(parentNode, false);
+  this._addChildrenToFlatList(parentNode, null, false);
 
   // Render sorted nodes
   if (this.rendered && $lastChildNode) {
     // Find the last affected node DIV
     $lastChildNode = scout.Tree.collectSubtree($lastChildNode).last();
 
-    if (this._$animationWrapper) {
-      // Stop the animation wrapper
-      this._$animationWrapper.stop(false, true);
-    }
-
     // Insert a marker DIV
     var $marker = $lastChildNode.afterDiv();
     for (i = 0; i < parentNode.childNodes.length; i++) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarMenuOrder.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeBreadcrumbFilter.js
similarity index 67%
rename from org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarMenuOrder.js
rename to org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeBreadcrumbFilter.js
index 6e83618..8b48962 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/calendar/CalendarMenuOrder.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeBreadcrumbFilter.js
@@ -8,8 +8,13 @@
  * Contributors:
  *     BSI Business Systems Integration AG - initial API and implementation
  ******************************************************************************/
-scout.CalendarMenuItemsOrder = {
-  order: function(items) {
+scout.TreeBreadcrumbFilter = function(tree) {
+  this.tree = tree;
+};
 
+scout.TreeBreadcrumbFilter.prototype.accept = function(node) {
+  if(this.tree.selectedNodes.length === 0 ){
+    return node.parentNode === undefined;
   }
+  return this.tree.isNodeInBreadcrumbVisible(node);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
index d1051c8..6d15836 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
@@ -15,6 +15,18 @@
 scout.inherits(scout.TreeLayout, scout.AbstractLayout);
 
 scout.TreeLayout.prototype.layout = function($container) {
+  var htmlContainer = this.tree.htmlComp;
+
+  //FIXME CGU/AWE remove this check as soon as HtmlComp.validateLayout checks for invisible components
+  if (!htmlContainer.isAttachedAndVisible() || !htmlContainer.$comp.isEveryParentVisible()) {
+    return;
+  }
+
+  this._layout($container);
+  scout.scrollbars.update(this.tree.$data);
+};
+
+scout.TreeLayout.prototype._layout = function($container) {
   var menuBarSize, containerSize, heightOffset,
     menuBar = this.tree.menuBar,
     htmlMenuBar = menuBar.htmlComp,
@@ -23,6 +35,10 @@
   containerSize = htmlContainer.getAvailableSize()
     .subtract(htmlContainer.getInsets());
 
+  if (this.tree.autoToggleBreadcrumbStyle) {
+    this.tree.setBreadcrumbStyleActive(containerSize.width <= this.tree.breadcrumbTogglingThreshold);
+  }
+
   heightOffset = 0;
   if (menuBar.$container.isVisible()) {
     menuBarSize = scout.MenuBarLayout.size(htmlMenuBar, containerSize);
@@ -31,6 +47,23 @@
   }
 
   this._setDataHeight(heightOffset);
+
+  // Check if width has changed
+  if (htmlContainer.size && htmlContainer.size.width !== htmlContainer.getSize().width) {
+    if (this.tree.isHorizontalScrollingEnabled()) {
+      // Width is only relevant if horizontal scrolling is enabled -> mark as dirty
+      this.tree.nodeWidthDirty = true;
+      this.tree.maxNodeWidth = 0;
+    } else {
+      // Nodes may contain wrapped text (with breadcrumb style-or if nodes contain html) -> update heights
+      this.tree.updateNodeHeights();
+      this.tree._renderFiller();
+    }
+  }
+
+  this.tree.setViewRangeSize(this.tree.calculateViewRangeSize());
+  // Always render viewport (not only when viewRangeSize changes), because view range depends on scroll position and data height
+  this.tree._renderViewport();
 };
 
 scout.TreeLayout.prototype._setDataHeight = function(heightOffset) {
@@ -39,5 +72,12 @@
   heightOffset += $data.cssMarginTop() + $data.cssMarginBottom();
 
   $data.css('height', (heightOffset === 0 ? '100%' : 'calc(100% - ' + heightOffset + 'px)'));
-  scout.scrollbars.update($data);
+};
+
+scout.TreeLayout.prototype.preferredLayoutSize = function($container) {
+  // Make sure viewport is up to date before calculating pref size.
+  // This is necessary because the tree does not render the view port on any change (like insert or delete nodes). Instead it just invalidates the layout.
+  this.tree._renderViewport();
+
+  return scout.graphics.prefSize($container);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js
index 9371ad3..1b7dc08 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/AbstractTreeNavigationKeyStroke.js
@@ -28,20 +28,21 @@
     return false;
   }
 
-  var $currentNode = this.field.$selectedNodes().eq(0);
-  event._$treeCurrentNode = $currentNode;
-  event._treeCurrentNode = $currentNode.data('node');
+  if (this.field.selectedNodes.length > 0) {
+    event._treeCurrentNode = this.field.selectedNodes[0];
+    event._$treeCurrentNode = event._treeCurrentNode.$node;
+  }
   return true;
 };
 
 scout.AbstractTreeNavigationKeyStroke.prototype.handle = function(event) {
-  var newNodeSelection = this._handleInternal(event._$treeCurrentNode, event._treeCurrentNode);
+  var newNodeSelection = this._handleInternal(event._treeCurrentNode);
   if (newNodeSelection) {
     this.field.selectNodes(newNodeSelection);
     this.field.scrollTo(newNodeSelection);
   }
 };
 
-scout.AbstractTreeNavigationKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
+scout.AbstractTreeNavigationKeyStroke.prototype._handleInternal = function(currentNode) {
   throw new Error('method must be overwritten by subclass');
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseAllKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseAllKeyStroke.js
index 8423fc3..34791cb 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseAllKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseAllKeyStroke.js
@@ -18,7 +18,10 @@
 };
 scout.inherits(scout.TreeCollapseAllKeyStroke, scout.AbstractTreeNavigationKeyStroke);
 
-scout.TreeCollapseAllKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
+scout.TreeCollapseAllKeyStroke.prototype._handleInternal = function(currentNode) {
   this.field.collapseAll();
-  return this.field.$nodes().first().data('node');
+  if(this.field.visibleNodesFlat.length>0){
+    this.field.selectNodes(this.field.visibleNodesFlat[0]);
+  }
+  return this.field.visibleNodesFlat[0];
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js
index 64fed84..fcea248 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeCollapseOrDrillUpKeyStroke.js
@@ -23,7 +23,7 @@
   return accepted && event._treeCurrentNode;
 };
 
-scout.TreeCollapseOrDrillUpKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
+scout.TreeCollapseOrDrillUpKeyStroke.prototype._handleInternal = function(currentNode) {
   if (currentNode.expanded) {
     this.field.collapseNode(currentNode);
     return null;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js
index 9d23074..6203890 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js
@@ -23,9 +23,11 @@
   return accepted && event._treeCurrentNode;
 };
 
-scout.TreeExpandOrDrillDownKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
+scout.TreeExpandOrDrillDownKeyStroke.prototype._handleInternal = function(currentNode) {
   if (!currentNode.expanded && !currentNode.leaf) {
-    this.field.expandNode(currentNode);
+    this.field.expandNode(currentNode, {
+      lazy: false // always show all nodes on node double click
+    });
     return null;
   } else if (currentNode.childNodes.length > 0) {
     return currentNode.childNodes[0];
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationDownKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationDownKeyStroke.js
index d2d7ec7..ef43ad0 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationDownKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationDownKeyStroke.js
@@ -14,7 +14,7 @@
   this.renderingHints.text = '↓';
   this.renderingHints.$drawingArea = function($drawingArea, event) {
     var $currentNode = event._$treeCurrentNode;
-    if ($currentNode.length === 0) {
+    if (!$currentNode) {
       return this.field.$nodes().first();
     }
     return $currentNode.nextAll('.tree-node:not(.hidden):first');
@@ -22,9 +22,13 @@
 };
 scout.inherits(scout.TreeNavigationDownKeyStroke, scout.AbstractTreeNavigationKeyStroke);
 
-scout.TreeNavigationDownKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if ($currentNode.length === 0) {
-    return this.field.$nodes().first().data('node');
+scout.TreeNavigationDownKeyStroke.prototype._handleInternal = function(currentNode) {
+  var nodes = this.field.visibleNodesFlat;
+  if (nodes.length === 0) {
+    return null;
   }
-  return $currentNode.nextAll('.tree-node:not(.hidden):first').data('node');
+  if (!currentNode) {
+    return nodes[0];
+  }
+  return nodes[nodes.indexOf(currentNode) + 1];
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationEndKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationEndKeyStroke.js
new file mode 100644
index 0000000..92068a7
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationEndKeyStroke.js
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     BSI Business Systems Integration AG - initial API and implementation
+ ******************************************************************************/
+scout.TreeNavigationEndKeyStroke = function(tree, modifierBitMask) {
+  scout.TreeNavigationEndKeyStroke.parent.call(this, tree, modifierBitMask);
+  this.which = [scout.keys.END];
+  this.renderingHints.$drawingArea = function($drawingArea, event) {
+    var visibleNodesCount = this.field.visibleNodesFlat.length;
+    if(visibleNodesCount>0 && this.field.visibleNodesFlat[visibleNodesCount-1].rendered ){
+      return this.field.visibleNodesFlat[visibleNodesCount-1].$node;
+    }
+    return null;
+  }.bind(this);
+};
+scout.inherits(scout.TreeNavigationEndKeyStroke, scout.AbstractTreeNavigationKeyStroke);
+
+scout.TreeNavigationEndKeyStroke.prototype._handleInternal = function(currentNode) {
+  var nodes = this.field.visibleNodesFlat;
+  if (nodes.length === 0) {
+    return null;
+  }
+    return nodes[nodes.length-1];
+};
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationUpKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationUpKeyStroke.js
index b32b467..e67e76b 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationUpKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeNavigationUpKeyStroke.js
@@ -14,7 +14,7 @@
   this.renderingHints.text = '↑';
   this.renderingHints.$drawingArea = function($drawingArea, event) {
     var $currentNode = event._$treeCurrentNode;
-    if ($currentNode.length === 0) {
+    if (!$currentNode) {
       return this.field.$nodes().last();
     }
     return $currentNode.prevAll('.tree-node:not(.hidden):first');
@@ -22,9 +22,13 @@
 };
 scout.inherits(scout.TreeNavigationUpKeyStroke, scout.AbstractTreeNavigationKeyStroke);
 
-scout.TreeNavigationUpKeyStroke.prototype._handleInternal = function($currentNode, currentNode) {
-  if ($currentNode.length === 0) {
-    return this.field.$nodes().last().data('node');
+scout.TreeNavigationUpKeyStroke.prototype._handleInternal = function(currentNode) {
+  var nodes = this.field.visibleNodesFlat;
+  if (nodes.length === 0) {
+    return null;
   }
-  return $currentNode.prevAll('.tree-node:not(.hidden):first').data('node');
+  if (!currentNode) {
+    return nodes[nodes.length - 1];
+  }
+  return nodes[nodes.indexOf(currentNode) - 1];
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeSpaceKeyStroke.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeSpaceKeyStroke.js
index e12df2c..70a8b28 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeSpaceKeyStroke.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/keystrokes/TreeSpaceKeyStroke.js
@@ -18,18 +18,13 @@
 
 scout.TreeSpaceKeyStroke.prototype._accept = function(event) {
   var accepted = scout.TreeSpaceKeyStroke.parent.prototype._accept.call(this, event);
-  return accepted && this.field.checkable;
+  return accepted && this.field.checkable && this.field.selectedNodes.length > 0;
 };
 
 scout.TreeSpaceKeyStroke.prototype.handle = function(event) {
-  var $currentNode = this.field.$selectedNodes().eq(0);
-  if ($currentNode.length === 0) {
-    return;
-  }
-
-  var check = !$($currentNode[0]).data('node').checked;
-  for (var j = 0; j < $currentNode.length; j++) {
-    var node = $($currentNode[j]).data('node');
-    this.field.checkNode(node, check);
-  }
+  var selection = this.field.selectedNodes;
+  var checked = selection[0].checked;
+  selection.forEach(function(node) {
+    this.field.checkNode(node, !checked);
+  }, this);
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Device.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Device.js
index b2f4903..4b969cc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Device.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Device.js
@@ -36,6 +36,7 @@
 
   if (userAgent) {
     this._parseSystem(userAgent);
+    this._parseSystemVersion(userAgent);
     this._parseBrowser(userAgent);
     this._parseBrowserVersion(userAgent);
   }
@@ -74,7 +75,7 @@
  * Called during bootstrap by index.html before the session startup.<p>
  * Precalculates the value of some attributes to store them
  * in a static way (and prevent many repeating function calls within loops).<p>
- * Also loads device specific scripts (fast click for ios devices)
+ * Also loads device specific scripts (e.g. fast click for ios devices)
  */
 scout.Device.prototype.bootstrap = function() {
   var deferreds = [];
@@ -85,31 +86,71 @@
   this.scrollbarWidth = this._detectScrollbarWidth();
   this.type = this._detectType(this.userAgent);
 
-  if (this.isIos()) {
+  if (this._needsFastClick()) {
     // We use Fastclick to prevent the 300ms delay when touching an element.
-    // With Chrome 32 the issue is solved, so no need to load the script for other devices than iOS
-    deferreds.push(this._loadScriptDeferred('res/fastclickmod-1.0.1.min.js', function() {
-      FastClick.attach(document.body);
-      $.log.info('FastClick script loaded and attached');
-    }));
+    deferreds.push(this._loadFastClickDeferred());
+  } else if (this.isIos()){
+    this._installActiveHandler();
   }
 
   if (this.hasOnScreenKeyboard()) {
     // Auto focusing of elements is bad with on screen keyboards -> deactivate to prevent unwanted popping up of the keyboard
     this.focusManagerActive = false;
-    deferreds.push(this._loadScriptDeferred('res/jquery.mobile.custom-1.4.5.min.js', function() {
-      $.log.info('JQuery Mobile script loaded');
-    }));
+    deferreds.push(this._loadJQueryMobileDeferred());
   }
   return deferreds;
 };
 
+/**
+ * The 300ms delay exists because the browser does not know whether the user wants to just tab or wants to zoom using double tab.
+ * Therefore most browsers add the delay only if zoom is enabled. This works for firefox, chrome (>=32) and safari/ios (>=9.3).
+ * It does not work if safari is opened in standalone/homescreen mode. For IE (and safari since ios 9.3) it can be disabled using a css property called touch-action.
+ *
+ * By default, zooming is disabled and home screen mode is enabled, see meta tags viewport and apple-mobile-web-app-capable in head.html
+ */
+scout.Device.prototype._needsFastClick = function() {
+  if (!this.isIos()) {
+    // Currently only IOS still has the issue -> don't load the script for other systems and browsers
+    return false;
+  }
+
+  if (this.systemVersion >= 9.3 && !this.isStandalone()) {
+    // With Safari >= 9.3 the delay is gone if zooming is disabled, but not for the home screen / web app mode.
+    return false;
+  }
+
+  // -> load only for older IOS devices or if standalone mode is enabled
+  return true;
+};
+
+scout.Device.prototype._loadFastClickDeferred = function() {
+  return this._loadScriptDeferred('res/fastclick-1.0.6.min.js', function() {
+    FastClick.attach(document.body);
+    $.log.info('FastClick script loaded and attached');
+  });
+};
+
+scout.Device.prototype._loadJQueryMobileDeferred = function() {
+  return this._loadScriptDeferred('res/jquery.mobile.custom-1.4.5.min.js', function() {
+    $.log.info('JQuery Mobile script loaded');
+  });
+};
+
 scout.Device.prototype._loadScriptDeferred = function(scriptUrl, doneFunc) {
   return $
     .getCachedScript(scriptUrl)
     .done(doneFunc);
 };
 
+/**
+ * IOs does only trigger :active when touching an element if a touchstart listener is attached
+ * Unfortunately, the :active is also triggered when scrolling, there is no delay.
+ * To fix this we would have to work with a custom active class which will be toggled on touchstart/end
+ */
+scout.Device.prototype._installActiveHandler = function() {
+  document.addEventListener('touchstart', function() {}, false);
+};
+
 scout.Device.prototype.hasOnScreenKeyboard = function() {
   return this.supportsFeature('_onScreenKeyboard', function() {
     return this.isIos() || this.isAndroid() || this.isWindowsTablet();
@@ -142,6 +183,13 @@
 };
 
 /**
+ * @returns true if navigator.standalone is true which is the case for iOS home screen mode
+ */
+scout.Device.prototype.isStandalone = function() {
+  return !!window.navigator.standalone;
+};
+
+/**
  * This method returns false for very old browsers. Basically we check for the first version
  * that supports ECMAScript 5. This methods excludes all browsers that are known to be
  * unsupported, all others (e.g. unknown engines) are allowed by default.
@@ -159,14 +207,6 @@
   return true;
 };
 
-scout.Device.prototype._parseSystem = function(userAgent) {
-  if (userAgent.indexOf('iPhone') > -1 || userAgent.indexOf('iPad') > -1) {
-    this.system = scout.Device.System.IOS;
-  } else if (userAgent.indexOf('Android') > -1) {
-    this.system = scout.Device.System.ANDROID;
-  }
-};
-
 /**
  * Can not detect type until DOM is ready because we must create a DIV to measure the scrollbars.
  */
@@ -189,6 +229,30 @@
   return scout.Device.Type.DESKTOP;
 };
 
+scout.Device.prototype._parseSystem = function(userAgent) {
+  if (userAgent.indexOf('iPhone') > -1 || userAgent.indexOf('iPad') > -1) {
+    this.system = scout.Device.System.IOS;
+  } else if (userAgent.indexOf('Android') > -1) {
+    this.system = scout.Device.System.ANDROID;
+  }
+};
+
+/**
+ * Currently only supports IOS
+ */
+scout.Device.prototype._parseSystemVersion = function(userAgent) {
+  var versionRegex,
+    System = scout.Device.System;
+  if (this.system === System.IOS) {
+    versionRegex = / OS ([0-9]+\.?[0-9]*)/;
+    // replace all _ with .
+    userAgent = userAgent.replace(/_/g, '.');
+  }
+  if (versionRegex) {
+    this.systemVersion = this._parseVersion(userAgent, versionRegex);
+  }
+};
+
 scout.Device.prototype._parseBrowser = function(userAgent) {
   if (userAgent.indexOf('Firefox') > -1) {
     this.browser = scout.Device.Browser.FIREFOX;
@@ -205,6 +269,45 @@
   }
 };
 
+/**
+ * Version regex only matches the first number pair
+ * but not the revision-version. Example:
+ * - 21     match: 21
+ * - 21.1   match: 21.1
+ * - 21.1.3 match: 21.1
+ */
+scout.Device.prototype._parseBrowserVersion = function(userAgent) {
+  var versionRegex, browsers = scout.Device.Browser;
+  if (this.browser === browsers.INTERNET_EXPLORER) {
+    // with internet explorer 11 user agent string does not contain the 'MSIE' string anymore
+    // additionally in new version the version-number after Trident/ is not the browser-version
+    // but the engine-version.
+    if (userAgent.indexOf('MSIE') > -1) {
+      versionRegex = /MSIE ([0-9]+\.?[0-9]*)/;
+    } else {
+      versionRegex = /rv:([0-9]+\.?[0-9]*)/;
+    }
+  } else if (this.browser === browsers.EDGE) {
+    versionRegex = /Edge\/([0-9]+\.?[0-9]*)/;
+  } else if (this.browser === browsers.SAFARI) {
+    versionRegex = /Version\/([0-9]+\.?[0-9]*)/;
+  } else if (this.browser === browsers.FIREFOX) {
+    versionRegex = /Firefox\/([0-9]+\.?[0-9]*)/;
+  } else if (this.browser === browsers.CHROME) {
+    versionRegex = /Chrome\/([0-9]+\.?[0-9]*)/;
+  }
+  if (versionRegex) {
+    this.browserVersion = this._parseVersion(userAgent, versionRegex);
+  }
+};
+
+scout.Device.prototype._parseVersion = function(userAgent, versionRegex) {
+  var matches = versionRegex.exec(userAgent);
+  if (Array.isArray(matches) && matches.length === 2) {
+    return parseFloat(matches[1]);
+  }
+};
+
 scout.Device.prototype.supportsFeature = function(property, checkFunc) {
   if (this.features[property] === undefined) {
     this.features[property] = checkFunc(property);
@@ -362,42 +465,6 @@
   }.bind(this));
 };
 
-/**
- * Currently the browserVersion is only set for IE. Because the only version-check we do,
- * is whether or not we use an old IE version. Version regex only matches the first number pair
- * but not the revision-version. Example:
- * - 21     match: 21
- * - 21.1   match: 21.1
- * - 21.1.3 match: 21.1
- */
-scout.Device.prototype._parseBrowserVersion = function(userAgent) {
-  var versionRegex, browsers = scout.Device.Browser;
-  if (this.browser === browsers.INTERNET_EXPLORER) {
-    // with internet explorer 11 user agent string does not contain the 'MSIE' string anymore
-    // additionally in new version the version-number after Trident/ is not the browser-version
-    // but the engine-version.
-    if (userAgent.indexOf('MSIE') > -1) {
-      versionRegex = /MSIE ([0-9]+\.?[0-9]*)/;
-    } else {
-      versionRegex = /rv:([0-9]+\.?[0-9]*)/;
-    }
-  } else if (this.browser === browsers.EDGE) {
-    versionRegex = /Edge\/([0-9]+\.?[0-9]*)/;
-  } else if (this.browser === browsers.SAFARI) {
-    versionRegex = /Version\/([0-9]+\.?[0-9]*)/;
-  } else if (this.browser === browsers.FIREFOX) {
-    versionRegex = /Firefox\/([0-9]+\.?[0-9]*)/;
-  } else if (this.browser === browsers.CHROME) {
-    versionRegex = /Chrome\/([0-9]+\.?[0-9]*)/;
-  }
-  if (versionRegex) {
-    var matches = versionRegex.exec(userAgent);
-    if (Array.isArray(matches) && matches.length === 2) {
-      this.browserVersion = parseFloat(matches[1]);
-    }
-  }
-};
-
 scout.Device.prototype._detectScrollbarWidth = function(userAgent) {
   var $measure = $('body')
     .appendDiv()
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/EventSupport.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/EventSupport.js
index a2f9a49..c438086 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/EventSupport.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/EventSupport.js
@@ -59,9 +59,8 @@
     return;
   }
 
-  var listeners = this._eventListeners.slice();
-  for (var i = 0; i < listeners.length; i++) {
-    var listener = listeners[i];
+  for (var i = this._eventListeners.length - 1; i >= 0; i--) {
+    var listener = this._eventListeners[i];
     var funcMatches = (func === listener.func || func === listener.origFunc);
     var typeMatches = (type === listener.type);
     var remove = false;
@@ -74,7 +73,7 @@
     }
 
     if (remove) {
-      scout.arrays.remove(this._eventListeners, listener);
+      this._eventListeners.splice(i, 1);
     }
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Range.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Range.js
index 89d5335..35d40de 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Range.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/Range.js
@@ -53,6 +53,36 @@
   return [new scout.Range(this.from, this.to)];
 };
 
+
+scout.Range.prototype.shrink = function(other) {
+  // other is empty
+  if (other.size() === 0) {
+    return new scout.Range(this.from, this.to);
+  }
+  // other is greater
+  if (this.from >= other.from && this.to <= other.to) {
+    return new scout.Range(0, 0);
+  }
+  // other is contained completely
+  if (other.from >= this.from && other.to <= this.to) {
+    return new scout.Range(this.from, other.to);
+  }
+  // other overlaps on the bottom
+  if (other.from >= this.from && other.from < this.to) {
+    return new scout.Range(this.from, other.from);
+  }
+  // other overlaps on the top
+  if (this.from > other.from && this.from < other.to) {
+    return new scout.Range(other.to, this.to);
+  }
+  if(other.to<this.from){
+    return new scout.Range(this.from-other.size()-1, this.to-other.size()-1);
+  }
+  // other is outside
+  return new scout.Range(this.from, this.to);
+};
+
+
 scout.Range.prototype.union = function(other) {
   if (this.to < other.from || other.to < this.from) {
     var range1 = new scout.Range(this.from, this.to);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/arrays.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/arrays.js
index 87dc7bc..f855050 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/arrays.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/arrays.js
@@ -12,6 +12,7 @@
 
   /**
    * Ensures the given parameter is an array
+   * @memberOf scout.arrays
    */
   ensure: function(array) {
     if (array === undefined || array === null) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/dates.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/dates.js
index c74349f..185eaae 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/dates.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/dates.js
@@ -455,7 +455,7 @@
       return false;
     }
     var date = new Date(0);
-    date.setYear(year);
+    date.setFullYear(year);
     date.setMonth(1);
     date.setDate(29);
     return (date.getDate() === 29);
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/filters.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/filters.js
index 1bfa261..db8c839 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/filters.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/filters.js
@@ -43,7 +43,7 @@
    * @param DOM or jQuery container.
    */
   outsideFilter: function(container) {
-    container = container instanceof jQuery ? container[0] : container;
+    container = container instanceof $ ? container[0] : container;
     return function() {
       return this !== container && !$.contains(container, this);
     };
@@ -55,7 +55,7 @@
    * @param DOM or jQuery element.
    */
   notSameFilter: function(element) {
-    element = element instanceof jQuery ? element[0] : element;
+    element = element instanceof $ ? element[0] : element;
     return function() {
       return this !== element;
     };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/numbers.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/numbers.js
index 4535246..fa6ed16 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/numbers.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/numbers.js
@@ -79,8 +79,7 @@
         result += letters[Math.floor(Math.random() * letters.length)];
       }
     }
-    result += '/' + (this._correlationCounter++);
-    return result;
+    return result + '/' + (this._correlationCounter++);
   },
 
   /**
@@ -144,8 +143,7 @@
         }
     }
 
-    number = this.shiftDecimalPoint(number, -decimalPlaces);
-    return number;
+    return this.shiftDecimalPoint(number, -decimalPlaces);
   },
 
   /**
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/objects.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/objects.js
index c57e2f9..5399ffd 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/objects.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/objects.js
@@ -33,6 +33,38 @@
     return count;
   },
 
+  /**
+   * returns
+   *  - true if the obj has at least one of the given properties.
+   *  - false if the obj has none of the given properties.
+   *
+   * @param obj
+   * @param properties a single property or an array of properties
+   * @returns {Boolean}
+   */
+  someOwnProperties : function(obj, properties) {
+    var propArr = scout.arrays.ensure(properties);
+    return propArr.some(function (prop){
+      return obj.hasOwnProperty(prop);
+    });
+  },
+
+  /**
+   * returns
+   *  - true if the obj or its prototypes have at least one of the given properties.
+   *  - false if the obj or its prototypes have none of the given properties.
+   *
+   * @param obj
+   * @param properties a single property or an array of properties
+   * @returns {Boolean}
+   */
+  someProperties : function(obj, properties) {
+    var propArr = scout.arrays.ensure(properties);
+    return propArr.some(function (prop){
+      return prop in obj;
+    });
+  },
+
   valueCopy: function(obj) {
     // Nothing to be done for immutable things
     if (obj === undefined || obj === null || typeof obj !== 'object') {
@@ -65,6 +97,16 @@
   },
 
   /**
+   * Returns the given property if the object is truthy.
+   */
+  optProperty: function(obj, property) {
+    if (obj) {
+      return obj[property];
+    }
+    return null;
+  },
+
+  /**
    * Returns true if:
    * - obj is not undefined or null
    * - obj not isNaN
@@ -110,8 +152,7 @@
     var whitelist = [
       'ModelAdapter.init',
       'ModelAdapter._init',
-      'Calendar.init',
-      'MobileTable.init'
+      'Calendar.init'
     ];
     var result1 = [
       'Legend:',
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/polyfills.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/polyfills.js
index 6ef1308..e765658 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/polyfills.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/polyfills.js
@@ -73,7 +73,7 @@
       }
       // Make sure no text encoding stuff is done by xhr
       ajaxOpts.xhr = function() {
-        var xhr = jQuery.ajaxSettings.xhr();
+        var xhr = $.ajaxSettings.xhr();
         xhr.send = xhr.sendAsBinary || xhr.send; // sendAsBinary only exists in older browsers
         return xhr;
       };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/strings.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/strings.js
index 1c237bb..ca86740 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/strings.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/strings.js
@@ -13,6 +13,7 @@
   /**
    * @param text
    * @param encodeHtml defaults to true
+   * @memberOf scout.strings
    */
   nl2br: function(text, encodeHtml) {
     if (!text) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/styles.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/styles.js
index 9762501..048416d 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/styles.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/util/styles.js
@@ -11,22 +11,44 @@
 scout.styles = {
 
   /**
+   * @memberOf scout.styles
+   */
+  styleMap: {},
+
+  /**
    * Generates an invisible div and appends it to the body, only once. The same div will be reused on subsequent calls.
    * Adds the given css class to that element and returns a style object containing the values for every given property.
    * The style is cached. Subsequent calls with the same css class will return the same style object.
    */
   get: function(cssClass, properties) {
-    var key = cssClass;
-    if (!scout.styles.styleMap) {
-      scout.styles.styleMap = {};
+    var style = scout.styles.styleMap[cssClass];
+    // ensure array
+    properties = scout.arrays.ensure(properties);
+    properties = properties.map(function(prop) {
+      return {
+        name: prop,
+        // replace property names like 'max-width' in 'maxWidth'
+        nameCamelCase: prop.replace(/\-(.)/g,
+          function(match, p1) {
+            return p1.toUpperCase();
+          })
+      };
+    });
+
+    // ensure style
+    if (!style) {
+      style = {};
+      scout.styles.put(cssClass, style);
     }
 
-    var style = scout.styles.styleMap[key];
-    if (style) {
+    var notResolvedProperties = properties.filter(function(prop) {
+      return !(prop.nameCamelCase in style);
+    });
+    if (notResolvedProperties.length === 0) {
       return style;
     }
-    style = {};
 
+    // resolve missing properties
     var elem = scout.styles.element;
     if (!elem) {
       elem = window.document.createElement('div');
@@ -34,19 +56,20 @@
       window.document.body.appendChild(elem);
       scout.styles.element = elem;
     }
-
     elem.className = cssClass;
     var computedStyle = window.getComputedStyle(elem);
-
-    properties = scout.arrays.ensure(properties);
-    properties.forEach(function(property) {
-      style[property] = computedStyle[property];
+    notResolvedProperties.forEach(function(property) {
+      style[property.nameCamelCase] = computedStyle[property.name];
     });
+    elem.className = '';
 
-    scout.styles.styleMap[key] = style;
     return style;
   },
 
+  put: function(cssClass, style) {
+    this.styleMap[cssClass] = style;
+  },
+
   /**
    * Creates an rgb object based on the given rgb string with the format rgb(0, 0, 0).
    */
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
index 716b73b..1c57abc 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
@@ -12,19 +12,32 @@
   this.session;
   this.children = [];
   this.initialized = false;
+
+  /**
+   * The 'rendering' flag is set the true while the _inital_ rendering is performed.
+   * It is used to to something different in a _render* method when the method is
+   * called for the first time.
+   */
+  this.rendering = false;
+
+  /**
+   * The 'rendered' flag is set the true when initial rendering of the widget is completed.
+   */
   this.rendered = false;
   this.attached = false;
   this.destroyed = false;
   this.$container;
+  // If set to true, remove won't remove the element immediately but after the animation has been finished
+  // This expects a css animation which may be triggered by the class 'removed'
+  // If browser does not support css animation, remove will be executed immediately
+  this.animateRemoval;
 };
 
 scout.Widget.prototype.init = function(options) {
   this._init(options);
   this._initKeyStrokeContext(this.keyStrokeContext);
   this.initialized = true;
-  if (this.events) {
-    this.trigger('initialized');
-  }
+  this.trigger('initialized');
 };
 
 /**
@@ -43,6 +56,7 @@
   if (!this.session) {
     throw new Error('Session expected: ' + this);
   }
+  this.animateRemoval = scout.nvl(options.animateRemoval, false);
 };
 
 scout.Widget.prototype._initKeyStrokeContext = function(keyStrokeContext) {
@@ -60,12 +74,14 @@
   if (this.destroyed) {
     throw new Error('Widget is destroyed: ' + this);
   }
+  this.rendering = true;
   this._renderInternal($parent);
   this._link();
   this.session.keyStrokeManager.installKeyStrokeContext(this.keyStrokeContext);
   if (this.parent) {
     this.parent.addChild(this);
   }
+  this.rendering = false;
   this.rendered = true;
   this.attached = true;
   this._postRender();
@@ -105,23 +121,85 @@
 };
 
 scout.Widget.prototype.remove = function() {
+  if (!this.rendered || this._isRemovalPending()) {
+    return;
+  }
+  if (this.animateRemoval) {
+    this._removeAnimated();
+  } else {
+    this._removeInternal();
+  }
+};
+
+/**
+ * Returns true if the removal of this or an ancestor widget is pending. Checking the ancestor is omitted if the parent is being removed.
+ * This may be used to prevent a removal if an ancestor will be removed (e.g by an animation)
+ */
+scout.Widget.prototype._isRemovalPending = function() {
+  if (this.removalPending) {
+    return true;
+  }
+  var parent = this.parent;
+  if (!parent || parent.removing) {
+    // If parent is being removed, no need to check the ancestors because removing is already in progress
+    return false;
+  }
+  while (parent) {
+    if (parent.removalPending) {
+      return true;
+    }
+    parent = parent.parent;
+  }
+  return false;
+};
+
+scout.Widget.prototype._removeInternal = function() {
   if (!this.rendered) {
     return;
   }
+
   $.log.trace('Removing widget: ' + this);
+  this.removing = true;
 
   // remove children in reverse order.
   this.children.slice().reverse().forEach(function(child) {
     child.remove();
   });
   this.session.keyStrokeManager.uninstallKeyStrokeContext(this.keyStrokeContext);
+  this._cleanup();
   this._remove();
-  this.rendered = false;
-  this.attached = false;
   if (this.parent) {
     this.parent.removeChild(this);
   }
-  this._trigger('remove');
+  this.rendered = false;
+  this.attached = false;
+  this.removing = false;
+  this.trigger('remove');
+};
+
+/**
+ * Adds class 'removed' to container which can be used to trigger the animation.
+ * After the animation is executed, the element gets removed using this._removeInternal.
+ */
+scout.Widget.prototype._removeAnimated = function() {
+  if (!scout.device.supportsCssAnimation() || !this.$container) {
+    // Cannot remove animated, remove regularly
+    this._removeInternal();
+    return;
+  }
+
+  // Remove open popups first, they are not animated
+  this.session.desktop.removePopupsFor(this);
+
+  this.removalPending = true;
+  // Don't execute immediately to make sure nothing interferes with the animation (e.g. layouting) which could make it laggy
+  setTimeout(function() {
+    this.$container.addClass('removed');
+    this.$container.oneAnimationEnd(function() {
+      this.removalPending = false;
+      this._removeInternal();
+    }.bind(this));
+  }.bind(this));
 };
 
 /**
@@ -133,17 +211,18 @@
   }
 };
 
-scout.Widget.prototype._trigger = function(type, event) {
-  event = event || {};
-  event.eventOn = this;
-  if (this.events) {
-    this.events.trigger(type, event);
+/**
+ * Called right before _remove is called.
+ * Default calls LayoutValidator.cleanupInvalidComponents to make sure that child components are removed from the invalid components list.
+ */
+scout.Widget.prototype._cleanup = function() {
+  if (this.$container) {
+    this.session.layoutValidator.cleanupInvalidComponents(this.$container);
   }
 };
 
 scout.Widget.prototype._remove = function() {
   if (this.$container) {
-    this.session.layoutValidator.cleanupInvalidObjects(this.$container);
     this.$container.remove();
     this.$container = null;
   }
@@ -172,14 +251,20 @@
   scout.arrays.remove(this.children, child);
 };
 
-scout.Widget.prototype.isOrHasWidget = function(widget) {
+/**
+ * @returns true if the given widget is the same as this or a descendant
+ */
+scout.Widget.prototype.isOrHas = function(widget) {
   if (widget === this) {
     return true;
   }
-  return this.hasWidget(widget);
+  return this.has(widget);
 };
 
-scout.Widget.prototype.hasWidget = function(widget) {
+/**
+ * @returns true if the given widget is a descendant
+ */
+scout.Widget.prototype.has = function(widget) {
   while (widget) {
     if (widget.parent === this) {
       return true;
@@ -190,6 +275,17 @@
   return false;
 };
 
+/**
+ * Adds default loading support to the widget. The default loading support hides
+ * the whole field $container when the field is in loading state. Override this
+ * method if you want to hide something else for a special field.
+ */
+scout.Widget.prototype.addLoadingSupport = function() {
+  this.loadingSupport = new scout.DefaultFieldLoadingSupport({
+    field: this
+  });
+};
+
 //--- Layouting / HtmlComponent methods ---
 
 scout.Widget.prototype.pack = function() {
@@ -271,42 +367,28 @@
   this.events = new scout.EventSupport();
 };
 
-/**
- * Call this function in the constructor of your widget if you need keystroke context support.
- **/
-scout.Widget.prototype._addKeyStrokeContextSupport = function() {
-  this.keyStrokeContext = this._createKeyStrokeContext();
-  if (this.keyStrokeContext) {
-    this.keyStrokeContext.$scopeTarget = function() {
-      return this.$container;
-    }.bind(this);
-    this.keyStrokeContext.$bindTarget = function() {
-      return this.$container;
-    }.bind(this);
-  }
-};
-
-/**
- * Creates a new keystroke context.
- * This method is intended to be overwritten by subclasses to provide another keystroke context.
- */
-scout.Widget.prototype._createKeyStrokeContext = function() {
-  return new scout.KeyStrokeContext();
-};
-
 scout.Widget.prototype.trigger = function(type, event) {
-  if (event) {
-    // create a shallow copy of the given event. Otherwise this function would
-    // have a side-effect on the given event because it adds the 'source' property
-    // which causes problems in some cases.
-    event = $.extend({}, event);
-  } else {
-    event = {};
+  if (!this.events) {
+    return;
   }
+
+  event = event || {};
   event.source = this;
   this.events.trigger(type, event);
 };
 
+scout.Widget.prototype.one = function(type, func) {
+  this.events.one(type, func);
+};
+
+scout.Widget.prototype.on = function(type, func) {
+  return this.events.on(type, func);
+};
+
+scout.Widget.prototype.off = function(type, func) {
+  this.events.off(type, func);
+};
+
 /**
  * @param $element (optional) element from which the entryPoint will be resolved. If not set this.$container is used.
  * @returns the entry-point for this Widget. If the widget is part of the main-window it returns this.session.$entryPoint,
@@ -320,18 +402,6 @@
   return $element.entryPoint();
 };
 
-scout.Widget.prototype.one = function(type, func) {
-  this.events.one(type, func);
-};
-
-scout.Widget.prototype.on = function(type, func) {
-  return this.events.on(type, func);
-};
-
-scout.Widget.prototype.off = function(type, func) {
-  this.events.off(type, func);
-};
-
 /**
  * This method attaches the detached $container to the DOM.
  */
@@ -374,9 +444,10 @@
  * widgets, because when a DOM element is detached - child elements are not notified
  */
 scout.Widget.prototype.detach = function() {
-  if (!this.attached || !this.rendered) {
+  if (!this.attached || !this.rendered || this._isRemovalPending()) {
     return;
   }
+
   this._triggerChildrenBeforeDetach(this);
   this._detach();
 };
@@ -407,6 +478,92 @@
   // NOP
 };
 
+/**
+ * Call this function in the constructor of your widget if you need keystroke context support.
+ **/
+scout.Widget.prototype._addKeyStrokeContextSupport = function() {
+  this.keyStrokeContext = this._createKeyStrokeContext();
+  if (this.keyStrokeContext) {
+    this.keyStrokeContext.$scopeTarget = function() {
+      return this.$container;
+    }.bind(this);
+    this.keyStrokeContext.$bindTarget = function() {
+      return this.$container;
+    }.bind(this);
+  }
+};
+
+/**
+ * Creates a new keystroke context.
+ * This method is intended to be overwritten by subclasses to provide another keystroke context.
+ */
+scout.Widget.prototype._createKeyStrokeContext = function() {
+  return new scout.KeyStrokeContext();
+};
+
+scout.Widget.prototype.updateKeyStrokes = function(newKeyStrokes, oldKeyStrokes) {
+  this.unregisterKeyStrokes(oldKeyStrokes);
+  this.registerKeyStrokes(newKeyStrokes);
+};
+
+scout.Widget.prototype.registerKeyStrokes = function(keyStrokes) {
+  keyStrokes = scout.arrays.ensure(keyStrokes);
+  keyStrokes.forEach(function(keyStroke) {
+    this.keyStrokeContext.registerKeyStroke(keyStroke);
+  }, this);
+};
+
+scout.Widget.prototype.unregisterKeyStrokes = function(keyStrokes) {
+  keyStrokes = scout.arrays.ensure(keyStrokes);
+  keyStrokes.forEach(function(keyStroke) {
+    this.keyStrokeContext.unregisterKeyStroke(keyStroke);
+  }, this);
+};
+
+scout.Widget.prototype._fireBulkPropertyChange = function(oldProperties, newProperties) {
+  var propertyChangeEvent = {
+    newProperties: newProperties,
+    oldProperties: oldProperties,
+    changedProperties: []
+  };
+  // To allow a listener to react only to properties that have really changed their value, we
+  // calculate the list of "changedProperties". This may be relevant, when the value on the model
+  // changes from A to B and back to A, which emits a property change event when in fact, the
+  // property has not really changed for the UI.
+  for (var prop in newProperties) {
+    if (newProperties[prop] !== oldProperties[prop]) {
+      propertyChangeEvent.changedProperties.push(prop);
+    }
+  }
+  this.trigger('propertyChange', propertyChangeEvent);
+};
+
+/**
+ * Fires a property change for a single property.
+ */
+scout.Widget.prototype._firePropertyChange = function(propertyName, oldValue, newValue) {
+  if (!propertyName) {
+    return;
+  }
+  var oldProperties = {},
+    newProperties = {};
+  oldProperties[propertyName] = oldValue;
+  newProperties[propertyName] = newValue;
+  this._fireBulkPropertyChange(oldProperties, newProperties);
+};
+
+/**
+ * Sets the value of the property 'propertyName' to 'newValue' and then fires a propertyChange event for that property.
+ */
+scout.Widget.prototype._setProperty = function(propertyName, newValue) {
+  if (!propertyName) {
+    return;
+  }
+  var oldValue = this[propertyName];
+  this[propertyName] = newValue;
+  this._firePropertyChange(propertyName, oldValue, newValue);
+};
+
 scout.Widget.prototype.toString = function() {
   return 'Widget[rendered=' + this.rendered +
     (this.$container ? ' $container=' + scout.graphics.debugOutput(this.$container) : '') + ']';
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/FONTLOG.txt b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/FONTLOG.txt
new file mode 100644
index 0000000..d80d4e1
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/FONTLOG.txt
@@ -0,0 +1,18 @@
+FONTLOG for the ScoutIcons fonts
+
+This file provides detailed information on the ScoutIcons Font Software.
+This information should be distributed along with the ScoutIcons fonts
+and any derivative works.
+
+Basic Font Information
+
+ScoutIcons is used for graphical font icons within the Eclipse Scout
+user interface. Some characters in the fonts are imported from
+Font Awesome (http://fontawesome.io/).
+
+ChangeLog
+
+20 October 2014 (Claudio Guglielmo)
+- Initial release
+
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/LICENSE_ScoutIcons b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/LICENSE_ScoutIcons
new file mode 100644
index 0000000..13ecde7
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/LICENSE_ScoutIcons
@@ -0,0 +1,94 @@
+Copyright (c) 2016, BSI Business Systems Integration AG (<https://www.bsi-software.com/>),
+with Reserved Font Name ScoutIcons.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/OFL-FAQ.txt b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/OFL-FAQ.txt
new file mode 100644
index 0000000..b7caf2b
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/OFL-FAQ.txt
@@ -0,0 +1,427 @@
+OFL FAQ - Frequently Asked Questions about the SIL Open Font License (OFL)
+Version 1.1-update4 - Sept 2014
+(See http://scripts.sil.org/OFL for updates)
+
+
+CONTENTS OF THIS FAQ
+1  USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL
+2  USING OFL FONTS FOR WEB PAGES AND ONLINE WEB FONT SERVICES
+3  MODIFYING OFL-LICENSED FONTS
+4  LICENSING YOUR ORIGINAL FONTS UNDER THE OFL
+5  CHOOSING RESERVED FONT NAMES
+6  ABOUT THE FONTLOG
+7  MAKING CONTRIBUTIONS TO OFL PROJECTS
+8  ABOUT THE LICENSE ITSELF
+9  ABOUT SIL INTERNATIONAL
+APPENDIX A - FONTLOG EXAMPLE
+
+1  USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL
+
+1.1  Can I use the fonts for a book or other print publication, to create logos or other graphics or even to manufacture objects based on their outlines?
+Yes. You are very welcome to do so. Authors of fonts released under the OFL allow you to use their font software as such for any kind of design work. No additional license or permission is required, unlike with some other licenses. Some examples of these uses are: logos, posters, business cards, stationery, video titling, signage, t-shirts, personalised fabric, 3D-printed/laser-cut shapes, sculptures, rubber stamps, cookie cutters and lead type.
+
+1.1.1  Does that restrict the license or distribution of that artwork?
+No. You remain the author and copyright holder of that newly derived graphic or object. You are simply using an open font in the design process. It is only when you redistribute, bundle or modify the font itself that other conditions of the license have to be respected (see below for more details).
+
+1.1.2  Is any kind of acknowledgement required?
+No. Font authors may appreciate being mentioned in your artwork's acknowledgements alongside the name of the font, possibly with a link to their website, but that is not required.
+
+1.2  Can the fonts be included with Free/Libre and Open Source Software collections such as GNU/Linux and BSD distributions and repositories?
+Yes! Fonts licensed under the OFL can be freely included alongside other software under FLOSS (Free/Libre and Open Source Software) licenses. Since fonts are typically aggregated with, not merged into, existing software, there is little need to be concerned about incompatibility with existing software licenses. You may also repackage the fonts and the accompanying components in a .rpm or .deb package (or other similar package formats or installers) and include them in distribution CD/DVDs and online repositories. (Also see section 5.9 about rebuilding from source.)
+
+1.3  I want to distribute the fonts with my program. Does this mean my program also has to be Free/Libre and Open Source Software?
+No. Only the portions based on the Font Software are required to be released under the OFL. The intent of the license is to allow aggregation or bundling with software under restricted licensing as well.
+
+1.4  Can I sell a software package that includes these fonts?
+Yes, you can do this with both the Original Version and a Modified Version of the fonts. Examples of bundling made possible by the OFL would include: word processors, design and publishing applications, training and educational software, games and entertainment software, mobile device applications, etc.
+
+1.5  Can I include the fonts on a CD of freeware or commercial fonts?
+Yes, as long some other font or software is also on the disk, so the OFL font is not sold by itself.
+
+1.6  Why won't the OFL let me sell the fonts alone?
+The intent is to keep people from making money by simply redistributing the fonts. The only people who ought to profit directly from the fonts should be the original authors, and those authors have kindly given up potential direct income to distribute their fonts under the OFL. Please honour and respect their contribution!
+
+1.7  What about sharing OFL fonts with friends on a CD, DVD or USB stick?
+You are very welcome to share open fonts with friends, family and colleagues through removable media. Just remember to include the full font package, including any copyright notices and licensing information as available in OFL.txt. In the case where you sell the font, it has to come bundled with software.
+
+1.8  Can I host the fonts on a web site for others to use?
+Yes, as long as you make the full font package available. In most cases it may be best to point users to the main site that distributes the Original Version so they always get the most recent stable and complete version. See also discussion of web fonts in Section 2.
+
+1.9  Can I host the fonts on a server for use over our internal network?
+Yes. If the fonts are transferred from the server to the client computer by means that allow them to be used even if the computer is no longer attached to the network, the full package (copyright notices, licensing information, etc.) should be included.
+
+1.10  Does the full OFL license text always need to accompany the font?
+The only situation in which an OFL font can be distributed without the text of the OFL (either in a separate file or in font metadata), is when a font is embedded in a document or bundled within a program. In the case of metadata included within a font, it is legally sufficient to include only a link to the text of the OFL on http://scripts.sil.org/OFL, but we strongly recommend against this. Most modern font formats include metadata fields that will accept the full OFL text, and full inclusion increases the likelihood that users will understand and properly apply the license.
+
+1.11  What do you mean by 'embedding'? How does that differ from other means of distribution?
+By 'embedding' we mean inclusion of the font in a document or file in a way that makes extraction (and redistribution) difficult or clearly discouraged. In many cases the names of embedded fonts might also not be obvious to those reading the document, the font data format might be altered, and only a subset of the font - only the glyphs required for the text - might be included. Any other means of delivering a font to another person is considered 'distribution', and needs to be accompanied by any copyright notices and licensing information available in OFL.txt.
+
+1.12  So can I embed OFL fonts in my document?
+Yes, either in full or a subset. The restrictions regarding font modification and redistribution do not apply, as the font is not intended for use outside the document.
+
+1.13  Does embedding alter the license of the document itself?
+No. Referencing or embedding an OFL font in any document does not change the license of the document itself. The requirement for fonts to remain under the OFL does not apply to any document created using the fonts and their derivatives. Similarly, creating any kind of graphic using a font under OFL does not make the resulting artwork subject to the OFL.
+
+1.14  If OFL fonts are extracted from a document in which they are embedded (such as a PDF file), what can be done with them? Is this a risk to author(s)?
+The few utilities that can extract fonts embedded in a PDF will typically output limited amounts of outlines - not a complete font. To create a working font from this method is much more difficult and time consuming than finding the source of the original OFL font. So there is little chance that an OFL font would be extracted and redistributed inappropriately through this method. Even so, copyright laws address any misrepresentation of authorship. All Font Software released under the OFL and marked as such by the author(s) is intended to remain under this license regardless of the distribution method, and cannot be redistributed under any other license. We strongly discourage any font extraction - we recommend directly using the font sources instead - but if you extract font outlines from a document, please be considerate: respect the work of the author(s) and the licensing model.
+
+1.15  What about distributing fonts with a document? Within a compressed folder structure? Is it distribution, bundling or embedding?
+Certain document formats may allow the inclusion of an unmodified font within their file structure which may consist of a compressed folder containing the various resources forming the document (such as pictures and thumbnails). Including fonts within such a structure is understood as being different from embedding but rather similar to bundling (or mere aggregation) which the license explicitly allows. In this case the font is conveyed unchanged whereas embedding a font usually transforms it from the original format. The OFL does not allow anyone to extract the font from such a structure to then redistribute it under another license. The explicit permission to redistribute and embed does not cancel the requirement for the Font Software to remain under the license chosen by its author(s). Even if the font travels inside the document as one of its assets, it should not lose its authorship information and licensing.
+
+1.16  What about ebooks shipping with open fonts?
+The requirements differ depending on whether the fonts are linked, embedded or distributed (bundled or aggregated). Some ebook formats use web technologies to do font linking via @font-face, others are designed for font embedding, some use fonts distributed with the document or reading software, and a few rely solely on the fonts already present on the target system. The license requirements depend on the type of inclusion as discussed in 1.15.
+
+1.17  Can Font Software released under the OFL be subject to URL-based access restrictions methods or DRM (Digital Rights Management) mechanisms?
+Yes, but these issues are out-of-scope for the OFL. The license itself neither encourages their use nor prohibits them since such mechanisms are not implemented in the components of the Font Software but through external software. Such restrictions are put in place for many different purposes corresponding to various usage scenarios. One common example is to limit potentially dangerous cross-site scripting attacks. However, in the spirit of libre/open fonts and unrestricted writing systems, we strongly encourage open sharing and reuse of OFL fonts, and the establishment of an environment where such restrictions are unnecessary. Note that whether you wish to use such mechanisms or you prefer not to, you must still abide by the rules set forth by the OFL when using fonts released by their authors under this license. Derivative fonts must be licensed under the OFL, even if they are part of a service for which you charge fees and/or for which access to source code is restricted. You may not sell the fonts on their own - they must be part of a larger software package, bundle or subscription plan. For example, even if the OFL font is distributed in a software package or via an online service using a DRM mechanism, the user would still have the right to extract that font, use, study, modify and redistribute it under the OFL.
+
+1.18  I've come across a font released under the OFL. How can I easily get more information about the Original Version? How can I know where it stands compared to the Original Version or other Modified Versions?
+Consult the copyright statement(s) in the license for ways to contact the original authors. Consult the FONTLOG (see section 6 for more details and examples) for information on how the font differs from the Original Version, and get in touch with the various contributors via the information in the acknowledgement section. Please consider using the Original Versions of the fonts whenever possible.
+
+1.19  What do you mean in condition 4 of the OFL's permissions and conditions? Can you provide examples of abusive promotion / endorsement / advertisement vs. normal acknowledgement?
+The intent is that the goodwill and reputation of the author(s) should not be used in a way that makes it sound like the original author(s) endorse or approve of a specific Modified Version or software bundle. For example, it would not be right to advertise a word processor by naming the author(s) in a listing of software features, or to promote a Modified Version on a web site by saying "designed by ...". However, it would be appropriate to acknowledge the author(s) if your software package has a list of people who deserve thanks. We realize that this can seem to be a grey area, but the standard used to judge an acknowledgement is that if the acknowledgement benefits the author(s) it is allowed, but if it primarily benefits other parties, or could reflect poorly on the author(s), then it is not.
+
+1.20 I'm writing a small app for mobile platforms, do I need to include the whole package? 
+If you bundle a font under the OFL with your mobile app you must comply with the terms of the license. At a minimum you must include the copyright statement, the license notice and the license text. A mention of this information in your About box or Changelog, with a link to where the font package is from, is good practice, and the extra space needed to carry these items is very small. You do not, however, need to include the full contents of the font package - only the fonts you use and the copyright and license that apply to them. For example, if you only use the regular weight in your app, you do not need to include the italic and bold versions.
+
+1.21 What about including OFL fonts by default in my firmware or dedicated operating system? 
+Many such systems are restricted and turned into appliances so that users cannot study or modify them. Using open fonts to increase quality and language coverage is a great idea, but you need to be aware that if there is a way for users to extract fonts you cannot legally prevent them from doing that. The fonts themselves, including any changes you make to them, must be distributed under the OFL even if your firmware has a more restrictive license. If you do transform the fonts and change their formats when you include them in your firmware you must respect any names reserved by the font authors via the RFN mechanism and pick your own font name. Alternatively if you directly add a font under the OFL to the font folder of your firmware without modifying or optimizing it you are simply bundling the font like with any other software collection, and do not need to make any further changes.
+
+1.22  Can I make and publish CMS themes or templates that use OFL fonts?  Can I include the fonts themselves in the themes or templates? Can I sell the whole package?
+Yes, you are very welcome to integrate open fonts into themes and templates for your preferred CMS and make them more widely available. Remember that you can only sell the fonts and your CMS add-on as part of a software bundle. (See 1.4 for details and examples about selling bundles).
+
+1.23  Can OFL fonts be included in services that deliver fonts to the desktop from remote repositories? Even if they contain both OFL and non-OFL fonts?
+Yes. Some foundries have set up services to deliver fonts to subscribers directly to desktops from their online repositories; similarly, plugins are available to preview and use fonts directly in your design tool or publishing suite. These services may mix open and restricted fonts in the same channel, however they should make a clear distinction between them to users. These services should also not hinder users (such as through DRM or obfuscation mechanisms) from extracting and using the OFL fonts in other environments, or continuing to use OFL fonts after subscription terms have ended, as those uses are specifically allowed by the OFL.
+
+1.24  Can services that provide or distribute OFL fonts restrict my use of them?
+No. The terms of use of such services cannot replace or restrict the terms of the OFL, as that would be the same as distributing the fonts under a different license, which is not allowed. You are still entitled to use, modify and redistribute them as the original authors have intended outside of the sole control of that particular distribution channel. Note, however, that the fonts provided by these services may differ from the Original Versions.
+
+
+2  USING OFL FONTS FOR WEBPAGES AND ONLINE WEB FONT SERVICES
+
+NOTE: This section often refers to a separate paper on 'Web Fonts & RFNs'. This is available at http://scripts.sil.org/OFL_web_fonts_and_RFNs
+
+2.1  Can I make webpages using these fonts?
+Yes! Go ahead! Using CSS (Cascading Style Sheets) is recommended. Your three best options are: 
+- referring directly in your stylesheet to open fonts which may be available on the user's system
+- providing links to download the full package of the font - either from your own website or from elsewhere - so users can install it themselves
+- using @font-face to distribute the font directly to browsers. This is recommended and explicitly allowed by the licensing model because it is distribution. The font file itself is distributed with other components of the webpage. It is not embedded in the webpage but referenced through a web address which will cause the browser to retrieve and use the corresponding font to render the webpage (see 1.11 and 1.15 for details related to embedding fonts into documents). As you take advantage of the @font-face cross-platform standard, be aware that web fonts are often tuned for a web environment and not intended for installation and use outside a browser. The reasons in favour of using web fonts are to allow design of dynamic text elements instead of static graphics, to make it easier for content to be localized and translated, indexed and searched, and all this with cross-platform open standards without depending on restricted extensions or plugins. You should check the CSS cascade (the order in which fonts are being called or delivered to your users) when testing.
+
+2.2  Can I make and use WOFF (Web Open Font Format) versions of OFL fonts?
+Yes, but you need to be careful. A change in font format normally is considered modification, and Reserved Font Names (RFNs) cannot be used. Because of the design of the WOFF format, however, it is possible to create a WOFF version that is not considered modification, and so would not require a name change. You are allowed to create, use and distribute a WOFF version of an OFL font without changing the font name, but only if:
+
+- the original font data remains unchanged except for WOFF compression, and
+- WOFF-specific metadata is either omitted altogether or present and includes, unaltered, the contents of all equivalent metadata in the original font.
+
+If the original font data or metadata is changed, or the WOFF-specific metadata is incomplete, the font must be considered a Modified Version, the OFL restrictions would apply and the name of the font must be changed: any RFNs cannot be used and copyright notices and licensing information must be included and cannot be deleted or modified. You must come up with a unique name - we recommend one corresponding to your domain or your particular web application. Be aware that only the original author(s) can use RFNs. This is to prevent collisions between a derivative tuned to your audience and the original upstream version and so to reduce confusion.
+
+Please note that most WOFF conversion tools and online services do not meet the two requirements listed above, and so their output must be considered a Modified Version. So be very careful and check to be sure that the tool or service you're using is compressing unchanged data and completely and accurately reflecting the original font metadata.
+
+2.3  What about other web font formats such as EOT/EOTLite/CWT/etc.?
+In most cases these formats alter the original font data more than WOFF, and do not completely support appropriate metadata, so their use must be considered modification and RFNs may not be used. However, there may be certain formats or usage scenarios that may allow the use of RFNs. See http://scripts.sil.org/OFL_web_fonts_and_RFNs 
+
+2.4  Can I make OFL fonts available through web font online services?
+Yes, you are welcome to include OFL fonts in online web font services as long as you properly meet all the conditions of the license. The origin and open status of the font should be clear among the other fonts you are hosting. Authorship, copyright notices and license information must be sufficiently visible to your users or subscribers so they know where the font comes from and the rights granted by the author(s). Make sure the font file contains the needed copyright notice(s) and licensing information in its metadata. Please double-check the accuracy of every field to prevent contradictory information. Other font formats, including EOT/EOTLite/CWT and superior alternatives like WOFF, already provide fields for this information. Remember that if you modify the font within your library or convert it to another format for any reason the OFL restrictions apply and you need to change the names accordingly. Please respect the author's wishes as expressed in the OFL and do not misrepresent original designers and their work. Don't lump quality open fonts together with dubious freeware or public domain fonts. Consider how you can best work with the original designers and foundries, support their efforts and generate goodwill that will benefit your service. (See 1.17 for details related to URL-based access restrictions methods or DRM mechanisms).
+
+2.5  Some web font formats and services provide ways of "optimizing" the font for a particular website or web application; is that allowed? 
+Yes, it is permitted, but remember that these optimized versions are Modified Versions and so must follow OFL requirements like appropriate renaming. Also you need to bear in mind the other important parameters beyond compression, speed and responsiveness: you need to consider the audience of your particular website or web application, as choosing some optimization parameters may turn out to be less than ideal for them. Subsetting by removing certain glyphs or features may seriously limit functionality of the font in various languages that your users expect. It may also introduce degradation of quality in the rendering or specific bugs on the various target platforms compared to the original font from upstream. In other words, remember that one person's optimized font may be another person's missing feature. Various advanced typographic features (OpenType, Graphite or AAT) are also available through CSS and may provide the desired effects without the need to modify the font.
+
+2.6  Is subsetting a web font considered modification?
+Yes. Removing any parts of the font when delivering a web font to a browser, including unused glyphs and smart font code, is considered modification. This is permitted by the OFL but would not normally allow the use of RFNs. Some newer subsetting technologies may be able to subset in a way that allows users to effectively have access to the complete font, including smart font behaviour. See 2.8 and http://scripts.sil.org/OFL_web_fonts_and_RFNs
+
+2.7  Are there any situations in which a modified web font could use RFNs?
+Yes. If a web font is optimized only in ways that preserve Functional Equivalence (see 2.8), then it may use RFNs, as it reasonably represents the Original Version and respects the intentions of the author(s) and the main purposes of the RFN mechanism (avoids collisions, protects authors, minimizes support, encourages derivatives). However this is technically very difficult and often impractical, so a much better scenario is for the web font service or provider to sign a separate agreement with the author(s) that allows the use of RFNs for Modified Versions.
+
+2.8  How do you know if an optimization to a web font preserves Functional Equivalence?
+Functional Equivalence is described in full in the 'Web fonts and RFNs' paper at http://scripts.sil.org/OFL_web_fonts_and_RFNs, in general, an optimized font is deemed to be Functionally Equivalent (FE) to the Original Version if it:
+
+- Supports the same full character inventory. If a character can be properly displayed using the Original Version, then that same character, encoded correctly on a web page, will display properly. 
+- Provides the same smart font behavior. Any dynamic shaping behavior that works with the Original Version should work when optimized, unless the browser or environment does not support it. There does not need to be guaranteed support in the client, but there should be no forced degradation of smart font or shaping behavior, such as the removal or obfuscation of OpenType, Graphite or AAT tables.
+- Presents text with no obvious degradation in visual quality. The lettershapes should be equally (or more) readable, within limits of the rendering platform.
+- Preserves original author, project and license metadata. At a minimum, this should include: Copyright and authorship; The license as stated in the Original Version, whether that is the full text of the OFL or a link to the web version; Any RFN declarations; Information already present in the font or documentation that points back to the Original Version, such as a link to the project or the author's website.
+
+If an optimized font meets these requirements, and so is considered to be FE, then it's very likely that the original author would feel that the optimized font is a good and reasonable equivalent. If it falls short of any of these requirements, the optimized font does not reasonably represent the Original Version, and so should be considered to be a Modified Version. Like other Modified Versions, it would not be allowed to use any RFNs and you simply need to pick your own font name.
+
+2.9  Isn't use of web fonts another form of embedding?
+No. Unlike embedded fonts in a PDF, web fonts are not an integrated part of the document itself. They are not specific to a single document and are often applied to thousands of documents around the world. The font data is not stored alongside the document data and often originates from a different location. The ease by which the web fonts used by a document may be identified and downloaded for desktop use demonstrates that they are philosophically and technically separate from the web pages that specify them. See http://scripts.sil.org/OFL_web_fonts_and_RFNs
+
+2.10  So would it be better to not use RFNs at all if you want your font to be distributed by a web fonts service?
+No. Although the OFL does not require authors to use RFNs, the RFN mechanism is an important part of the OFL model and completely compatible with web font services. If that web font service modifies the fonts, then the best solution is to sign a separate agreement for the use of any RFNs. It is perfectly valid for an author to not declare any RFNs, but before they do so they need to fully understand the benefits they are giving up, and the overall negative effect of allowing many different versions bearing the same name to be widely distributed. As a result, we don't generally recommend it.
+
+2.11  What should an agreement for the use of RFNs say? Are there any examples?
+There is no prescribed format for this agreement, as legal systems vary, and no recommended examples. Authors may wish to add specific clauses to further restrict use, require author review of Modified Versions, establish user support mechanisms or provide terms for ending the agreement. Such agreements are usually not public, and apply only to the main parties. However, it would be very beneficial for web font services to clearly state when they have established such agreements, so that the public understands clearly that their service is operating appropriately.
+
+See the separate paper on 'Web Fonts & RFNs' for in-depth discussion of issues related to the use of RFNs for web fonts. This is available at http://scripts.sil.org/OFL_web_fonts_and_RFNs
+
+
+3  MODIFYING OFL-LICENSED FONTS
+
+3.1  Can I change the fonts? Are there any limitations to what things I can and cannot change?
+You are allowed to change anything, as long as such changes do not violate the terms of the license. In other words, you are not allowed to remove the copyright statement(s) from the font, but you could put additional information into it that covers your contribution. See the placeholders in the OFL header template for recommendations on where to add your own statements. (Remember that, when authors have reserved names via the RFN mechanism, you need to change the internal names of the font to your own font name when making your modified version even if it is just a small change.)
+
+3.2  I have a font that needs a few extra glyphs - can I take them from an OFL licensed font and copy them into mine?
+Yes, but if you distribute that font to others it must be under the OFL, and include the information mentioned in condition 2 of the license.
+
+3.3  Can I charge people for my additional work? In other words, if I add a bunch of special glyphs or OpenType/Graphite/AAT code, can I sell the enhanced font?
+Not by itself. Derivative fonts must be released under the OFL and cannot be sold by themselves. It is permitted, however, to include them in a larger software package (such as text editors, office suites or operating systems), even if the larger package is sold. In that case, you are strongly encouraged, but not required, to also make that derived font easily and freely available outside of the larger package.
+
+3.4  Can I pay someone to enhance the fonts for my use and distribution?
+Yes. This is a good way to fund the further development of the fonts. Keep in mind, however, that if the font is distributed to others it must be under the OFL. You won't be able to recover your investment by exclusively selling the font, but you will be making a valuable contribution to the community. Please remember how you have benefited from the contributions of others.
+
+3.5  I need to make substantial revisions to the font to make it work with my program. It will be a lot of work, and a big investment, and I want to be sure that it can only be distributed with my program. Can I restrict its use?
+No. If you redistribute a Modified Version of the font it must be under the OFL. You may not restrict it in any way beyond what the OFL permits and requires. This is intended to ensure that all released improvements to the fonts become available to everyone. But you will likely get an edge over competitors by being the first to distribute a bundle with the enhancements. Again, please remember how you have benefited from the contributions of others.
+
+3.6  Do I have to make any derivative fonts (including extended source files, build scripts, documentation, etc.) publicly available?
+No, but please consider sharing your improvements with others. You may find that you receive in return more than what you gave.
+
+3.7  If a trademark is claimed in the OFL font, does that trademark need to remain in modified fonts?
+Yes. Any trademark notices must remain in any derivative fonts to respect trademark laws, but you may add any additional trademarks you claim, officially registered or not. For example if an OFL font called "Foo" contains a notice that "Foo is a trademark of Acme", then if you rename the font to "Bar" when creating a Modified Version, the new trademark notice could say "Foo is a trademark of Acme Inc. - Bar is a trademark of Roadrunner Technologies Ltd.". Trademarks work alongside the OFL and are not subject to the terms of the licensing agreement. The OFL does not grant any rights under trademark law. Bear in mind that trademark law varies from country to country and that there are no international trademark conventions as there are for copyright. You may need to significantly invest in registering and defending a trademark for it to remain valid in the countries you are interested in. This may be costly for an individual independent designer.
+
+3.8 If I commit changes to a font (or publish a branch in a DVCS) as part of a public open source software project, do I have to change the internal font names? 
+Only if there are declared RFNs. Making a public commit or publishing a public branch is effectively redistributing your modifications, so any change to the font will require that you do not use the RFNs. Even if there are no RFNs, it may be useful to change the name or add a suffix indicating that a particular version of the font is still in development and not released yet. This will clearly indicate to users and fellow designers that this particular font is not ready for release yet. See section 5 for more details.
+
+
+4  LICENSING YOUR ORIGINAL FONTS UNDER THE OFL
+
+4.1  Can I use the SIL OFL for my own fonts?
+Yes! We heartily encourage everyone to use the OFL to distribute their own original fonts. It is a carefully constructed license that allows great freedom along with enough artistic integrity protection for the work of the authors as well as clear rules for other contributors and those who redistribute the fonts. The licensing model is used successfully by various organisations, both for-profit and not-for-profit, to release fonts of varying levels of scope and complexity.
+
+4.2  What do I have to do to apply the OFL to my font?
+If you want to release your fonts under the OFL, we recommend you do the following:
+
+4.2.1  Put your copyright and Reserved Font Names information at the beginning of the main OFL.txt file in place of the dedicated placeholders (marked with the <> characters). Include this file in your release package.
+
+4.2.2  Put your copyright and the OFL text with your chosen Reserved Font Name(s) into your font files (the copyright and license fields). A link to the OFL text on the OFL web site is an acceptable (but not recommended) alternative. Also add this information to any other components (build scripts, glyph databases, documentation, test files, etc). Accurate metadata in your font files is beneficial to you as an increasing number of applications are exposing this information to the user. For example, clickable links can bring users back to your website and let them know about other work you have done or services you provide. Depending on the format of your fonts and sources, you can use template human-readable headers or machine-readable metadata. You should also double-check that there is no conflicting metadata in the font itself contradicting the license, such as the fstype bits in the os2 table or fields in the name table.
+
+4.2.3  Write an initial FONTLOG.txt for your font and include it in the release package (see Section 6 and Appendix A for details including a template).
+
+4.2.4  Include the relevant practical documentation on the license by adding the current OFL-FAQ.txt file in your package.
+
+4.2.5  If you wish you can use the OFL graphics (http://scripts.sil.org/OFL_logo) on your website. 
+
+4.3  Will you make my font OFL for me?
+We won't do the work for you. We can, however, try to answer your questions, unfortunately we do not have the resources to review and check your font packages for correct use of the OFL. We recommend you turn to designers, foundries or consulting companies with experience in doing open font design to provide this service to you. 
+
+4.4  Will you distribute my OFL font for me?
+No, although if the font is of sufficient quality and general interest we may include a link to it on our partial list of OFL fonts on the OFL web site. You may wish to consider other open font catalogs or hosting services, such as the Unifont Font Guide (http://unifont.org/fontguide), The League of Movable Type (http://theleagueofmovabletype.com) or the Open Font Library (http://openfontlibrary.org/), which despite the name has no direct relationship to the OFL or SIL. We do not endorse any particular catalog or hosting service - it is your responsibility to determine if the service is right for you and if it treats authors with fairness. 
+
+4.5  Why should I use the OFL for my fonts?
+- to meet needs for fonts that can be modified to support lesser-known languages
+- to provide a legal and clear way for people to respect your work but still use it (and reduce piracy)
+- to involve others in your font project
+- to enable your fonts to be expanded with new weights and improved writing system/language support
+- to allow more technical font developers to add features to your design (such as OpenType, Graphite or AAT support)
+- to renew the life of an old font lying on your hard drive with no business model
+- to allow your font to be included in Libre Software operating systems like Ubuntu
+- to give your font world status and wide, unrestricted distribution
+- to educate students about quality typeface and font design
+- to expand your test base and get more useful feedback 
+- to extend your reach to new markets when users see your metadata and go to your website
+- to get your font more easily into one of the web font online services
+- to attract attention for your commercial fonts
+- to make money through web font services
+- to make money by bundling fonts with applications
+- to make money adjusting and extending existing open fonts
+- to get a better chance that foundations/NGOs/charities/companies who commission fonts will pick you 
+- to be part of a sharing design and development community 
+- to give back and contribute to a growing body of font sources
+
+
+5  CHOOSING RESERVED FONT NAMES
+
+5.1  What are Reserved Font Names?
+These are font names, or portions of font names, that the author has chosen to reserve for use only with the Original Version of the font, or for Modified Version(s) created by the original author.
+
+5.2  Why can't I use the Reserved Font Names in my derivative font names? I'd like people to know where the design came from.
+The best way to acknowledge the source of the design is to thank the original authors and any other contributors in the files that are distributed with your revised font (although no acknowledgement is required). The FONTLOG is a natural place to do this. Reserved Font Names ensure that the only fonts that have the original names are the unmodified Original Versions. This allows designers to maintain artistic integrity while allowing collaboration to happen. It eliminates potential confusion and name conflicts. When choosing a name, be creative and avoid names that reuse almost all the same letters in the same order or sound like the original. It will help everyone if Original Versions and Modified Versions can easily be distinguished from one another and from other derivatives. Any substitution and matching mechanism is outside the scope of the license.
+
+5.3  What do you mean by "primary name as presented to the user"? Are you referring to the font menu name?
+Yes, this applies to the font menu name and other mechanisms that specify a font in a document. It would be fine, however, to keep a text reference to the original fonts in the description field, in your modified source file or in documentation provided alongside your derivative as long as no one could be confused that your modified source is the original. But you cannot use the Reserved Font Names in any way to identify the font to the user (unless the Copyright Holder(s) allow(s) it through a separate agreement). Users who install derivatives (Modified Versions) on their systems should not see any of the original Reserved Font Names in their font menus, for example. Again, this is to ensure that users are not confused and do not mistake one font for another and so expect features only another derivative or the Original Version can actually offer. 
+
+5.4  Am I not allowed to use any part of the Reserved Font Names?
+You may not use individual words from the Reserved Font Names, but you would be allowed to use parts of words, as long as you do not use any word from the Reserved Font Names entirely. We do not recommend using parts of words because of potential confusion, but it is allowed. For example, if "Foobar" was a Reserved Font Name, you would be allowed to use "Foo" or "bar", although we would not recommend it. Such an unfortunate choice would confuse the users of your fonts as well as make it harder for other designers to contribute.
+
+5.5  So what should I, as an author, identify as Reserved Font Names?
+Original authors are encouraged to name their fonts using clear, distinct names, and only declare the unique parts of the name as Reserved Font Names. For example, the author of a font called "Foobar Sans" would declare "Foobar" as a Reserved Font Name, but not "Sans", as that is a common typographical term, and may be a useful word to use in a derivative font name. Reserved Font Names should also be single words for simplicity and legibility. A font called "Flowing River" should have Reserved Font Names "Flowing" and "River", not "Flowing River". You also need to be very careful about reserving font names which are already linked to trademarks (whether registered or not) which you do not own.
+
+5.6  Do I, as an author, have to identify any Reserved Font Names?
+No. RFNs are optional and not required, but we encourage you to use them. This is primarily to avoid confusion between your work and Modified Versions. As an author you can release a font under the OFL and not declare any Reserved Font Names. There may be situations where you find that using no RFNs and letting your font be changed and modified - including any kind of modification - without having to change the original name is desirable. However you need to be fully aware of the consequences. There will be no direct way for end-users and other designers to distinguish your Original Version from many Modified Versions that may be created. You have to trust whoever is making the changes and the optimizations to not introduce problematic changes. The RFNs you choose for your own creation have value to you as an author because they allow you to maintain artistic integrity and keep some control over the distribution channel to your end-users. For discussion of RFNs and web fonts see section 2.
+
+5.7  Are any names (such as the main font name) reserved by default?
+No. That is a change to the license as of version 1.1. If you want any names to be Reserved Font Names, they must be specified after the copyright statement(s).
+
+5.8  Is there any situation in which I can use Reserved Font Names for a Modified Version?
+The Copyright Holder(s) can give certain trusted parties the right to use any of the Reserved Font Names through separate written agreements. For example, even if "Foobar" is a RFN, you could write up an agreement to give company "XYZ" the right to distribute a modified version with a name that includes "Foobar". This allows for freedom without confusion. The existence of such an agreement should be made as clear as possible to downstream users and designers in the distribution package and the relevant documentation. They need to know if they are a party to the agreement or not and what they are practically allowed to do or not even if all the details of the agreement are not public.
+
+5.9  Do font rebuilds require a name change? Do I have to change the name of the font when my packaging workflow includes a full rebuild from source?
+Yes, all rebuilds which change the font data and the smart code are Modified Versions and the requirements of the OFL apply: you need to respect what the Author(s) have chosen in terms of Reserved Font Names. However if a package (or installer) is simply a wrapper or a compressed structure around the final font - leaving them intact on the inside - then no name change is required. Please get in touch with the author(s) and copyright holder(s) to inquire about the presence of font sources beyond the final font file(s) and the recommended build path. That build path may very well be non-trivial and hard to reproduce accurately by the maintainer. If a full font build path is made available by the upstream author(s) please be aware that any regressions and changes you may introduce when doing a rebuild for packaging purposes is your own responsibility as a package maintainer since you are effectively creating a separate branch. You should make it very clear to your users that your rebuilt version is not the canonical one from upstream.
+
+5.10  Can I add other Reserved Font Names when making a derivative font?
+Yes. List your additional Reserved Font Names after your additional copyright statement, as indicated with example placeholders at the top of the OFL.txt file. Be sure you do not remove any existing RFNs but only add your own. RFN statements should be placed next to the copyright statement of the relevant author as indicated in the OFL.txt template to make them visible to designers wishing to make their separate version.
+
+
+6  ABOUT THE FONTLOG
+
+6.1  What is this FONTLOG thing exactly?
+It has three purposes: 1) to provide basic information on the font to users and other designers and developers, 2) to document changes that have been made to the font or accompanying files, either by the original authors or others, and 3) to provide a place to acknowledge authors and other contributors. Please use it!
+
+6.2  Is the FONTLOG required?
+It is not a requirement of the license, but we strongly recommend you have one.
+
+6.3  Am I required to update the FONTLOG when making Modified Versions?
+No, but users, designers and other developers might get very frustrated with you if you don't. People need to know how derivative fonts differ from the original, and how to take advantage of the changes, or build on them. There are utilities that can help create and maintain a FONTLOG, such as the FONTLOG support in FontForge.
+
+6.4  What should the FONTLOG look like?
+It is typically a separate text file (FONTLOG.txt), but can take other formats. It commonly includes these four sections:
+
+- brief header describing the FONTLOG itself and name of the font family
+- Basic Font Information - description of the font family, purpose and breadth
+- ChangeLog - chronological listing of changes
+- Acknowledgements - list of authors and contributors with contact information
+
+It could also include other sections, such as: where to find documentation, how to make contributions, information on contributing organizations, source code details, and a short design guide. See Appendix A for an example FONTLOG.
+
+
+7  MAKING CONTRIBUTIONS TO OFL PROJECTS
+
+7.1  Can I contribute work to OFL projects?
+In many cases, yes. It is common for OFL fonts to be developed by a team of people who welcome contributions from the wider community. Contact the original authors for specific information on how to participate in their projects.
+
+7.2  Why should I contribute my changes back to the original authors?
+It would benefit many people if you contributed back in response to what you've received. Your contributions and improvements to the fonts and other components could be a tremendous help and would encourage others to contribute as well and 'give back'. You will then benefit from other people's contributions as well. Sometimes maintaining your own separate version takes more effort than merging back with the original. Be aware that any contributions, however, must be either your own original creation or work that you own, and you may be asked to affirm that clearly when you contribute.
+
+7.3  I've made some very nice improvements to the font. Will you consider adopting them and putting them into future Original Versions?
+Most authors would be very happy to receive such contributions. Keep in mind that it is unlikely that they would want to incorporate major changes that would require additional work on their end. Any contributions would likely need to be made for all the fonts in a family and match the overall design and style. Authors are encouraged to include a guide to the design with the fonts. It would also help to have contributions submitted as patches or clearly marked changes - the use of smart source revision control systems like subversion, mercurial, git or bzr is a good idea. Please follow the recommendations given by the author(s) in terms of preferred source formats and configuration parameters for sending contributions. If this is not indicated in a FONTLOG or other documentation of the font, consider asking them directly. Examples of useful contributions are bug fixes, additional glyphs, stylistic alternates (and the smart font code to access them) or improved hinting. Keep in mind that some kinds of changes (esp. hinting) may be technically difficult to integrate.
+
+7.4  How can I financially support the development of OFL fonts?
+It is likely that most authors of OFL fonts would accept financial contributions - contact them for instructions on how to do this. Such contributions would support future development. You can also pay for others to enhance the fonts and contribute the results back to the original authors for inclusion in the Original Version.
+
+
+8  ABOUT THE LICENSE ITSELF
+
+8.1  I see that this is version 1.1 of the license. Will there be later changes?
+Version 1.1 is the first minor revision of the OFL. We are confident that version 1.1 will meet most needs, but are open to future improvements. Any revisions would be for future font releases, and previously existing licenses would remain in effect. No retroactive changes are possible, although the Copyright Holder(s) can re-release the font under a revised OFL. All versions will be available on our web site: http://scripts.sil.org/OFL.
+
+8.2  Does this license restrict the rights of the Copyright Holder(s)?
+No. The Copyright Holder(s) still retain(s) all the rights to their creation; they are only releasing a portion of it for use in a specific way. For example, the Copyright Holder(s) may choose to release a 'basic' version of their font under the OFL, but sell a restricted 'enhanced' version under a different license. They may also choose to release the same font under both the OFL and some other license. Only the Copyright Holder(s) can do this, and doing so does not change the terms of the OFL as it applies to that font.
+
+8.3  Is the OFL a contract or a license?
+The OFL is a worldwide license based on international copyright agreements and conventions. It is not a contract and so does not require you to sign it to have legal validity. By using, modifying and redistributing components under the OFL you indicate that you accept the license.
+
+8.4  I really like the terms of the OFL, but want to change it a little. Am I allowed to take ideas and actual wording from the OFL and put them into my own custom license for distributing my fonts?
+We strongly recommend against creating your very own unique open licensing model. Using a modified or derivative license will likely cut you off - along with the font(s) under that license - from the community of designers using the OFL, potentially expose you and your users to legal liabilities, and possibly put your work and rights at risk. The OFL went though a community and legal review process that took years of effort, and that review is only applicable to an unmodified OFL. The text of the OFL has been written by SIL (with review and consultation from the community) and is copyright (c) 2005-2013 SIL International. You may re-use the ideas and wording (in part, not in whole) in another non-proprietary license provided that you call your license by another unambiguous name, that you do not use the preamble, that you do not mention SIL and that you clearly present your license as different from the OFL so as not to cause confusion by being too similar to the original. If you feel the OFL does not meet your needs for an open license, please contact us.
+
+8.5  Can I translate the license and the FAQ into other languages?
+SIL certainly recognises the need for people who are not familiar with English to be able to understand the OFL and its use. Making the license very clear and readable has been a key goal for the OFL, but we know that people understand their own language best.
+
+If you are an experienced translator, you are very welcome to translate the OFL and OFL-FAQ so that designers and users in your language community can understand the license better. But only the original English version of the license has legal value and has been approved by the community. Translations do not count as legal substitutes and should only serve as a way to explain the original license. SIL - as the author and steward of the license for the community at large - does not approve any translation of the OFL as legally valid because even small translation ambiguities could be abused and create problems.
+
+SIL gives permission to publish unofficial translations into other languages provided that they comply with the following guidelines:
+
+- Put the following disclaimer in both English and the target language stating clearly that the translation is unofficial:
+
+"This is an unofficial translation of the SIL Open Font License into <language_name>. It was not published by SIL International, and does not legally state the distribution terms for fonts that use the OFL. A release under the OFL is only valid when using the original English text. However, we recognize that this unofficial translation will help users and designers not familiar with English to better understand and use the OFL. We encourage designers who consider releasing their creation under the OFL to read the OFL-FAQ in their own language if it is available. Please go to http://scripts.sil.org/OFL for the official version of the license and the accompanying OFL-FAQ."
+
+- Keep your unofficial translation current and update it at our request if needed, for example if there is any ambiguity which could lead to confusion.  
+
+If you start such a unofficial translation effort of the OFL and OFL-FAQ please let us know.
+
+8.6 Does the OFL have an explicit expiration term?
+No, the implicit intent of the OFL is that the permissions granted are perpetual and irrevocable. 
+
+
+9  ABOUT SIL INTERNATIONAL
+
+9.1  Who is SIL International and what do they do?
+SIL serves language communities worldwide, building their capacity for sustainable language development, by means of research, translation, training and materials development. SIL makes its services available to all without regard to religious belief, political ideology, gender, race, or ethnic background. SIL's members and volunteers share a Christian commitment.
+
+9.2  What does this have to do with font licensing?
+The ability to read, write, type and publish in one's own language is one of the most critical needs for millions of people around the world. This requires fonts that are widely available and support lesser-known languages. SIL develops - and encourages others to develop - a complete stack of writing systems implementation components available under open licenses. This open stack includes input methods, smart fonts, smart rendering libraries and smart applications. There has been a need for a common open license that is specifically applicable to fonts and related software (a crucial component of this stack), so SIL developed the SIL Open Font License with the help of the Free/Libre and Open Source Software community.
+
+9.3  How can I contact SIL?
+Our main web site is: http://www.sil.org/
+Our site about complex scripts is: http://scripts.sil.org/
+Information about this license (and contact information) is at: http://scripts.sil.org/OFL
+
+
+APPENDIX A - FONTLOG EXAMPLE
+
+Here is an example of the recommended format for a FONTLOG, although other formats are allowed.
+
+-----
+FONTLOG for the GlobalFontFamily fonts
+
+This file provides detailed information on the GlobalFontFamily Font Software. This information should be distributed along with the GlobalFontFamily fonts and any derivative works.
+
+Basic Font Information
+
+GlobalFontFamily is a Unicode typeface family that supports all languages that use the Latin script and its variants, and could be expanded to support other scripts.
+
+NewWorldFontFamily is based on the GlobalFontFamily and also supports Greek, Hebrew, Cyrillic and Armenian.
+
+More specifically, this release supports the following Unicode ranges...
+This release contains...
+Documentation can be found at...
+To contribute to the project...
+
+ChangeLog
+
+10 December 2010 (Fred Foobar) GlobalFontFamily-devel version 1.4
+- fix new build and testing system (bug #123456)
+
+1 August 2008 (Tom Parker) GlobalFontFamily version 1.2.1
+- Tweaked the smart font code (Branch merged with trunk version)
+- Provided improved build and debugging environment for smart behaviours
+
+7 February 2007 (Pat Johnson) NewWorldFontFamily Version 1.3
+- Added Greek and Cyrillic glyphs
+
+7 March 2006 (Fred Foobar) NewWorldFontFamily Version 1.2
+- Tweaked contextual behaviours
+
+1 Feb 2005 (Jane Doe) NewWorldFontFamily Version 1.1
+- Improved build script performance and verbosity
+- Extended the smart code documentation
+- Corrected minor typos in the documentation
+- Fixed position of combining inverted breve below (U+032F)
+- Added OpenType/Graphite smart code for Armenian
+- Added Armenian glyphs (U+0531 -> U+0587) 
+- Released as "NewWorldFontFamily"
+
+1 Jan 2005 (Joe Smith) GlobalFontFamily Version 1.0
+- Initial release
+
+Acknowledgements
+
+If you make modifications be sure to add your name (N), email (E), web-address (if you have one) (W) and description (D). This list is in alphabetical order.
+
+N: Jane Doe
+E: jane@university.edu
+W: http://art.university.edu/projects/fonts
+D: Contributor - Armenian glyphs and code
+
+N: Fred Foobar
+E: fred@foobar.org
+W: http://foobar.org
+D: Contributor - misc Graphite fixes
+
+N: Pat Johnson
+E: pat@fontstudio.org
+W: http://pat.fontstudio.org
+D: Designer - Greek & Cyrillic glyphs based on Roman design
+
+N: Tom Parker
+E: tom@company.com
+W: http://www.company.com/tom/projects/fonts
+D: Engineer - original smart font code
+
+N: Joe Smith
+E: joe@fontstudio.org
+W: http://joe.fontstudio.org
+D: Designer - original Roman glyphs
+
+Fontstudio.org is an not-for-profit design group whose purpose is...
+Foobar.org is a distributed community of developers...
+Company.com is a small business who likes to support community designers...
+University.edu is a renowned educational institution with a strong design department...
+-----
+
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclick-1.0.6.js b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclick-1.0.6.js
new file mode 100644
index 0000000..a723f22
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclick-1.0.6.js
@@ -0,0 +1,867 @@
+;(function () {
+  'use strict';
+
+  /* BSI Changes:
+   * - Synthesize mouse down and mouse up events as well
+   * - Make content editable elements work
+   *
+   * To find the changes in the code, look for ==== MODIFIED
+   */
+
+  /**
+   * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
+   *
+   * @codingstandard ftlabs-jsv2
+   * @copyright The Financial Times Limited [All Rights Reserved]
+   * @license MIT License (see LICENSE.txt)
+   */
+
+  /*jslint browser:true, node:true*/
+  /*global define, Event, Node*/
+
+
+  /**
+   * Instantiate fast-clicking listeners on the specified layer.
+   *
+   * @constructor
+   * @param {Element} layer The layer to listen on
+   * @param {Object} [options={}] The options to override the defaults
+   */
+  function FastClick(layer, options) {
+    var oldOnClick;
+
+    options = options || {};
+
+    /**
+     * Whether a click is currently being tracked.
+     *
+     * @type boolean
+     */
+    this.trackingClick = false;
+
+
+    /**
+     * Timestamp for when click tracking started.
+     *
+     * @type number
+     */
+    this.trackingClickStart = 0;
+
+
+    /**
+     * The element being tracked for a click.
+     *
+     * @type EventTarget
+     */
+    this.targetElement = null;
+
+
+    /**
+     * X-coordinate of touch start event.
+     *
+     * @type number
+     */
+    this.touchStartX = 0;
+
+
+    /**
+     * Y-coordinate of touch start event.
+     *
+     * @type number
+     */
+    this.touchStartY = 0;
+
+
+    /**
+     * ID of the last touch, retrieved from Touch.identifier.
+     *
+     * @type number
+     */
+    this.lastTouchIdentifier = 0;
+
+
+    /**
+     * Touchmove boundary, beyond which a click will be cancelled.
+     *
+     * @type number
+     */
+    this.touchBoundary = options.touchBoundary || 10;
+
+
+    /**
+     * The FastClick layer.
+     *
+     * @type Element
+     */
+    this.layer = layer;
+
+    /**
+     * The minimum time between tap(touchstart and touchend) events
+     *
+     * @type number
+     */
+    this.tapDelay = options.tapDelay || 200;
+
+    /**
+     * The maximum time for a tap
+     *
+     * @type number
+     */
+    this.tapTimeout = options.tapTimeout || 700;
+
+    if (FastClick.notNeeded(layer)) {
+      return;
+    }
+
+    // Some old versions of Android don't have Function.prototype.bind
+    function bind(method, context) {
+      return function() { return method.apply(context, arguments); };
+    }
+
+
+    var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
+    var context = this;
+    for (var i = 0, l = methods.length; i < l; i++) {
+      context[methods[i]] = bind(context[methods[i]], context);
+    }
+
+    // Set up event handlers as required
+    if (deviceIsAndroid) {
+      layer.addEventListener('mouseover', this.onMouse, true);
+      layer.addEventListener('mousedown', this.onMouse, true);
+      layer.addEventListener('mouseup', this.onMouse, true);
+    }
+
+    layer.addEventListener('click', this.onClick, true);
+    layer.addEventListener('touchstart', this.onTouchStart, false);
+    layer.addEventListener('touchmove', this.onTouchMove, false);
+    layer.addEventListener('touchend', this.onTouchEnd, false);
+    layer.addEventListener('touchcancel', this.onTouchCancel, false);
+
+    // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+    // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
+    // layer when they are cancelled.
+    if (!Event.prototype.stopImmediatePropagation) {
+      layer.removeEventListener = function(type, callback, capture) {
+        var rmv = Node.prototype.removeEventListener;
+        if (type === 'click') {
+          rmv.call(layer, type, callback.hijacked || callback, capture);
+        } else {
+          rmv.call(layer, type, callback, capture);
+        }
+      };
+
+      layer.addEventListener = function(type, callback, capture) {
+        var adv = Node.prototype.addEventListener;
+        if (type === 'click') {
+          adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
+            if (!event.propagationStopped) {
+              callback(event);
+            }
+          }), capture);
+        } else {
+          adv.call(layer, type, callback, capture);
+        }
+      };
+    }
+
+    // If a handler is already declared in the element's onclick attribute, it will be fired before
+    // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
+    // adding it as listener.
+    if (typeof layer.onclick === 'function') {
+
+      // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
+      // - the old one won't work if passed to addEventListener directly.
+      oldOnClick = layer.onclick;
+      layer.addEventListener('click', function(event) {
+        oldOnClick(event);
+      }, false);
+      layer.onclick = null;
+    }
+  }
+
+  /**
+  * Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
+  *
+  * @type boolean
+  */
+  var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
+
+  /**
+   * Android requires exceptions.
+   *
+   * @type boolean
+   */
+  var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;
+
+
+  /**
+   * iOS requires exceptions.
+   *
+   * @type boolean
+   */
+  var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
+
+
+  /**
+   * iOS 4 requires an exception for select elements.
+   *
+   * @type boolean
+   */
+  var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
+
+
+  /**
+   * iOS 6.0-7.* requires the target element to be manually derived
+   *
+   * @type boolean
+   */
+  var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);
+
+  /**
+   * BlackBerry requires exceptions.
+   *
+   * @type boolean
+   */
+  var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;
+
+  /**
+   * Determine whether a given element requires a native click.
+   *
+   * @param {EventTarget|Element} target Target DOM element
+   * @returns {boolean} Returns true if the element needs a native click
+   */
+  FastClick.prototype.needsClick = function(target) {
+    switch (target.nodeName.toLowerCase()) {
+
+    // Don't send a synthetic click to disabled inputs (issue #62)
+    case 'button':
+    case 'select':
+    case 'textarea':
+      if (target.disabled) {
+        return true;
+      }
+
+      break;
+    case 'input':
+
+      // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
+      if ((deviceIsIOS && target.type === 'file') || target.disabled) {
+        return true;
+      }
+
+      break;
+    case 'label':
+    case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
+    case 'video':
+      return true;
+    }
+
+    return (/\bneedsclick\b/).test(target.className);
+  };
+
+
+  /**
+   * Determine whether a given element requires a call to focus to simulate click into element.
+   *
+   * @param {EventTarget|Element} target Target DOM element
+   * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
+   */
+  FastClick.prototype.needsFocus = function(target) {
+    switch (target.nodeName.toLowerCase()) {
+    case 'textarea':
+      return true;
+    case 'select':
+      return !deviceIsAndroid;
+    case 'input':
+      switch (target.type) {
+      case 'button':
+      case 'checkbox':
+      case 'file':
+      case 'image':
+      case 'radio':
+      case 'submit':
+        return false;
+      }
+
+      // No point in attempting to focus disabled inputs
+      return !target.disabled && !target.readOnly;
+    default:
+      return (/\bneedsfocus\b/).test(target.className);
+    }
+  };
+
+
+  /**
+   * Send a click event to the specified element.
+   *
+   * @param {EventTarget|Element} targetElement
+   * @param {Event} event
+   */
+  FastClick.prototype.sendClick = function(targetElement, event) {
+    var clickEvent, touch;
+
+    // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
+    if (document.activeElement && document.activeElement !== targetElement) {
+      document.activeElement.blur();
+    }
+
+    touch = event.changedTouches[0];
+
+    // ==== MODIFIED
+    // Synthesise a click event, with an extra attribute so it can be tracked
+    clickEvent = document.createEvent('MouseEvents');
+    clickEvent.initMouseEvent('mousedown', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
+    clickEvent.forwardedTouchEvent = true;
+    targetElement.dispatchEvent(clickEvent);
+
+    clickEvent = document.createEvent('MouseEvents');
+    clickEvent.initMouseEvent('mouseup', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
+    clickEvent.forwardedTouchEvent = true;
+    targetElement.dispatchEvent(clickEvent);
+    // ==== MODIFIED
+
+    clickEvent = document.createEvent('MouseEvents');
+    clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
+    clickEvent.forwardedTouchEvent = true;
+    targetElement.dispatchEvent(clickEvent);
+  };
+
+  FastClick.prototype.determineEventType = function(targetElement) {
+
+    //Issue #159: Android Chrome Select Box does not open with a synthetic click event
+    if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
+      return 'mousedown';
+    }
+
+    return 'click';
+  };
+
+
+  /**
+   * @param {EventTarget|Element} targetElement
+   */
+  FastClick.prototype.focus = function(targetElement) {
+    var length;
+
+    // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
+    if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
+      length = targetElement.value.length;
+      targetElement.setSelectionRange(length, length);
+    } else {
+      targetElement.focus();
+    }
+  };
+
+
+  /**
+   * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
+   *
+   * @param {EventTarget|Element} targetElement
+   */
+  FastClick.prototype.updateScrollParent = function(targetElement) {
+    var scrollParent, parentElement;
+
+    scrollParent = targetElement.fastClickScrollParent;
+
+    // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
+    // target element was moved to another parent.
+    if (!scrollParent || !scrollParent.contains(targetElement)) {
+      parentElement = targetElement;
+      do {
+        if (parentElement.scrollHeight > parentElement.offsetHeight) {
+          scrollParent = parentElement;
+          targetElement.fastClickScrollParent = parentElement;
+          break;
+        }
+
+        parentElement = parentElement.parentElement;
+      } while (parentElement);
+    }
+
+    // Always update the scroll top tracker if possible.
+    if (scrollParent) {
+      scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
+    }
+  };
+
+
+  /**
+   * @param {EventTarget} targetElement
+   * @returns {Element|EventTarget}
+   */
+  FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
+
+    // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
+    if (eventTarget.nodeType === Node.TEXT_NODE) {
+      return eventTarget.parentNode;
+    }
+
+    return eventTarget;
+  };
+
+
+  /**
+   * On touch start, record the position and scroll offset.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.onTouchStart = function(event) {
+    var targetElement, touch, selection;
+
+    // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
+    if (event.targetTouches.length > 1) {
+      return true;
+    }
+
+    targetElement = this.getTargetElementFromEventTarget(event.target);
+    touch = event.targetTouches[0];
+
+    // ==== MODIFIED
+    // Ignore touch on content editable elements to make them work as expected
+    if (targetElement.isContentEditable) {
+      return true;
+    }
+    // ==== MODIFIED
+
+    if (deviceIsIOS) {
+
+      // Only trusted events will deselect text on iOS (issue #49)
+      selection = window.getSelection();
+      if (selection.rangeCount && !selection.isCollapsed) {
+        return true;
+      }
+
+      if (!deviceIsIOS4) {
+
+        // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
+        // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
+        // with the same identifier as the touch event that previously triggered the click that triggered the alert.
+        // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
+        // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
+        // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
+        // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
+        // random integers, it's safe to to continue if the identifier is 0 here.
+        if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
+          event.preventDefault();
+          return false;
+        }
+
+        this.lastTouchIdentifier = touch.identifier;
+
+        // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
+        // 1) the user does a fling scroll on the scrollable layer
+        // 2) the user stops the fling scroll with another tap
+        // then the event.target of the last 'touchend' event will be the element that was under the user's finger
+        // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
+        // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
+        this.updateScrollParent(targetElement);
+      }
+    }
+
+    this.trackingClick = true;
+    this.trackingClickStart = event.timeStamp;
+    this.targetElement = targetElement;
+
+    this.touchStartX = touch.pageX;
+    this.touchStartY = touch.pageY;
+
+    // Prevent phantom clicks on fast double-tap (issue #36)
+    if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+      event.preventDefault();
+    }
+
+    return true;
+  };
+
+
+  /**
+   * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.touchHasMoved = function(event) {
+    var touch = event.changedTouches[0], boundary = this.touchBoundary;
+
+    if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
+      return true;
+    }
+
+    return false;
+  };
+
+
+  /**
+   * Update the last position.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.onTouchMove = function(event) {
+    if (!this.trackingClick) {
+      return true;
+    }
+
+    // If the touch has moved, cancel the click tracking
+    if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
+      this.trackingClick = false;
+      this.targetElement = null;
+    }
+
+    return true;
+  };
+
+
+  /**
+   * Attempt to find the labelled control for the given label element.
+   *
+   * @param {EventTarget|HTMLLabelElement} labelElement
+   * @returns {Element|null}
+   */
+  FastClick.prototype.findControl = function(labelElement) {
+
+    // Fast path for newer browsers supporting the HTML5 control attribute
+    if (labelElement.control !== undefined) {
+      return labelElement.control;
+    }
+
+    // All browsers under test that support touch events also support the HTML5 htmlFor attribute
+    if (labelElement.htmlFor) {
+      return document.getElementById(labelElement.htmlFor);
+    }
+
+    // If no for attribute exists, attempt to retrieve the first labellable descendant element
+    // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
+    return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
+  };
+
+
+  /**
+   * On touch end, determine whether to send a click event at once.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.onTouchEnd = function(event) {
+    var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
+
+    if (!this.trackingClick) {
+      return true;
+    }
+
+    // Prevent phantom clicks on fast double-tap (issue #36)
+    if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+      this.cancelNextClick = true;
+      return true;
+    }
+
+    if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
+      return true;
+    }
+
+    // Reset to prevent wrong click cancel on input (issue #156).
+    this.cancelNextClick = false;
+
+    this.lastClickTime = event.timeStamp;
+
+    trackingClickStart = this.trackingClickStart;
+    this.trackingClick = false;
+    this.trackingClickStart = 0;
+
+    // On some iOS devices, the targetElement supplied with the event is invalid if the layer
+    // is performing a transition or scroll, and has to be re-detected manually. Note that
+    // for this to function correctly, it must be called *after* the event target is checked!
+    // See issue #57; also filed as rdar://13048589 .
+    if (deviceIsIOSWithBadTarget) {
+      touch = event.changedTouches[0];
+
+      // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
+      targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
+      targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
+    }
+
+    targetTagName = targetElement.tagName.toLowerCase();
+    if (targetTagName === 'label') {
+      forElement = this.findControl(targetElement);
+      if (forElement) {
+        this.focus(targetElement);
+        if (deviceIsAndroid) {
+          return false;
+        }
+
+        targetElement = forElement;
+      }
+    } else if (this.needsFocus(targetElement)) {
+
+      // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
+      // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
+      if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
+        this.targetElement = null;
+        return false;
+      }
+
+      this.focus(targetElement);
+      this.sendClick(targetElement, event);
+
+      // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
+      // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
+      if (!deviceIsIOS || targetTagName !== 'select') {
+        this.targetElement = null;
+        event.preventDefault();
+      }
+
+      return false;
+    }
+
+    if (deviceIsIOS && !deviceIsIOS4) {
+
+      // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
+      // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
+      scrollParent = targetElement.fastClickScrollParent;
+      if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
+        return true;
+      }
+    }
+
+    // Prevent the actual click from going though - unless the target node is marked as requiring
+    // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
+    if (!this.needsClick(targetElement)) {
+      event.preventDefault();
+      this.sendClick(targetElement, event);
+    }
+
+    return false;
+  };
+
+
+  /**
+   * On touch cancel, stop tracking the click.
+   *
+   * @returns {void}
+   */
+  FastClick.prototype.onTouchCancel = function() {
+    this.trackingClick = false;
+    this.targetElement = null;
+  };
+
+
+  /**
+   * Determine mouse events which should be permitted.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.onMouse = function(event) {
+
+    // If a target element was never set (because a touch event was never fired) allow the event
+    if (!this.targetElement) {
+      return true;
+    }
+
+    if (event.forwardedTouchEvent) {
+      return true;
+    }
+
+    // Programmatically generated events targeting a specific element should be permitted
+    if (!event.cancelable) {
+      return true;
+    }
+
+    // Derive and check the target element to see whether the mouse event needs to be permitted;
+    // unless explicitly enabled, prevent non-touch click events from triggering actions,
+    // to prevent ghost/doubleclicks.
+    if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
+
+      // Prevent any user-added listeners declared on FastClick element from being fired.
+      if (event.stopImmediatePropagation) {
+        event.stopImmediatePropagation();
+      } else {
+
+        // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+        event.propagationStopped = true;
+      }
+
+      // Cancel the event
+      event.stopPropagation();
+      event.preventDefault();
+
+      return false;
+    }
+
+    // If the mouse event is permitted, return true for the action to go through.
+    return true;
+  };
+
+
+  /**
+   * On actual clicks, determine whether this is a touch-generated click, a click action occurring
+   * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
+   * an actual click which should be permitted.
+   *
+   * @param {Event} event
+   * @returns {boolean}
+   */
+  FastClick.prototype.onClick = function(event) {
+    var permitted;
+
+    // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
+    if (this.trackingClick) {
+      this.targetElement = null;
+      this.trackingClick = false;
+      return true;
+    }
+
+    // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
+    if (event.target.type === 'submit' && event.detail === 0) {
+      return true;
+    }
+
+    permitted = this.onMouse(event);
+
+    // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
+    if (!permitted) {
+      this.targetElement = null;
+    }
+
+    // If clicks are permitted, return true for the action to go through.
+    return permitted;
+  };
+
+
+  /**
+   * Remove all FastClick's event listeners.
+   *
+   * @returns {void}
+   */
+  FastClick.prototype.destroy = function() {
+    var layer = this.layer;
+
+    if (deviceIsAndroid) {
+      layer.removeEventListener('mouseover', this.onMouse, true);
+      layer.removeEventListener('mousedown', this.onMouse, true);
+      layer.removeEventListener('mouseup', this.onMouse, true);
+    }
+
+    layer.removeEventListener('click', this.onClick, true);
+    layer.removeEventListener('touchstart', this.onTouchStart, false);
+    layer.removeEventListener('touchmove', this.onTouchMove, false);
+    layer.removeEventListener('touchend', this.onTouchEnd, false);
+    layer.removeEventListener('touchcancel', this.onTouchCancel, false);
+  };
+
+
+  /**
+   * Check whether FastClick is needed.
+   *
+   * @param {Element} layer The layer to listen on
+   */
+  FastClick.notNeeded = function(layer) {
+    var metaViewport;
+    var chromeVersion;
+    var blackberryVersion;
+    var firefoxVersion;
+
+    // Devices that don't support touch don't need FastClick
+    if (typeof window.ontouchstart === 'undefined') {
+      return true;
+    }
+
+    // Chrome version - zero for other browsers
+    chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
+
+    if (chromeVersion) {
+
+      if (deviceIsAndroid) {
+        metaViewport = document.querySelector('meta[name=viewport]');
+
+        if (metaViewport) {
+          // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
+          if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
+            return true;
+          }
+          // Chrome 32 and above with width=device-width or less don't need FastClick
+          if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
+            return true;
+          }
+        }
+
+      // Chrome desktop doesn't need FastClick (issue #15)
+      } else {
+        return true;
+      }
+    }
+
+    if (deviceIsBlackBerry10) {
+      blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
+
+      // BlackBerry 10.3+ does not require Fastclick library.
+      // https://github.com/ftlabs/fastclick/issues/251
+      if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
+        metaViewport = document.querySelector('meta[name=viewport]');
+
+        if (metaViewport) {
+          // user-scalable=no eliminates click delay.
+          if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
+            return true;
+          }
+          // width=device-width (or less than device-width) eliminates click delay.
+          if (document.documentElement.scrollWidth <= window.outerWidth) {
+            return true;
+          }
+        }
+      }
+    }
+
+    // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
+    if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
+      return true;
+    }
+
+    // Firefox version - zero for other browsers
+    firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
+
+    if (firefoxVersion >= 27) {
+      // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896
+
+      metaViewport = document.querySelector('meta[name=viewport]');
+      if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
+        return true;
+      }
+    }
+
+    // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
+    // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
+    if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
+      return true;
+    }
+
+    return false;
+  };
+
+
+  /**
+   * Factory method for creating a FastClick object
+   *
+   * @param {Element} layer The layer to listen on
+   * @param {Object} [options={}] The options to override the defaults
+   */
+  FastClick.attach = function(layer, options) {
+    return new FastClick(layer, options);
+  };
+
+
+  if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
+
+    // AMD. Register as an anonymous module.
+    define(function() {
+      return FastClick;
+    });
+  } else if (typeof module !== 'undefined' && module.exports) {
+    module.exports = FastClick.attach;
+    module.exports.FastClick = FastClick;
+  } else {
+    window.FastClick = FastClick;
+  }
+}());
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclickmod-1.0.1.js b/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclickmod-1.0.1.js
deleted file mode 100644
index 900a9d6..0000000
--- a/org.eclipse.scout.rt.ui.html/src/main/resources/WebContent/res/fastclickmod-1.0.1.js
+++ /dev/null
@@ -1,802 +0,0 @@
-/**
- * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
- *
- * @version 1.0.1
- * @codingstandard ftlabs-jsv2
- * @copyright The Financial Times Limited [All Rights Reserved]
- * @license MIT License (see LICENSE.txt)
- */
-
-/*jslint browser:true, node:true*/
-/*global define, Event, Node*/
-
-
-/**
- * Instantiate fast-clicking listeners on the specified layer.
- *
- * @constructor
- * @param {Element} layer The layer to listen on
- * @param {Object} options The options to override the defaults
- */
-function FastClick(layer, options) {
-  'use strict';
-  var oldOnClick;
-
-  options = options || {};
-
-  /**
-   * Whether a click is currently being tracked.
-   *
-   * @type boolean
-   */
-  this.trackingClick = false;
-
-
-  /**
-   * Timestamp for when click tracking started.
-   *
-   * @type number
-   */
-  this.trackingClickStart = 0;
-
-
-  /**
-   * The element being tracked for a click.
-   *
-   * @type EventTarget
-   */
-  this.targetElement = null;
-
-
-  /**
-   * X-coordinate of touch start event.
-   *
-   * @type number
-   */
-  this.touchStartX = 0;
-
-
-  /**
-   * Y-coordinate of touch start event.
-   *
-   * @type number
-   */
-  this.touchStartY = 0;
-
-
-  /**
-   * ID of the last touch, retrieved from Touch.identifier.
-   *
-   * @type number
-   */
-  this.lastTouchIdentifier = 0;
-
-
-  /**
-   * Touchmove boundary, beyond which a click will be cancelled.
-   *
-   * @type number
-   */
-  this.touchBoundary = options.touchBoundary || 10;
-
-
-  /**
-   * The FastClick layer.
-   *
-   * @type Element
-   */
-  this.layer = layer;
-
-  /**
-   * The minimum time between tap(touchstart and touchend) events
-   *
-   * @type number
-   */
-  this.tapDelay = options.tapDelay || 200;
-
-  if (FastClick.notNeeded(layer)) {
-    return;
-  }
-
-  // Some old versions of Android don't have Function.prototype.bind
-  function bind(method, context) {
-    return function() { return method.apply(context, arguments); };
-  }
-
-
-  var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
-  var context = this;
-  for (var i = 0, l = methods.length; i < l; i++) {
-    context[methods[i]] = bind(context[methods[i]], context);
-  }
-
-  // Set up event handlers as required
-  if (deviceIsAndroid) {
-    layer.addEventListener('mouseover', this.onMouse, true);
-    layer.addEventListener('mousedown', this.onMouse, true);
-    layer.addEventListener('mouseup', this.onMouse, true);
-  }
-
-  layer.addEventListener('click', this.onClick, true);
-  layer.addEventListener('touchstart', this.onTouchStart, false);
-  layer.addEventListener('touchmove', this.onTouchMove, false);
-  layer.addEventListener('touchend', this.onTouchEnd, false);
-  layer.addEventListener('touchcancel', this.onTouchCancel, false);
-
-  // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
-  // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
-  // layer when they are cancelled.
-  if (!Event.prototype.stopImmediatePropagation) {
-    layer.removeEventListener = function(type, callback, capture) {
-      var rmv = Node.prototype.removeEventListener;
-      if (type === 'click') {
-        rmv.call(layer, type, callback.hijacked || callback, capture);
-      } else {
-        rmv.call(layer, type, callback, capture);
-      }
-    };
-
-    layer.addEventListener = function(type, callback, capture) {
-      var adv = Node.prototype.addEventListener;
-      if (type === 'click') {
-        adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
-          if (!event.propagationStopped) {
-            callback(event);
-          }
-        }), capture);
-      } else {
-        adv.call(layer, type, callback, capture);
-      }
-    };
-  }
-
-  // If a handler is already declared in the element's onclick attribute, it will be fired before
-  // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
-  // adding it as listener.
-  if (typeof layer.onclick === 'function') {
-
-    // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
-    // - the old one won't work if passed to addEventListener directly.
-    oldOnClick = layer.onclick;
-    layer.addEventListener('click', function(event) {
-      oldOnClick(event);
-    }, false);
-    layer.onclick = null;
-  }
-}
-
-
-/**
- * Android requires exceptions.
- *
- * @type boolean
- */
-var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0;
-
-
-/**
- * iOS requires exceptions.
- *
- * @type boolean
- */
-var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent);
-
-
-/**
- * iOS 4 requires an exception for select elements.
- *
- * @type boolean
- */
-var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
-
-
-/**
- * iOS 6.0(+?) requires the target element to be manually derived
- *
- * @type boolean
- */
-var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS ([6-9]|\d{2})_\d/).test(navigator.userAgent);
-
-
-/**
- * Determine whether a given element requires a native click.
- *
- * @param {EventTarget|Element} target Target DOM element
- * @returns {boolean} Returns true if the element needs a native click
- */
-FastClick.prototype.needsClick = function(target) {
-  'use strict';
-  switch (target.nodeName.toLowerCase()) {
-
-  // Don't send a synthetic click to disabled inputs (issue #62)
-  case 'button':
-  case 'select':
-  case 'textarea':
-    if (target.disabled) {
-      return true;
-    }
-
-    break;
-  case 'input':
-
-    // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
-    if ((deviceIsIOS && target.type === 'file') || target.disabled) {
-      return true;
-    }
-
-    break;
-  case 'label':
-  case 'video':
-    return true;
-  }
-
-  return (/\bneedsclick\b/).test(target.className);
-};
-
-
-/**
- * Determine whether a given element requires a call to focus to simulate click into element.
- *
- * @param {EventTarget|Element} target Target DOM element
- * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
- */
-FastClick.prototype.needsFocus = function(target) {
-  'use strict';
-  switch (target.nodeName.toLowerCase()) {
-  case 'textarea':
-    return true;
-  case 'select':
-    return !deviceIsAndroid;
-  case 'input':
-    switch (target.type) {
-    case 'button':
-    case 'checkbox':
-    case 'file':
-    case 'image':
-    case 'radio':
-    case 'submit':
-      return false;
-    }
-
-    // No point in attempting to focus disabled inputs
-    return !target.disabled && !target.readOnly;
-  default:
-    return (/\bneedsfocus\b/).test(target.className);
-  }
-};
-
-
-/**
- * Send a click event to the specified element.
- *
- * @param {EventTarget|Element} targetElement
- * @param {Event} event
- */
-FastClick.prototype.sendClick = function(targetElement, event) {
-  'use strict';
-  var clickEvent, touch;
-
-  // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
-  if (document.activeElement && document.activeElement !== targetElement) {
-    document.activeElement.blur();
-  }
-
-  touch = event.changedTouches[0];
-
-  // Synthesise a click event, with an extra attribute so it can be tracked
-  // ==== MODIFIED
-  clickEvent = document.createEvent('MouseEvents');
-  clickEvent.initMouseEvent('mousedown', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
-  clickEvent.forwardedTouchEvent = true;
-  targetElement.dispatchEvent(clickEvent);
-
-  clickEvent = document.createEvent('MouseEvents');
-  clickEvent.initMouseEvent('mouseup', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
-  clickEvent.forwardedTouchEvent = true;
-  targetElement.dispatchEvent(clickEvent);
-  // ==== MODIFIED
-
-  clickEvent = document.createEvent('MouseEvents');
-  clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
-  clickEvent.forwardedTouchEvent = true;
-  targetElement.dispatchEvent(clickEvent);
-};
-
-FastClick.prototype.determineEventType = function(targetElement) {
-  'use strict';
-
-  //Issue #159: Android Chrome Select Box does not open with a synthetic click event
-  if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
-    return 'mousedown';
-  }
-
-  return 'click';
-};
-
-
-/**
- * @param {EventTarget|Element} targetElement
- */
-FastClick.prototype.focus = function(targetElement) {
-  'use strict';
-  var length;
-
-  // Issue #160: on iOS 7, some input elements (e.g. date datetime) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
-  if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time') {
-    length = targetElement.value.length;
-    targetElement.setSelectionRange(length, length);
-  } else {
-    targetElement.focus();
-  }
-};
-
-
-/**
- * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
- *
- * @param {EventTarget|Element} targetElement
- */
-FastClick.prototype.updateScrollParent = function(targetElement) {
-  'use strict';
-  var scrollParent, parentElement;
-
-  scrollParent = targetElement.fastClickScrollParent;
-
-  // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
-  // target element was moved to another parent.
-  if (!scrollParent || !scrollParent.contains(targetElement)) {
-    parentElement = targetElement;
-    do {
-      if (parentElement.scrollHeight > parentElement.offsetHeight) {
-        scrollParent = parentElement;
-        targetElement.fastClickScrollParent = parentElement;
-        break;
-      }
-
-      parentElement = parentElement.parentElement;
-    } while (parentElement);
-  }
-
-  // Always update the scroll top tracker if possible.
-  if (scrollParent) {
-    scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
-  }
-};
-
-
-/**
- * @param {EventTarget} targetElement
- * @returns {Element|EventTarget}
- */
-FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
-  'use strict';
-
-  // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
-  if (eventTarget.nodeType === Node.TEXT_NODE) {
-    return eventTarget.parentNode;
-  }
-
-  return eventTarget;
-};
-
-
-/**
- * On touch start, record the position and scroll offset.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.onTouchStart = function(event) {
-  'use strict';
-  var targetElement, touch, selection;
-
-  // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
-  if (event.targetTouches.length > 1) {
-    return true;
-  }
-
-  targetElement = this.getTargetElementFromEventTarget(event.target);
-  touch = event.targetTouches[0];
-
-  if (deviceIsIOS) {
-
-    // Only trusted events will deselect text on iOS (issue #49)
-    selection = window.getSelection();
-    if (selection.rangeCount && !selection.isCollapsed) {
-      return true;
-    }
-
-    if (!deviceIsIOS4) {
-
-      // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
-      // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
-      // with the same identifier as the touch event that previously triggered the click that triggered the alert.
-      // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
-      // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
-      if (touch.identifier === this.lastTouchIdentifier) {
-        event.preventDefault();
-        return false;
-      }
-
-      this.lastTouchIdentifier = touch.identifier;
-
-      // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
-      // 1) the user does a fling scroll on the scrollable layer
-      // 2) the user stops the fling scroll with another tap
-      // then the event.target of the last 'touchend' event will be the element that was under the user's finger
-      // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
-      // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
-      this.updateScrollParent(targetElement);
-    }
-  }
-
-  this.trackingClick = true;
-  this.trackingClickStart = event.timeStamp;
-  this.targetElement = targetElement;
-
-  this.touchStartX = touch.pageX;
-  this.touchStartY = touch.pageY;
-
-  // Prevent phantom clicks on fast double-tap (issue #36)
-  if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
-    event.preventDefault();
-  }
-
-  return true;
-};
-
-
-/**
- * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.touchHasMoved = function(event) {
-  'use strict';
-  var touch = event.changedTouches[0], boundary = this.touchBoundary;
-
-  if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
-    return true;
-  }
-
-  return false;
-};
-
-
-/**
- * Update the last position.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.onTouchMove = function(event) {
-  'use strict';
-  if (!this.trackingClick) {
-    return true;
-  }
-
-  // If the touch has moved, cancel the click tracking
-  if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
-    this.trackingClick = false;
-    this.targetElement = null;
-  }
-
-  return true;
-};
-
-
-/**
- * Attempt to find the labelled control for the given label element.
- *
- * @param {EventTarget|HTMLLabelElement} labelElement
- * @returns {Element|null}
- */
-FastClick.prototype.findControl = function(labelElement) {
-  'use strict';
-
-  // Fast path for newer browsers supporting the HTML5 control attribute
-  if (labelElement.control !== undefined) {
-    return labelElement.control;
-  }
-
-  // All browsers under test that support touch events also support the HTML5 htmlFor attribute
-  if (labelElement.htmlFor) {
-    return document.getElementById(labelElement.htmlFor);
-  }
-
-  // If no for attribute exists, attempt to retrieve the first labellable descendant element
-  // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
-  return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
-};
-
-
-/**
- * On touch end, determine whether to send a click event at once.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.onTouchEnd = function(event) {
-  'use strict';
-  var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
-
-  if (!this.trackingClick) {
-    return true;
-  }
-
-  // Prevent phantom clicks on fast double-tap (issue #36)
-  if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
-    this.cancelNextClick = true;
-    return true;
-  }
-
-  // Reset to prevent wrong click cancel on input (issue #156).
-  this.cancelNextClick = false;
-
-  this.lastClickTime = event.timeStamp;
-
-  trackingClickStart = this.trackingClickStart;
-  this.trackingClick = false;
-  this.trackingClickStart = 0;
-
-  // On some iOS devices, the targetElement supplied with the event is invalid if the layer
-  // is performing a transition or scroll, and has to be re-detected manually. Note that
-  // for this to function correctly, it must be called *after* the event target is checked!
-  // See issue #57; also filed as rdar://13048589 .
-  if (deviceIsIOSWithBadTarget) {
-    touch = event.changedTouches[0];
-
-    // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
-    targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
-    targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
-  }
-
-  targetTagName = targetElement.tagName.toLowerCase();
-  if (targetTagName === 'label') {
-    forElement = this.findControl(targetElement);
-    if (forElement) {
-      this.focus(targetElement);
-      if (deviceIsAndroid) {
-        return false;
-      }
-
-      targetElement = forElement;
-    }
-  } else if (this.needsFocus(targetElement)) {
-
-    // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
-    // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
-    if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
-      this.targetElement = null;
-      return false;
-    }
-
-    this.focus(targetElement);
-    this.sendClick(targetElement, event);
-
-    // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
-    // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
-    if (!deviceIsIOS || targetTagName !== 'select') {
-      this.targetElement = null;
-      event.preventDefault();
-    }
-
-    return false;
-  }
-
-  if (deviceIsIOS && !deviceIsIOS4) {
-
-    // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
-    // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
-    scrollParent = targetElement.fastClickScrollParent;
-    if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
-      return true;
-    }
-  }
-
-  // Prevent the actual click from going though - unless the target node is marked as requiring
-  // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
-  if (!this.needsClick(targetElement)) {
-    event.preventDefault();
-    this.sendClick(targetElement, event);
-  }
-
-  return false;
-};
-
-
-/**
- * On touch cancel, stop tracking the click.
- *
- * @returns {void}
- */
-FastClick.prototype.onTouchCancel = function() {
-  'use strict';
-  this.trackingClick = false;
-  this.targetElement = null;
-};
-
-
-/**
- * Determine mouse events which should be permitted.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.onMouse = function(event) {
-  'use strict';
-
-  // If a target element was never set (because a touch event was never fired) allow the event
-  if (!this.targetElement) {
-    return true;
-  }
-
-  if (event.forwardedTouchEvent) {
-    return true;
-  }
-
-  // Programmatically generated events targeting a specific element should be permitted
-  if (!event.cancelable) {
-    return true;
-  }
-
-  // Derive and check the target element to see whether the mouse event needs to be permitted;
-  // unless explicitly enabled, prevent non-touch click events from triggering actions,
-  // to prevent ghost/doubleclicks.
-  if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
-
-    // Prevent any user-added listeners declared on FastClick element from being fired.
-    if (event.stopImmediatePropagation) {
-      event.stopImmediatePropagation();
-    } else {
-
-      // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
-      event.propagationStopped = true;
-    }
-
-    // Cancel the event
-    event.stopPropagation();
-    event.preventDefault();
-
-    return false;
-  }
-
-  // If the mouse event is permitted, return true for the action to go through.
-  return true;
-};
-
-
-/**
- * On actual clicks, determine whether this is a touch-generated click, a click action occurring
- * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
- * an actual click which should be permitted.
- *
- * @param {Event} event
- * @returns {boolean}
- */
-FastClick.prototype.onClick = function(event) {
-  'use strict';
-  var permitted;
-
-  // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
-  if (this.trackingClick) {
-    this.targetElement = null;
-    this.trackingClick = false;
-    return true;
-  }
-
-  // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
-  if (event.target.type === 'submit' && event.detail === 0) {
-    return true;
-  }
-
-  permitted = this.onMouse(event);
-
-  // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
-  if (!permitted) {
-    this.targetElement = null;
-  }
-
-  // If clicks are permitted, return true for the action to go through.
-  return permitted;
-};
-
-
-/**
- * Remove all FastClick's event listeners.
- *
- * @returns {void}
- */
-FastClick.prototype.destroy = function() {
-  'use strict';
-  var layer = this.layer;
-
-  if (deviceIsAndroid) {
-    layer.removeEventListener('mouseover', this.onMouse, true);
-    layer.removeEventListener('mousedown', this.onMouse, true);
-    layer.removeEventListener('mouseup', this.onMouse, true);
-  }
-
-  layer.removeEventListener('click', this.onClick, true);
-  layer.removeEventListener('touchstart', this.onTouchStart, false);
-  layer.removeEventListener('touchmove', this.onTouchMove, false);
-  layer.removeEventListener('touchend', this.onTouchEnd, false);
-  layer.removeEventListener('touchcancel', this.onTouchCancel, false);
-};
-
-
-/**
- * Check whether FastClick is needed.
- *
- * @param {Element} layer The layer to listen on
- */
-FastClick.notNeeded = function(layer) {
-  'use strict';
-  var metaViewport;
-  var chromeVersion;
-
-  // Devices that don't support touch don't need FastClick
-  if (typeof window.ontouchstart === 'undefined') {
-    return true;
-  }
-
-  // Chrome version - zero for other browsers
-  chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
-
-  if (chromeVersion) {
-
-    if (deviceIsAndroid) {
-      metaViewport = document.querySelector('meta[name=viewport]');
-
-      if (metaViewport) {
-        // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
-        if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
-          return true;
-        }
-        // Chrome 32 and above with width=device-width or less don't need FastClick
-        if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
-          return true;
-        }
-      }
-
-    // Chrome desktop doesn't need FastClick (issue #15)
-    } else {
-      return true;
-    }
-  }
-
-  // IE10 with -ms-touch-action: none, which disables double-tap-to-zoom (issue #97)
-  if (layer.style.msTouchAction === 'none') {
-    return true;
-  }
-
-  return false;
-};
-
-
-/**
- * Factory method for creating a FastClick object
- *
- * @param {Element} layer The layer to listen on
- * @param {Object} options The options to override the defaults
- */
-FastClick.attach = function(layer, options) {
-  'use strict';
-  return new FastClick(layer, options);
-};
-
-
-if (typeof define !== 'undefined' && define.amd) {
-
-  // AMD. Register as an anonymous module.
-  define(function() {
-    'use strict';
-    return FastClick;
-  });
-} else if (typeof module !== 'undefined' && module.exports) {
-  module.exports = FastClick.attach;
-  module.exports.FastClick = FastClick;
-} else {
-  window.FastClick = FastClick;
-}
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
index e2106ca..c81cf1f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/json/defaultValues.json
@@ -20,6 +20,7 @@
       "loading": false,
       "mandatory": false,
       "statusVisible": true,
+      "statusPosition": "default",
       "menus": [],
       "menusVisible": false,
       "gridData": {
@@ -70,6 +71,10 @@
       "keyStroke": null,
       "statusVisible": false
     },
+    "Graph": {
+      "graphDepth": 1,
+      "toolbarVisible": false
+    },
     "GroupBox": {
       "borderDecoration": "auto",
       "borderVisible": true,
@@ -99,17 +104,23 @@
       "fields": []
     },
     "SmartField": {
-      "lookupStrategy": "remote",
       "proposal": false
     },
     "SmartFieldMultiline": {
     },
+    "SplitBox": {
+      "fieldCollapsed": false,
+      "collapsibleField": null
+    },
     "StringField": {
       "inputMasked": false,
       "multilineText": false,
       "updateDisplayTextOnModify": false,
       "maxLength": 4000
     },
+    "WrappedFormField": {
+      "initialFocusEnabled": false
+    },
     "DateField": {
       "hasDate": true,
       "hasTime": false
@@ -125,7 +136,6 @@
       "multiCheck": true,
       "multiSelect": true,
       "multilineText": false,
-      "rowHeightHint": -1,
       "rows": [],
       "scrollToSelection": false,
       "selectedRows": [],
@@ -134,7 +144,8 @@
       "tableStatusVisible": false
     },
     "Desktop": {
-      "actions": [],
+      "desktopStyle": "DEFAULT",
+      "menus": [],
       "addOns": [],
       "dialogs": [],
       "views": [],
@@ -143,7 +154,9 @@
       "fileChoosers": []
     },
     "Outline": {
-      "breadcrumbEnabled": false,
+      "displayStyle": "default",
+      "autoToggleBreadcrumbStyle": true,
+      "navigateButtonsVisible": true,
       "dialogs": [],
       "views": [],
       "messageBoxes": [],
@@ -172,13 +185,17 @@
       "multiCheck": true,
       "nodes": [],
       "selectedNodes": [],
-      "filterEnabled": false
+      "filterEnabled": false,
+      "lazyExpandingEnabled": true
     },
     "ImageField": {
       "scrollBarEnabled": false
     },
     "HtmlField": {
-      "scrollBarsEnabled": false
+      "scrollBarEnabled": false
+    },
+    "BrowserField": {
+      "scrollBarEnabled": false
     },
 
     // Other objects
@@ -262,6 +279,7 @@
         "SmartField": {
           "SmartFieldMultiline": null
         },
+        "SliderField": null,
         "StringField": null,
         "RadioButtonGroup": null
       },
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_fr.properties b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_fr.properties
new file mode 100644
index 0000000..8004616
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_fr.properties
@@ -0,0 +1,131 @@
+ui.Active=Actifs
+ui.Aggregation=Aggr\u00E9gation
+ui.All=Tous
+ui.Average=Moyenne
+ui.BooleanColumnGroupingFalse=non marqu\u00E9s
+ui.BooleanColumnGroupingTrue=marqu\u00E9s
+ui.Browse=Parcourir
+ui.BrowserChrome=Google Chrome
+ui.BrowserFirefox=Mozilla Firefox
+ui.BrowserInternetExplorer=Microsoft Internet Explorer
+ui.BrowserTooOld=Votre navigateur n'est plus actuel et ne r\u00E9pond pas aux exigences pour fonctionner avec cette application. Veuillez utiliser une version actuelle de \:
+ui.CW=SC {0}
+ui.CalendarCalendarWeek=Semaine de calendrier
+ui.CalendarDay=Jour
+ui.CalendarMonth=Mois
+ui.CalendarToday=Aujourd'hui
+ui.CalendarWeek=Semaine
+ui.CalendarWorkWeek=5 jours
+ui.CalendarYear=Ann\u00E9e
+ui.Categories=Cat\u00E9gories
+ui.Chart=Diagramme
+ui.ChooseFile=S\u00E9lectionner un fichier
+ui.ChooseFiles=S\u00E9lectionner des fichiers
+ui.ClipboardTimeout=D\u00E9passement du temps imparti pour insertion du presse-papier
+ui.ClipboardTimeoutTitle=D\u00E9passement du temps Presse-papier
+ui.Coloring=Coloration
+ui.Column=Colonne
+ui.ConnectionInterrupted=Connexion interrompue
+ui.ConnectionReestablished=Connexion r\u00E9tablie
+ui.Continue=Continuer
+ui.ContinueAnyway=Poursuivre malgr\u00E9 tout
+ui.Copy=Copier
+ui.Count=Nombre
+ui.DateRange=Zone de date
+ui.EmptyCell=vide
+ui.ErrorCodeX=Code
+ui.FileChooserHint=Veuillez faire glisser les fichiers souhait\u00E9s dans cette zone ou les s\u00E9lectionner avec Parcourir.
+ui.FileSizeLimit=La taille maximale autoris\u00E9e a \u00E9t\u00E9 d\u00E9pass\u00E9e ({0} MB}.
+ui.FileSizeLimitTitle=Restriction de taille de fichier
+ui.Filter=Filtre
+ui.FilterBy_=Filtrer d'apr\u00E8s \u2026
+ui.FilterInfoCount=({0})
+ui.FilterInfoXOfY=({0} de {1})
+ui.FreeText=Texte libre
+ui.FromXToY=de {\u00E0} \u00E0 {1}
+ui.Grouping=Groupement
+ui.Ignore=Ignorer
+ui.Inactive=Inactifs
+ui.InternalProcessingErrorMsg=Une erreur interne de traitement est survenue {0}
+ui.InternalUiErrorMsg=Une erreur interne UI est survenue {0}
+ui.InvalidDateFormat=Format de date invalide
+ui.JavaScriptDisabledText=Cette application n\u00E9cessite JavaScript. Vous devez activer Javascript dans votre navigateur pour utiliser cette application.
+ui.JavaScriptDisabledTitle=JavaScript est d\u00E9sactiv\u00E9
+ui.LoadingPopupWindow=Chargement en cours\u2026
+ui.Login=Identification
+ui.LoginAgain=S'identifier \u00E0 nouveau
+ui.LoginFailed=Echec de l'identification
+ui.LogoutSuccessful=Vous avez quitt\u00E9 l'application avec succ\u00E8s.\nAu revoir\!
+ui.Map=Carte
+ui.Maximum=maximum
+ui.Minimum=Minimum
+ui.Move=D\u00E9placer
+ui.Network=R\u00E9seau
+ui.NetworkError=Erreur de r\u00E9seau
+ui.NumRowsFiltered={0} filtr\u00E9
+ui.NumRowsFilteredBy={0} filtr\u00E9 par {1}
+ui.NumRowsFilteredMin=Filtr\u00E9
+ui.NumRowsLoaded={0} charg\u00E9
+ui.NumRowsLoadedMin=Charg\u00E9
+ui.NumRowsRendered={0] souscrit\n
+ui.NumRowsSelected={0} s\u00E9lectionn\u00E9
+ui.NumRowsSelectedMin=S\u00E9lectionn\u00E9
+ui.NumberRange=Zone num\u00E9rique
+ui.OpenManually=Ouvrir manuellement
+ui.OtherValues=Divers
+ui.Outlines=Visionner
+ui.Password=Mot de passe
+ui.PleaseWait_=Veuillez attendre \u2026
+ui.PopupBlockerDetected=L'ouverture d'une nouvelle fen\u00EAtre a \u00E9t\u00E9 emp\u00EAch\u00E9e par la navigateur.
+ui.Reconnecting_=Connexion \u2026
+ui.Reload=Charger \u00E0 nouveau
+ui.ReloadData=Nouveau chargement des donn\u00E9es
+ui.RemoveFilter=Supprimer le filtre
+ui.SearchFor_=Rechercher par\u2026
+ui.SelectAll=Tout s\u00E9lectionner
+ui.SelectAllFilter=Tout
+ui.SelectNone=Ne rien s\u00E9lectionner
+ui.SelectNoneFilter=Aucun
+ui.ServerError=Erreur de serveur
+ui.SessionExpiredMsg=La session est termin\u00E9e. Veuillez charger \u00E0 nouveau la page.
+ui.SessionTimeout=Session Temps \u00E9coul\u00E9
+ui.ShowAllNodes=Afficher tous {0}
+ui.Sum=Somme
+ui.TableRowCount0=Aucune ligne
+ui.TableRowCount1=Une ligne
+ui.TableRowCount={0} lignes
+ui.Total=Total
+ui.UiInconsistentMsg=Le profil utilisateur pouvant se trouver dans un \u00E9tat inconsistant, il est conseill\u00E9 de charger \u00E0 nouveau la page.
+ui.UnexpectedProblem=Probl\u00E8me inattendu
+ui.UnsafeUpload=Fichier non fiable t\u00E9l\u00E9charg\u00E9
+ui.UnsafeUploadMsg=Le fichier t\u00E9l\u00E9charg\u00E9 n'est pas fiable. Veuillez effectuer un Scan antivirus de votre syst\u00E8me.
+ui.Up=Vers le haut
+ui.Upload=T\u00E9l\u00E9charger
+ui.User=Utilisateur
+ui.add=ajouter
+ui.addColumn=ajouter
+ui.additionally=en plus
+ui.ascending=croissant
+ui.ascendingAdditionally=en plus croissant
+ui.backward=vers l'arri\u00E8re
+ui.changeColumn=modifier
+ui.descending=d\u00E9croissant
+ui.descendingAdditionally=en plus d\u00E9croissant
+ui.forward=vers l'avant
+ui.from=de
+ui.fromGreenToRed=de Vert  vers Rouge
+ui.fromRedToGreen=de Rouge vers Vert
+ui.grouped=group\u00E9
+ui.groupedByMonth=group\u00E9 par mois
+ui.groupedByWeekday=groupe par jour de la semaine
+ui.groupedByYear=group\u00E9 par an
+ui.groupingApply=appliquer
+ui.overEverything=au dessus de tout
+ui.overSelection=au dessus des lignes s\u00E9lectionn\u00E9es
+ui.remove=supprimer
+ui.removeColumn=supprimer
+ui.showEveryDate=afficher chacune des dates
+ui.to=jusqu'au
+ui.toBegin=vers le d\u00E9but
+ui.toEnd=vers la fin
+ui.withBarChart=avec diagramme \u00E0 b\u00E2tonnets
diff --git a/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_it.properties b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_it.properties
new file mode 100644
index 0000000..5266de9
--- /dev/null
+++ b/org.eclipse.scout.rt.ui.html/src/main/resources/org/eclipse/scout/rt/ui/html/texts/Texts_it.properties
@@ -0,0 +1,131 @@
+ui.Active=Attivi
+ui.Aggregation=Aggregazione
+ui.All=Tutti
+ui.Average=Media
+ui.BooleanColumnGroupingFalse=Non marcati
+ui.BooleanColumnGroupingTrue=Marcati
+ui.Browse=Cerca
+ui.BrowserChrome=Google Chrome
+ui.BrowserFirefox=Mozilla Firefox
+ui.BrowserInternetExplorer=Microsoft Internet Explorer
+ui.BrowserTooOld=Versione del browser non pi\u00F9 attuale, non soddisfa i requisiti per lavorare con l'applicazione. Si prega di utilizzare la versione attuale di\:
+ui.CW=Settimana {0}
+ui.CalendarCalendarWeek=Settimana
+ui.CalendarDay=Giorno
+ui.CalendarMonth=Mese
+ui.CalendarToday=Oggi
+ui.CalendarWeek=Settimana
+ui.CalendarWorkWeek=5 giorni
+ui.CalendarYear=Anno
+ui.Categories=Categorie
+ui.Chart=Diagramma
+ui.ChooseFile=Scegli file
+ui.ChooseFiles=Scegli file
+ui.ClipboardTimeout=Superamento del tempo limite per inserimento da appunti.
+ui.ClipboardTimeoutTitle=Superamento tempo limite appunti
+ui.Coloring=Coloratura
+ui.Column=Colonna
+ui.ConnectionInterrupted=Connessione interrotta
+ui.ConnectionReestablished=Connessione ristabilita
+ui.Continue=Avanti
+ui.ContinueAnyway=Continua lo stesso
+ui.Copy=Copia
+ui.Count=Quantit\u00E0
+ui.DateRange=Area dati
+ui.EmptyCell=-vuoto-
+ui.ErrorCodeX=Codice {0}
+ui.FileChooserHint=Si prega di spostare i file desiderati in questa area oppure di sezionarli con Cerca.
+ui.FileSizeLimit=Superamento della massima dimensione consentita ({0} MB).
+ui.FileSizeLimitTitle=Limitazione delle dimensioni file
+ui.Filter=Filtro
+ui.FilterBy_=Filtra secondo...
+ui.FilterInfoCount=({0})
+ui.FilterInfoXOfY=({0} di {1})
+ui.FreeText=Testo libero
+ui.FromXToY=da {0} fino a {1}
+ui.Grouping=Raggruppamento
+ui.Ignore=Ignora
+ui.Inactive=Inattivi
+ui.InternalProcessingErrorMsg=Errore di elaborazione interno{0}.
+ui.InternalUiErrorMsg=Errore di elaborazione UI interno{0}.
+ui.InvalidDateFormat=Formato dati non valido
+ui.JavaScriptDisabledText=Questa applicazione richiede JavaScript. Attivare JavaScript nel browser per usare l'applicazione.
+ui.JavaScriptDisabledTitle=JavaScript \u00E8 disattivato
+ui.LoadingPopupWindow=Caricamento...
+ui.Login=Log-in
+ui.LoginAgain=Nuovo log-in
+ui.LoginFailed=Log-in fallito
+ui.LogoutSuccessful=Logout effettuato con successo.\nAuf Wiedersehen\!
+ui.Map=Scheda
+ui.Maximum=Massimo
+ui.Minimum=Minimo
+ui.Move=Sposta
+ui.Network=Rete
+ui.NetworkError=Errore di rete
+ui.NumRowsFiltered={0} filtrato
+ui.NumRowsFilteredBy={0} filtrato da {1}
+ui.NumRowsFilteredMin=Filtrato
+ui.NumRowsLoaded={0} caricato
+ui.NumRowsLoadedMin=Caricato
+ui.NumRowsRendered={0} rappresentato
+ui.NumRowsSelected={0} selezionato
+ui.NumRowsSelectedMin=Selezionato
+ui.NumberRange=Intervallo numerico
+ui.OpenManually=Apri manualmente
+ui.OtherValues=Altri
+ui.Outlines=Viste
+ui.Password=Password
+ui.PleaseWait_=Attendere prego
+ui.PopupBlockerDetected=Apertura automatica di una nuova finestra impedita dal browser.
+ui.Reconnecting_=Collegamento...
+ui.Reload=Ricarica
+ui.ReloadData=Ricarica dati
+ui.RemoveFilter=Rimuovi filtro
+ui.SearchFor_=Ricerca per...
+ui.SelectAll=Seleziona tutti
+ui.SelectAllFilter=Tutti
+ui.SelectNone=Scegli nessuno
+ui.SelectNoneFilter=Nessuno
+ui.ServerError=Errore server
+ui.SessionExpiredMsg=Sessione scaduta, si prega di ricaricare la pagina.
+ui.SessionTimeout=Timeout sessione
+ui.ShowAllNodes=Visualizza tutti i {0}
+ui.Sum=Somma
+ui.TableRowCount0=Nessuna riga
+ui.TableRowCount1=Una riga
+ui.TableRowCount={0} righe
+ui.Total=Totale
+ui.UiInconsistentMsg=La piattaforma utente potrebbe trovarsi in uno stato incongruente, perci\u00F2 si consiglia di ricaricare la pagina.
+ui.UnexpectedProblem=Problema inatteso
+ui.UnsafeUpload=Caricato file non sicuro
+ui.UnsafeUploadMsg=Il file caricato non \u00E8 sicuro. Si prega di eseguire una scansione antivirus nel sistema.
+ui.Up=Su
+ui.Upload=Carica
+ui.User=Utente
+ui.add=aggiungi
+ui.addColumn=aggiungi
+ui.additionally=supplementare
+ui.ascending=crescente
+ui.ascendingAdditionally=crescente supplementare
+ui.backward=all'indietro
+ui.changeColumn=modifica
+ui.descending=decrescente
+ui.descendingAdditionally=decrescente supplementare
+ui.forward=in avanti
+ui.from=di
+ui.fromGreenToRed=da verde a rosso
+ui.fromRedToGreen=da rosso a verde
+ui.grouped=raggruppato
+ui.groupedByMonth=raggruppato per mese
+ui.groupedByWeekday=raggruppato per giorno della settimana
+ui.groupedByYear=raggruppato per anno
+ui.groupingApply=applica
+ui.overEverything=sopra tutto
+ui.overSelection=sopra le righe selezionate
+ui.remove=rimuovi
+ui.removeColumn=rimuovi
+ui.showEveryDate=visualizza tutti i dati
+ui.to=fino a
+ui.toBegin=all'inizio
+ui.toEnd=alla fine
+ui.withBarChart=con diagramma a barre
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/BaseDesktopSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/BaseDesktopSpec.js
deleted file mode 100644
index e53568b..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/BaseDesktopSpec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/* global FormSpecHelper */
-describe('BaseDesktop', function() {
-  var session, helper, $sandbox, desktop, ntfc,
-    parent = new scout.Widget();
-
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    $sandbox = $('#sandbox');
-    parent.session = session;
-    desktop = scout.create('Desktop', {
-      parent: parent
-    });
-    ntfc = scout.create('DesktopNotification', {
-      id: 'theID',
-      parent: desktop,
-      status: {}
-    });
-    desktop.render($sandbox);
-  });
-
-  it('addNotification', function() {
-    spyOn(ntfc, 'fadeIn');
-    desktop.addNotification(ntfc);
-    expect(ntfc.fadeIn).toHaveBeenCalled();
-    expect(desktop.notifications.indexOf(ntfc)).toBe(0);
-    expect(desktop.$container.find('.notifications').length).toBe(1);
-    expect(desktop.$notification).not.toBe(null);
-  });
-
-  it('removeNotification with object', function() {
-    spyOn(ntfc, 'fadeOut');
-    desktop.addNotification(ntfc); // first add -> create $notifications DIV
-    desktop.removeNotification(ntfc);
-    expect(ntfc.fadeOut).toHaveBeenCalled();
-  });
-
-  it('removeNotification with (string) ID', function() {
-    spyOn(ntfc, 'fadeOut');
-    desktop.addNotification(ntfc); // first add -> create $notifications DIV
-    desktop.removeNotification('theID');
-    expect(ntfc.fadeOut).toHaveBeenCalled();
-  });
-
-  it('_onNotificationRemoved - last notifications removes $notifications DIV', function() {
-    desktop.addNotification(ntfc); // first add -> create $notifications DIV
-    desktop._onNotificationRemoved(ntfc);
-    expect(desktop.notifications.length).toBe(0);
-    expect(desktop.$container.find('.notifications').length).toBe(0);
-    expect(desktop.$notifications).toBe(null);
-  });
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopSpec.js
deleted file mode 100644
index f782055..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/DesktopSpec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-describe('Desktop', function() {
-
-  var session, desktop = new scout.Desktop();
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    desktop.viewButtons = [];
-    desktop.session = session;
-  });
-
-  describe('_addNullOutline', function() {
-
-    it('should add null-outline when outline of model doesn\'t exist', function() {
-      var ovb, outline = null;
-      desktop._addNullOutline(outline);
-      expect(desktop.viewButtons.length).toBe(1);
-      ovb = desktop.viewButtons[0];
-      expect(desktop.outline).toBe(ovb.outline);
-      expect(ovb.visibleInMenu).toBe(false);
-    });
-
-    it('shouldn\'t do anything when model already has an outline', function() {
-      var outline = {};
-      desktop.outline = outline;
-      desktop._addNullOutline(outline);
-      expect(desktop.outline).toBe(outline);
-      expect(desktop.viewButtons.length).toBe(0);
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/OutlineSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/OutlineSpec.js
deleted file mode 100644
index 909b845..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/desktop/OutlineSpec.js
+++ /dev/null
@@ -1,242 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-describe("Outline", function() {
-  var session;
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    jasmine.Ajax.install();
-    jasmine.clock().install();
-  });
-
-  afterEach(function() {
-    session = null;
-    jasmine.Ajax.uninstall();
-    jasmine.clock().uninstall();
-  });
-
-  function createModelFixture(nodeCount, depth, expanded) {
-    return createModel(createModelNodes(nodeCount, depth, expanded));
-  }
-
-  function createModel(nodes) {
-    var model = createSimpleModel('Outline', session);
-
-    if (nodes) {
-      model.nodes = nodes;
-    }
-
-    return model;
-  }
-
-  function createModelNode(id, text) {
-    return {
-      "id": id,
-      "text": text
-    };
-  }
-
-  function createModelNodes(nodeCount, depth, expanded) {
-    return createModelNodesInternal(nodeCount, depth, expanded);
-  }
-
-  function createModelNodesInternal(nodeCount, depth, expanded, parentNode) {
-    if (!nodeCount) {
-      return;
-    }
-
-    var nodes = [],
-      nodeId;
-    if (!depth) {
-      depth = 0;
-    }
-    for (var i = 0; i < nodeCount; i++) {
-      nodeId = i;
-      if (parentNode) {
-        nodeId = parentNode.id + '_' + nodeId;
-      }
-      nodes[i] = createModelNode(nodeId, 'node ' + i);
-      nodes[i].expanded = expanded;
-      if (depth > 0) {
-        nodes[i].childNodes = createModelNodesInternal(nodeCount, depth - 1, expanded, nodes[i]);
-      }
-    }
-    return nodes;
-  }
-
-  function createOutline(model) {
-    var tree = new scout.Outline();
-    tree.init(model);
-    return tree;
-  }
-
-  function createNodesDeletedEvent(model, nodeIds, commonParentNodeId) {
-    return {
-      target: model.id,
-      commonParentNodeId: commonParentNodeId,
-      nodeIds: nodeIds,
-      type: 'nodesDeleted'
-    };
-  }
-
-  function createAllChildNodesDeletedEvent(model, commonParentNodeId) {
-    return {
-      target: model.id,
-      commonParentNodeId: commonParentNodeId,
-      type: 'allChildNodesDeleted'
-    };
-  }
-
-  describe("dispose", function() {
-    var model, tree, node0, node1, node2;
-
-    beforeEach(function() {
-      // A large tree is used to properly test recursion
-      model = createModelFixture(3, 2, true);
-      tree = createOutline(model);
-      node0 = model.nodes[0];
-      node1 = model.nodes[1];
-      node2 = model.nodes[2];
-    });
-
-    it("calls onNodeDeleted for every node to be able to cleanup", function() {
-      spyOn(tree, '_onNodeDeleted');
-      tree.destroy();
-      expect(tree._onNodeDeleted.calls.count()).toBe(39);
-    });
-
-    it("calls onNodeDeleted for every node (which was not already deleted before) to be able to cleanup", function() {
-      spyOn(tree, '_onNodeDeleted');
-
-      var message = {
-        events: [createNodesDeletedEvent(model, [node0.id])]
-      };
-      session._processSuccessResponse(message);
-      expect(tree._onNodeDeleted.calls.count()).toBe(13);
-
-      tree._onNodeDeleted.calls.reset();
-      tree.destroy();
-      expect(tree._onNodeDeleted.calls.count()).toBe(26);
-    });
-
-  });
-
-  describe("navigateToTop", function() {
-
-    it("collapses all nodes in bread crumb mode", function() {
-      var model = createModelFixture(1, 1);
-      var node0 = model.nodes[0];
-
-      var tree = createOutline(model);
-      tree.breadcrumbEnabled = true;
-      tree.render(session.$entryPoint);
-
-      tree.selectNodes(node0);
-
-      expect(tree.selectedNodes.indexOf(node0) > -1).toBe(true);
-      expect(node0.expanded).toBe(true);
-
-      tree.navigateToTop();
-
-      expect(tree.selectedNodes.length).toBe(0);
-      expect(node0.expanded).toBe(false);
-    });
-  });
-
-  describe("onModelAction", function() {
-
-    describe("nodesDeleted event", function() {
-      var model, tree, node0, node1, node2;
-
-      beforeEach(function() {
-        // A large tree is used to properly test recursion
-        model = createModelFixture(3, 2, true);
-        tree = createOutline(model);
-        node0 = model.nodes[0];
-        node1 = model.nodes[1];
-        node2 = model.nodes[2];
-      });
-
-      it("calls onNodeDeleted for every node to be able to cleanup", function() {
-        spyOn(tree, '_onNodeDeleted');
-
-        var message = {
-          events: [createNodesDeletedEvent(model, [node0.id])]
-        };
-        session._processSuccessResponse(message);
-
-        expect(tree._onNodeDeleted.calls.count()).toBe(13);
-      });
-
-    });
-
-    describe("allChildNodesDeleted event", function() {
-      var model, tree, node0, node1, node2;
-
-      beforeEach(function() {
-        // A large tree is used to properly test recursion
-        model = createModelFixture(3, 2, true);
-        tree = createOutline(model);
-        node0 = model.nodes[0];
-        node1 = model.nodes[1];
-        node2 = model.nodes[2];
-      });
-
-      it("calls onNodeDeleted for every node to be able to cleanup", function() {
-        spyOn(tree, '_onNodeDeleted');
-
-        var message = {
-          events: [createAllChildNodesDeletedEvent(model)]
-        };
-        session._processSuccessResponse(message);
-
-        expect(tree._onNodeDeleted.calls.count()).toBe(39);
-        expect(scout.objects.countProperties(tree.nodesMap)).toBe(0);
-      });
-
-    });
-
-    describe("selectNodes", function() {
-      var model, outline, node;
-
-      beforeEach(function() {
-        model = createModelFixture(3, 2, true);
-        outline = createOutline(model);
-        node = model.nodes[0];
-      });
-
-      it("handle navigateUp only once", function() {
-        outline.navigateUpInProgress = true;
-        outline.selectNodes([]);
-        expect(outline.navigateUpInProgress).toBe(false);
-      });
-
-      // we must override the _render* methods for this test-case, since we had to
-      // implement a lot more of set-up code to make these methods work.
-      it("otherwise handle single selection (or do nothing when selection is != 1 node)", function() {
-        node.detailFormVisibleByUi = false;
-        outline.navigateUpInProgress = false;
-        outline._renderSelection = function() {};
-        outline._renderMenus = function() {};
-
-        // don't change the visibleByUi flag when selection is != 1
-        outline.selectNodes([]);
-        expect(node.detailFormVisibleByUi).toBe(false);
-
-        // set the visibleByUi flag to true when selection is exactly 1
-        outline.selectNodes([node]);
-        expect(node.detailFormVisibleByUi).toBe(true);
-      });
-    });
-
-  });
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormToolButtonSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormToolButtonSpec.js
deleted file mode 100644
index 8dd98ca..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/FormToolButtonSpec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/* global FormSpecHelper */
-describe("FormToolButton", function() {
-  var session, desktop, helper;
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    helper = new FormSpecHelper(session);
-    desktop = {
-      $parent: session.$entryPoint,
-      $toolContainer: session.$entryPoint.appendDiv('taskbar-tools').hide()
-    };
-  });
-
-  function createAction(model) {
-    model.form = helper.createFormWithOneField();
-    model.desktop = desktop;
-
-    var action = new scout.FormToolButton();
-    action.init(model);
-    action.position = function() {};
-    return action;
-  }
-
-  function findToolContainer() {
-    return $('.popup');
-  }
-
-  describe("onModelPropertyChange", function() {
-
-    describe("selected", function() {
-
-      it("opens and closes the tool container", function() {
-        var action = createAction(createSimpleModel('FormToolButton', session));
-        action.render(session.$entryPoint);
-        expect(findToolContainer()).not.toExist();
-
-        var event = createPropertyChangeEvent(action, {
-          "selected": true
-        });
-        action.onModelPropertyChange(event);
-        expect(findToolContainer()).toBeVisible();
-
-        event = createPropertyChangeEvent(action, {
-          "selected": false
-        });
-        action.onModelPropertyChange(event);
-        expect(findToolContainer()).not.toExist();
-      });
-
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js
deleted file mode 100644
index fc3e5d4..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/smartfield/SmartFieldSpec.js
+++ /dev/null
@@ -1,145 +0,0 @@
- /*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-describe('SmartField', function() {
-
-  var smartField;
-
-  beforeEach(function() {
-    smartField = new scout.SmartField();
-    smartField.$field = $('<input>');
-    smartField.session = {
-      listen: function() {
-        return {
-          done: function(func) {
-          }
-        };
-      }
-    };
-    smartField.remoteHandler = function() {};
-  });
-
-  describe('_onKeyUp', function() {
-
-    it('doesn not call _openProposal() when TAB has been pressed', function() {
-      smartField._openProposal = function(searchText, selectCurrentValue) {};
-      var event = {
-        which: scout.keys.TAB
-      };
-      spyOn(smartField, '_openProposal');
-      smartField._onKeyUp(event);
-      expect(smartField._openProposal).not.toHaveBeenCalled();
-    });
-
-    it('calls _openProposal() when a character key has been pressed', function() {
-      smartField._browseOnce = true;
-      smartField._popup = {};
-      smartField._openProposal = function(searchText, selectCurrentValue) {};
-      var event = {
-        which: scout.keys.A
-      };
-      spyOn(smartField, '_openProposal').and.callThrough();
-      smartField._onKeyUp(event);
-      expect(smartField._openProposal).toHaveBeenCalled();
-    });
-
-  });
-
-  describe('_syncProposalChooser', function() {
-
-    it('must reset _requestProposal property', function() {
-      expect(smartField._requestedProposal).toBe(false);
-      smartField._openProposal(true);
-      expect(smartField._requestedProposal).toBe(true);
-      smartField._syncProposalChooser({});
-      expect(smartField._requestedProposal).toBe(false);
-    });
-
-  }),
-
-  describe('_openProposal', function() {
-
-    var events = [null];
-
-    beforeEach(function() {
-      smartField.$field.val('foo');
-      smartField.remoteHandler = function(event, delay) {
-        events[0] = event;
-      };
-    });
-
-    it('must "browse all" when field is valid and browseAll parameter is true', function() {
-      smartField._openProposal(true);
-      expect(events[0].searchText).toBe('foo');
-      expect(events[0].browseAll).toBe(true);
-      expect(events[0].selectCurrentValue).toBe(true);
-    });
-
-    it('must search by display-text when field is valid and browseAll parameter is false', function() {
-      smartField._openProposal(false);
-      expect(events[0].searchText).toBe('foo');
-      expect(events[0].selectCurrentValue).toBe(false);
-    });
-
-    it('must "browseAll" when field is invalid', function() {
-      smartField.errorStatus = {};
-      smartField._openProposal(true);
-      expect(events[0].searchText).toBe('foo');
-      expect(events[0].browseAll).toBe(true);
-      expect(events[0].selectCurrentValue).toBe(false);
-    });
-  });
-
-  describe('_acceptProposal', function() {
-
-    it('must set displayText', function() {
-      smartField.$field.val('foo');
-      smartField._acceptProposal();
-      expect(smartField.displayText).toBe('foo');
-    });
-
-    it('must call clearTimeout() for pending typedProposal events', function() {
-      smartField._sendTimeoutId = null;
-      smartField.$field.val('bar');
-      smartField._proposalTyped();
-      expect(smartField._pendingProposalTyped).toBeTruthy();
-      smartField._acceptProposal();
-      expect(smartField._pendingProposalTyped).toBe(null);
-    });
-
-    it('dont send _acceptProposal when searchText has not changed', function() {
-      smartField._oldSearchText = 'foo';
-      smartField.$field.val('foo');
-      spyOn(smartField, 'remoteHandler');
-      smartField._acceptProposal();
-      expect(smartField.remoteHandler).not.toHaveBeenCalled();
-    });
-
-    it('send _acceptProposal when searchText has changed', function() {
-      smartField._oldSearchText = 'foo';
-      smartField.$field.val('bar');
-      spyOn(smartField, 'remoteHandler');
-      smartField._acceptProposal();
-      expect(smartField.remoteHandler).toHaveBeenCalled();
-    });
-
-    // test for ticket #168652
-    it('send deleteProposal when searchText has been deleted quickly', function() {
-      smartField._oldSearchText = 'foo';
-      smartField.$field.val('');
-      smartField.proposalChooser = {}; // fake proposal-chooser is open
-      spyOn(smartField, '_sendDeleteProposal');
-      smartField._acceptProposal();
-      expect(smartField._sendDeleteProposal).toHaveBeenCalled();
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js
deleted file mode 100644
index 71cf434..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/form/fields/wrappedform/WrappedFormSpec.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/* global FormSpecHelper */
-describe("WrappedForm", function() {
-  var session;
-  var helper;
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    helper = new FormSpecHelper(session);
-  });
-
-  function createField(model) {
-    var field = new scout.WrappedFormField();
-    field.init(model);
-    return field;
-  }
-
-  function createModel() {
-    return helper.createFieldModel('WrappedFormField');
-  }
-
-  describe("mandatory indicator", function() {
-
-    // Must not contain an indicator to prevent a double indicator if the first field is mandatory too
-    it("does not exist", function() {
-      var model = createModel();
-      model.mandatory = true;
-      var field = createField(model);
-      field.render(session.$entryPoint);
-
-      expect(field.$mandatory).toBeUndefined();
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/LayoutValidatorSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/LayoutValidatorSpec.js
deleted file mode 100644
index a1dd6f1..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/layout/LayoutValidatorSpec.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-describe("LayoutValidator", function() {
-  var session;
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-  });
-
-  describe("invalidateTree", function() {
-
-    it("keeps track of invalid html components", function() {
-      var $comp = $('<div>').appendTo(session.$entryPoint);
-      var htmlComp = new scout.HtmlComponent($comp, session);
-
-      htmlComp.invalidateLayoutTree();
-      expect(session.layoutValidator._invalidComponents.length).toBe(1);
-      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
-    });
-
-    it("considers only the topmost component", function() {
-      var $comp = $('<div>').appendTo(session.$entryPoint);
-      var htmlComp = new scout.HtmlComponent($comp, session);
-
-      var $compChild = $('<div>').appendTo($comp);
-      var htmlCompChild = new scout.HtmlComponent($compChild, session);
-
-      htmlCompChild.invalidateLayoutTree();
-      expect(session.layoutValidator._invalidComponents.length).toBe(1);
-      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlComp);
-    });
-
-    it("and validate roots", function() {
-      var $comp = $('<div>').appendTo(session.$entryPoint);
-      new scout.HtmlComponent($comp, session);
-
-      var $compChild = $('<div>').appendTo($comp);
-      var htmlCompChild = new scout.HtmlComponent($compChild, session);
-      htmlCompChild.validateRoot = true;
-
-      htmlCompChild.invalidateLayoutTree();
-      expect(session.layoutValidator._invalidComponents.length).toBe(1);
-      expect(session.layoutValidator._invalidComponents[0]).toBe(htmlCompChild);
-    });
-  });
-
-  describe("layout", function() {
-
-    it("calls validateLayout for each invalid html component", function() {
-      var $comp = $('<div>').appendTo(session.$entryPoint);
-      var htmlComp = new scout.HtmlComponent($comp, session);
-      spyOn(htmlComp, 'validateLayout');
-
-      htmlComp.invalidateLayoutTree();
-      session.layoutValidator.validate();
-      expect(htmlComp.validateLayout).toHaveBeenCalled();
-      expect(htmlComp.validateLayout.calls.count()).toEqual(1);
-    });
-
-    it("does not call validateLayout if component has been removed", function() {
-      var $comp = $('<div>').appendTo(session.$entryPoint);
-      var htmlComp = new scout.HtmlComponent($comp, session);
-      spyOn(htmlComp, 'validateLayout');
-
-      htmlComp.invalidateLayoutTree();
-      $comp.remove();
-      session.layoutValidator.validate();
-      expect(htmlComp.validateLayout).not.toHaveBeenCalled();
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/MobileTableSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/MobileTableSpec.js
deleted file mode 100644
index d117d71..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/table/MobileTableSpec.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-/* global TableSpecHelper */
-describe("MobileTable", function() {
-  var session;
-  var helper;
-
-  beforeEach(function() {
-    setFixtures(sandbox());
-    session = sandboxSession();
-    helper = new TableSpecHelper(session);
-    jasmine.Ajax.install();
-    jasmine.clock().install();
-  });
-
-  afterEach(function() {
-    session = null;
-    jasmine.Ajax.uninstall();
-    jasmine.clock().uninstall();
-  });
-
-  describe("render", function() {
-
-    //FIXME cgu: temporarily disabled until mobile works again
-//    it("does not create an addional div for scrolling", function() {
-//      var model = helper.createModelFixture(2);
-//      var table = helper.createMobileTable(model);
-//      table.render(session.$entryPoint);
-//      expect(table.$data).toBe(table.$data);
-//    });
-
-    it("does not display context menus", function() {
-      var model = helper.createModelFixture(2,2);
-      var table = helper.createMobileTable(model);
-      table.render(session.$entryPoint);
-
-      model.menus = [helper.createMenuModel('1','menu')];
-      var $row0 = table.$data.children().eq(0);
-      $row0.triggerContextMenu();
-
-      var $menu = helper.getDisplayingContextMenu(table);
-      expect($menu.length).toBeFalsy();
-    });
-  });
-
-
-});
diff --git a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/DeviceSpec.js b/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/DeviceSpec.js
deleted file mode 100644
index a22e1d8..0000000
--- a/org.eclipse.scout.rt.ui.html/src/test/js/scout/util/DeviceSpec.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     BSI Business Systems Integration AG - initial API and implementation
- ******************************************************************************/
-describe('Device', function() {
-
-  function verifyDevices(actual, expected) {
-    expect(actual.system).toBe(expected.system);
-    expect(actual.type).toBe(expected.type);
-  }
-
-  function createDevice(system, type) {
-    var device = new scout.Device();
-    device.system = system;
-    device.type = type;
-    return device;
-  }
-
-  describe('scout.device', function() {
-
-    it('is initialized automatically', function() {
-      expect(scout.device).toBeDefined();
-      expect(scout.device.browser).toBeDefined();
-      expect(scout.device.unselectableAttribute).toBeDefined();
-    });
-
-  });
-
-  describe('isWindowsTablet', function() {
-
-    it ('returns true when browser is Edge and scrollbarWidth is 0', function() {
-      scout.device.scrollbarWidth = 0;
-      scout.device.browser = scout.Device.Browser.EDGE;
-      expect(scout.device.isWindowsTablet()).toBe(true);
-    });
-
-  });
-
-  describe('new scout.Device instance detects system and type after bootstrap() has been called', function() {
-
-    function bootstrapDevice(userAgent) {
-      var device = new scout.Device(userAgent);
-      device.bootstrap();
-      return device;
-    }
-
-    it('recognizes iOS devices', function() {
-      var userAgent, expectedDevice;
-
-      // iPhone 4S
-      userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25';
-      expectedDevice = createDevice(scout.Device.System.IOS, scout.Device.Type.MOBILE);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-
-      // iPad 3
-      userAgent = 'Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3';
-      expectedDevice = createDevice(scout.Device.System.IOS, scout.Device.Type.TABLET);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-
-      // iPad 3 (home screen icon mode)
-      userAgent = 'Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176';
-      expectedDevice = createDevice(scout.Device.System.IOS, scout.Device.Type.TABLET);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-    });
-
-    it('recognizes Android devices', function() {
-      var userAgent, expectedDevice;
-
-      // Samsung Galaxy S4
-      userAgent = 'Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.170 Mobile Safari/537.36';
-      expectedDevice = createDevice(scout.Device.System.ANDROID, scout.Device.Type.MOBILE);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-
-      // Google Nexus 10 Tablet
-      userAgent = 'Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JWR66Y) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Safari/537.36';
-      expectedDevice = createDevice(scout.Device.System.ANDROID, scout.Device.Type.TABLET);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-    });
-
-    it('recognizes normal Windows PCs', function() {
-      // Windows with Firefox browser
-      var userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36';
-      var expectedDevice = createDevice(scout.Device.System.UNKNOWN, scout.Device.Type.DESKTOP);
-      verifyDevices(bootstrapDevice(userAgent), expectedDevice);
-    });
-
-    // Note: cannot detect Surface tablet reliable with Jasmine test, since scrollbar width
-    // measurement depends on the browser that runs the spec.
-
-    it('recognizes supported browsers', function() {
-      var userAgent, device;
-
-      // Microsoft Edge 12
-      test('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240',
-          scout.Device.Browser.EDGE, 12.10240);
-
-      // Internet Explorer 11
-      test('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko',
-          scout.Device.Browser.INTERNET_EXPLORER, 11.0);
-      // Internet Explorer 11 - as used by Outlook - note the additional ; and text after the version-no (rv).
-      test('Mozilla/5.0 (Windows NT 6.1; WOW65; Trident/7.0; rv:11.0; Microsoft Outlook 14.0.7155)',
-          scout.Device.Browser.INTERNET_EXPLORER, 11.0);
-
-      // Internet Explorer 8
-      test('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.30729; .NET CLR 3.0.30729)',
-          scout.Device.Browser.INTERNET_EXPLORER, 8.0);
-
-      // Safari (6)
-      test('Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25',
-          scout.Device.Browser.SAFARI, 6.0);
-
-      // Firefox (21) from v21 Firefox supports ECMA 5
-      test('Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1',
-          scout.Device.Browser.FIREFOX, 21.0);
-
-      // Chrome (23) from v23 Chrome supports ECMA 5
-      test('Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.6 Safari/537.11',
-          scout.Device.Browser.CHROME, 23.0);
-
-      function test(userAgent, expectedBrowser, expectedVersion) {
-        var device = new scout.Device(userAgent);
-        expect(device.browser).toBe(expectedBrowser);
-        expect(device.browserVersion).toEqual(expectedVersion);
-      }
-    });
-
-  });
-
-});
diff --git a/org.eclipse.scout.rt/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.scout.rt/.settings/org.eclipse.jdt.core.prefs
index 7a93103..a36938b 100644
--- a/org.eclipse.scout.rt/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.scout.rt/.settings/org.eclipse.jdt.core.prefs
@@ -68,7 +68,7 @@
 org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
 org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
 org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
 org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
 org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
 org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
diff --git a/org.eclipse.scout.rt/TransientDependencies.adoc b/org.eclipse.scout.rt/TransientDependencies.adoc
deleted file mode 100644
index f4708a1..0000000
--- a/org.eclipse.scout.rt/TransientDependencies.adoc
+++ /dev/null
@@ -1,22 +0,0 @@
-=== Transient Dependencies
-
-:doctype: article
-:revnumber: {project-version}
-
-As every dependencies build its own dependency tree two dependencies can depend on the same artifact.
-But they do not necessarily depend on the same version.
-This can result to a classpath with two version of the same dependency.
-
-==== Solution
-
-To work around this problem we define every transient dependency in the dependency management exactly once with a defined version.
-To search for all dependencies this script can be used:
-
-    mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:resolve | grep '\[INFO\]    ' | cut -d':' -f1-4 | sort | uniq | cut -c11- | grep -v none | grep -v org.eclipse | sed -r 's/(.*):(.*):(.*):(.*)/      \<dependency\>\n        \<groupId\>\1\<\/groupId\>\n        \<artifactId>\2\<\/artifactId\>\n        \<version\>\4\<\/version\>\n      \<\/dependency\>/'
-
-It prints out the dependencies as maven dependencies.
-Before this script is used the transient section in the org.eclipse.scout.rt/pom.xml at the end of the dependencyManagement section should be commented or removed.
-So we get all dependencies in their intended version.
-
-The output can be pasted to the org.eclipse.scout.rt/pom.xml at the end of the dependencyManagement section.
-Then remove duplicates from the transient section.
diff --git a/org.eclipse.scout.rt/TransitiveDependencies.adoc b/org.eclipse.scout.rt/TransitiveDependencies.adoc
new file mode 100644
index 0000000..3c87359
--- /dev/null
+++ b/org.eclipse.scout.rt/TransitiveDependencies.adoc
@@ -0,0 +1,24 @@
+=== Transitive Dependencies
+
+:doctype: article
+:revnumber: {project-version}
+
+As every dependencies build its own dependency tree two dependencies can depend on the same artifact.
+But they do not necessarily depend on the same version.
+This can result to a classpath with two version of the same dependency.
+
+==== Solution
+
+To work around this problem we define every transitive dependency in the dependency management exactly once with a defined version.
+To search for all dependencies this script can be used:
+
+    mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:resolve | grep '\[INFO\]    ' | cut -d':' -f1-4 | sort | uniq | cut -c11- | grep -v none | grep -v org.eclipse | sed -r 's/(.*):(.*):(.*):(.*)/      \<dependency\>\n        \<groupId\>\1\<\/groupId\>\n        \<artifactId>\2\<\/artifactId\>\n        \<version\>\4\<\/version\>\n      \<\/dependency\>/'
+
+It prints out the dependencies as maven dependencies.
+Before this script is used the transitive section in the org.eclipse.scout.rt/pom.xml at the end of the dependencyManagement section should be commented or removed.
+So we get all dependencies in their intended version.
+
+The output can be compared to the effective POM of org.eclipse.scout.rt/pom.xml (with commented out transitive dependencies).
+Duplicates can be removed and the remaining purely transitive dependencies can be added to the transitive section.
+
+Note: c3p0 is an optional transitive dependency from quartz not used in Scout and can be omitted.
diff --git a/org.eclipse.scout.rt/Sync Eclipse Scout Project Settings.launch "b/org.eclipse.scout.rt/\133org.eclipse.scout\135 Sync Project Settings.launch"
similarity index 100%
rename from org.eclipse.scout.rt/Sync Eclipse Scout Project Settings.launch
rename to "org.eclipse.scout.rt/\133org.eclipse.scout\135 Sync Project Settings.launch"
diff --git a/org.eclipse.scout.rt/pom.xml b/org.eclipse.scout.rt/pom.xml
index 1ccd0d9..8fe6809 100644
--- a/org.eclipse.scout.rt/pom.xml
+++ b/org.eclipse.scout.rt/pom.xml
@@ -23,7 +23,7 @@
 
   <groupId>org.eclipse.scout.rt</groupId>
   <artifactId>org.eclipse.scout.rt</artifactId>
-  <version>5.2.0-SNAPSHOT</version>
+  <version>6.0.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <name>Eclipse Scout RT</name>
   <description>Eclipse Scout RT</description>
@@ -53,8 +53,6 @@
 
     <module>../org.eclipse.scout.rt.client</module>
     <module>../org.eclipse.scout.rt.client.test</module>
-    <module>../org.eclipse.scout.rt.client.mobile</module>
-    <module>../org.eclipse.scout.rt.client.mobile.test</module>
     <module>../org.eclipse.scout.rt.svg.client</module>
     <module>../org.eclipse.scout.rt.svg.client.test</module>
 
@@ -73,7 +71,7 @@
   </modules>
 
   <properties>
-    <scout.base.version>5.2.0</scout.base.version>
+    <scout.base.version>6.0.0</scout.base.version>
     <base.version>${scout.base.version}</base.version>
     <org.eclipse.scout.rt.version>${project.version}</org.eclipse.scout.rt.version>
     <jetty.version>9.2.13.v20150730</jetty.version>
@@ -81,7 +79,7 @@
 
     <master_coverage_jacoco_destFile>${basedir}/../org.eclipse.scout.rt/target/jacoco-all.exec</master_coverage_jacoco_destFile>
     <!-- Sonar properties -->
-    <sonar.branch>releases_5.2.x</sonar.branch>
+    <sonar.branch>releases_6.0.x</sonar.branch>
     <sonar.jacoco.reportPath>${master_coverage_jacoco_destFile}</sonar.jacoco.reportPath>
     <sonar.exclusions>**/resources/WebContent/**</sonar.exclusions>
     <sonar.coverage.exclusions>*.test/**,
@@ -159,150 +157,144 @@
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.json</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.platform</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.platform.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.shared</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.shared.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.commons</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.jms</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.jaxws</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.jdbc</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.server.jdbc.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.client</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.client.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
-      </dependency>
-
-      <dependency>
-        <groupId>org.eclipse.scout.rt</groupId>
-        <artifactId>org.eclipse.scout.rt.client.mobile</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.svg.client</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.serverbridge</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.jaxws.apt</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.ui.html</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.ui.html.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.ui.html.scriptprocessor</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.ui.html.scriptprocessor.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.rt.svg.ui.html</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.dev.jetty</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.dev.jetty.test</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.scout.rt</groupId>
         <artifactId>org.eclipse.scout.dev.jetty.test.affix</artifactId>
-        <version>5.2.0-SNAPSHOT</version>
+        <version>6.0.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
@@ -369,8 +361,8 @@
 
       <dependency>
         <groupId>org.apache.commons</groupId>
-        <artifactId>commons-math</artifactId>
-        <version>2.2</version>
+        <artifactId>commons-math3</artifactId>
+        <version>3.5</version>
       </dependency>
 
       <!-- Dev Dependencies -->
@@ -390,7 +382,7 @@
         <version>${jetty.version}</version>
       </dependency>
 
-      <!-- Transient Dependencies -->
+      <!-- Transitive Dependencies -->
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-core</artifactId>
@@ -468,11 +460,6 @@
       </dependency>
       <dependency>
         <groupId>org.apache.xmlgraphics</groupId>
-        <artifactId>batik-js</artifactId>
-        <version>1.7</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.xmlgraphics</groupId>
         <artifactId>batik-parser</artifactId>
         <version>1.7</version>
       </dependency>
@@ -509,7 +496,7 @@
       <dependency>
         <groupId>org.objenesis</groupId>
         <artifactId>objenesis</artifactId>
-        <version>2.1</version>
+        <version>2.2</version>
       </dependency>
       <dependency>
         <groupId>org.ow2.asm</groupId>
@@ -661,7 +648,7 @@
   <scm>
     <connection>scm:git:git://git.eclipse.org/gitroot/scout/org.eclipse.scout.rt.git</connection>
     <developerConnection>scm:git:ssh://${eclipse_gerrit_username}@git.eclipse.org:29418/scout/org.eclipse.scout.rt</developerConnection>
-    <tag>releases/5.2.x</tag>
+    <tag>releases/6.0.x</tag>
     <url>http://git.eclipse.org/c/scout/org.eclipse.scout.rt.git/</url>
   </scm>
 
diff --git a/pom.xml b/pom.xml
index a1d505b..eadb0cd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
 
   <groupId>org.eclipse.scout.rt</groupId>
   <artifactId>org.eclipse.scout.rt-root</artifactId>
-  <version>5.2.0</version>
+  <version>6.0.0</version>
   <packaging>pom</packaging>
   <name>Eclipse Scout RT ROOT Module</name>