diff options
37 files changed, 3133 insertions, 279 deletions
diff --git a/GWT development mode for vaadin.launch b/GWT development mode for vaadin.launch new file mode 100644 index 0000000000..5195348bf5 --- /dev/null +++ b/GWT development mode for vaadin.launch @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/vaadin"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry externalArchive="/Users/jouni/.ivy2/cache/com.google.gwt/gwt-dev/jars/gwt-dev-2.4.0.jar" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry externalArchive="/Users/jouni/.ivy2/cache/com.google.gwt/gwt-user/jars/gwt-user-2.4.0.jar" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="vaadin"/> </runtimeClasspathEntry> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/src" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/tests/testbench" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/tests/client-side" path="3" type="2"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/vaadin/tests/server-side" path="3" type="2"/> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-noserver -war WebContent/VAADIN/widgetsets com.vaadin.terminal.gwt.DefaultWidgetSet -startupUrl http://localhost:8080/vaadin -bindAddress 0.0.0.0"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="vaadin"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512M -XX:MaxPermSize=256M"/> +<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="/Users/jouni/Documents/Work/Dev/Vaadin/vaadin"/> +</launchConfiguration> diff --git a/WebContent/VAADIN/themes/base/base.scss b/WebContent/VAADIN/themes/base/base.scss index 58f0c32af7..efe6e0cd05 100644 --- a/WebContent/VAADIN/themes/base/base.scss +++ b/WebContent/VAADIN/themes/base/base.scss @@ -1,6 +1,7 @@ @import "absolutelayout/absolutelayout.scss"; @import "accordion/accordion.scss"; @import "button/button.scss"; +@import "boxlayout/boxlayout.scss"; @import "caption/caption.scss"; @import "common/common.scss"; @import "csslayout/csslayout.scss"; diff --git a/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css new file mode 100644 index 0000000000..f899e8f4ac --- /dev/null +++ b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.css @@ -0,0 +1,167 @@ +/* +TODO +- separate styles to proper places +- decide a good class name structure for core layouts (e.g. 'v-layout', 'v-vertical', 'v-grid' etc.) +- use !important in carefully selected places to prevent accidental layout breakage by custom theming (e.g. alignments should be forced) + +*/ + +.v-boxlayout.v-margin-top {padding-top: 12px;} +.v-boxlayout.v-margin-right {padding-right: 12px;} +.v-boxlayout.v-margin-bottom {padding-bottom: 12px;} +.v-boxlayout.v-margin-left {padding-left: 12px;} + +.v-spacing { + width: 6px; + height: 6px; +} + +.v-boxlayout { + display: inline-block; +} + +div.v-boxlayout.v-horizontal.v { + white-space: nowrap; +} + +.v-boxlayout > .v-expand { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 100%; +} + +.v-slot, +.v-spacing { + display: inline-block; + white-space: normal; + vertical-align: top; +} + +/* Clear any floats inside the slot, to prevent unwanted collapsing */ +.v-vertical > .v-slot:after { + content: ""; + display: inline-block; + clear: both; + width: 0; + height: 0; + overflow: hidden; +} + +.v-vertical > .v-slot, +.v-vertical > .v-expand > .v-slot { + display: block; + clear: both; +} + +.v-horizontal > .v-slot, +.v-horizontal > .v-expand > .v-slot { + height: 100%; +} + +.v-vertical > .v-spacing, +.v-vertical > .v-expand > .v-spacing { + width: 0; + display: block; + clear: both; +} + +.v-horizontal > .v-spacing, +.v-horizontal > .v-expand > .v-spacing { + height: 0; +} + +.v-align-middle:before, +.v-align-bottom:before, +.v-expand > .v-align-middle:before, +.v-expand > .v-align-bottom:before { + content: ""; + display: inline-block; + height: 100%; + vertical-align: middle; + width: 0; +} + +.v-align-middle, +.v-align-bottom { + white-space: nowrap; +} + +.v-align-middle > .v, +.v-align-bottom > .v { + display: inline-block; +} + +.v-align-middle, +.v-align-middle > .v { + vertical-align: middle; +} + +.v-align-bottom, +.v-align-bottom > .v { + vertical-align: bottom; +} + +.v-align-center { + text-align: center; +} + +.v-align-center > .v { + margin-left: auto; + margin-right: auto; +} + +.v-align-right { + text-align: right; +} + +.v-align-right > .v { + margin-left: auto; +} + +.v-has-caption, +.v-has-caption > .v-caption { + display: inline-block; /* Force natural width to zero */ +} + +.v-caption { + overflow: visible; + vertical-align: middle; +} + +.v-caption-on-left, +.v-caption-on-right { + white-space: nowrap; +} + +.v-caption-on-top > .v-caption, +.v-caption-on-bottom > .v-caption { + display: block; +} + +.v-caption-on-left > .v-caption { + padding-right: .5em; +} + +.v-caption-on-right > .v-caption { + padding-left: .5em; +} + +.v-caption-on-left > .v, +.v-caption-on-right > .v { + display: inline-block; + vertical-align: middle; +} + +.v-has-caption.v-has-width > .v { + width: 100% !important; +} + +.v-has-caption.v-has-height > .v { + height: 100% !important; +} + +.v-errorindicator { + vertical-align: middle; +}
\ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/boxlayout/boxlayout.scss b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.scss new file mode 100644 index 0000000000..ef0f021a0a --- /dev/null +++ b/WebContent/VAADIN/themes/base/boxlayout/boxlayout.scss @@ -0,0 +1,171 @@ +/* +TODO +- separate styles to proper places +- decide a good class name structure for core layouts (e.g. 'v-layout', 'v-vertical', 'v-grid' etc.) +- use !important in carefully selected places to prevent accidental layout breakage by custom theming (e.g. alignments should be forced) + +*/ + +@mixin base-boxlayout { + +.v-boxlayout.v-margin-top {padding-top: 12px;} +.v-boxlayout.v-margin-right {padding-right: 12px;} +.v-boxlayout.v-margin-bottom {padding-bottom: 12px;} +.v-boxlayout.v-margin-left {padding-left: 12px;} + +.v-spacing { + width: 6px; + height: 6px; +} + +.v-boxlayout { + display: inline-block; +} + +div.v-boxlayout.v-horizontal.v { + white-space: nowrap; +} + +.v-boxlayout > .v-expand { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 100%; +} + +.v-slot, +.v-spacing { + display: inline-block; + white-space: normal; + vertical-align: top; +} + +/* Clear any floats inside the slot, to prevent unwanted collapsing */ +.v-vertical > .v-slot:after { + content: ""; + display: inline-block; + clear: both; + width: 0; + height: 0; + overflow: hidden; +} + +.v-vertical > .v-slot, +.v-vertical > .v-expand > .v-slot { + display: block; + clear: both; +} + +.v-horizontal > .v-slot, +.v-horizontal > .v-expand > .v-slot { + height: 100%; +} + +.v-vertical > .v-spacing, +.v-vertical > .v-expand > .v-spacing { + width: 0; + display: block; + clear: both; +} + +.v-horizontal > .v-spacing, +.v-horizontal > .v-expand > .v-spacing { + height: 0; +} + +.v-align-middle:before, +.v-align-bottom:before, +.v-expand > .v-align-middle:before, +.v-expand > .v-align-bottom:before { + content: ""; + display: inline-block; + height: 100%; + vertical-align: middle; + width: 0; +} + +.v-align-middle, +.v-align-bottom { + white-space: nowrap; +} + +.v-align-middle > .v, +.v-align-bottom > .v { + display: inline-block; +} + +.v-align-middle, +.v-align-middle > .v { + vertical-align: middle; +} + +.v-align-bottom, +.v-align-bottom > .v { + vertical-align: bottom; +} + +.v-align-center { + text-align: center; +} + +.v-align-center > .v { + margin-left: auto; + margin-right: auto; +} + +.v-align-right { + text-align: right; +} + +.v-align-right > .v { + margin-left: auto; +} + +.v-has-caption, +.v-has-caption > .v-caption { + display: inline-block; /* Force natural width to zero */ +} + +.v-caption { + overflow: visible; + vertical-align: middle; +} + +.v-caption-on-left, +.v-caption-on-right { + white-space: nowrap; +} + +.v-caption-on-top > .v-caption, +.v-caption-on-bottom > .v-caption { + display: block; +} + +.v-caption-on-left > .v-caption { + padding-right: .5em; +} + +.v-caption-on-right > .v-caption { + padding-left: .5em; +} + +.v-caption-on-left > .v, +.v-caption-on-right > .v { + display: inline-block; + vertical-align: middle; +} + +.v-has-caption.v-has-width > .v { + width: 100% !important; +} + +.v-has-caption.v-has-height > .v { + height: 100% !important; +} + +.v-errorindicator { + vertical-align: middle; +} + +}
\ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/button/button.scss b/WebContent/VAADIN/themes/base/button/button.scss index 1d3c4abec1..a9e7867268 100644 --- a/WebContent/VAADIN/themes/base/button/button.scss +++ b/WebContent/VAADIN/themes/base/button/button.scss @@ -6,7 +6,7 @@ .v-button { display: inline-block; zoom: 1; - text-align: center; + text-align: center !important; text-decoration: none; border: 2px outset #ddd; background: #eee; @@ -23,7 +23,6 @@ user-select: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; - -ms-box-sizing: border-box; box-sizing: border-box; } @@ -59,7 +58,7 @@ .v-button-link, .v-nativebutton-link { border: none; - text-align: left; + text-align: left !important; background: transparent; padding: 0; color: inherit; @@ -86,7 +85,7 @@ * NativeButton styles (html button element) * -------------------------------------- */ .v-nativebutton { - text-align: center; + text-align: center !important; cursor: pointer; white-space: nowrap; margin: 0; @@ -160,4 +159,4 @@ } */ -}
\ No newline at end of file +} diff --git a/WebContent/VAADIN/themes/base/csslayout/csslayout.scss b/WebContent/VAADIN/themes/base/csslayout/csslayout.scss index 7bd26d4197..c2c1b698ad 100644 --- a/WebContent/VAADIN/themes/base/csslayout/csslayout.scss +++ b/WebContent/VAADIN/themes/base/csslayout/csslayout.scss @@ -3,6 +3,10 @@ .v-csslayout { overflow: hidden; } +/* More specific selector to override 'v-connector' */ +div.v-csslayout { + display: block; +} .v-csslayout-margin, .v-csslayout-container { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; diff --git a/WebContent/VAADIN/themes/base/datefield/datefield.scss b/WebContent/VAADIN/themes/base/datefield/datefield.scss index 12ce3df980..bf95baa3e6 100644 --- a/WebContent/VAADIN/themes/base/datefield/datefield.scss +++ b/WebContent/VAADIN/themes/base/datefield/datefield.scss @@ -2,7 +2,7 @@ .v-datefield { white-space: nowrap; - float: left; /* Force minimum width */ + display: inline-block; /* Force minimum width */ } .v-datefield-textfield { vertical-align: top; @@ -90,4 +90,4 @@ } */ -}
\ No newline at end of file +} diff --git a/WebContent/VAADIN/themes/base/label/label.scss b/WebContent/VAADIN/themes/base/label/label.scss index e4f3f89062..ae1539acc9 100644 --- a/WebContent/VAADIN/themes/base/label/label.scss +++ b/WebContent/VAADIN/themes/base/label/label.scss @@ -4,4 +4,8 @@ overflow: hidden; } +.v-label.v-has-width { + white-space: normal; +} + }
\ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/menubar/menubar.scss b/WebContent/VAADIN/themes/base/menubar/menubar.scss index 79b94a63af..512a8ee1d5 100644 --- a/WebContent/VAADIN/themes/base/menubar/menubar.scss +++ b/WebContent/VAADIN/themes/base/menubar/menubar.scss @@ -1,7 +1,7 @@ @mixin base-menubar { .v-menubar { - float: left; /* Force minimum width */ + display: inline-block; white-space: nowrap; overflow: hidden; } @@ -95,4 +95,4 @@ background: transparent url(img/check.gif) no-repeat left; } -}
\ No newline at end of file +} diff --git a/WebContent/VAADIN/themes/base/paintable/paintable.scss b/WebContent/VAADIN/themes/base/paintable/paintable.scss index 87431ee225..92f30604ff 100644 --- a/WebContent/VAADIN/themes/base/paintable/paintable.scss +++ b/WebContent/VAADIN/themes/base/paintable/paintable.scss @@ -1,9 +1,12 @@ @mixin base-paintable { -.v-connector { +.v { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + text-align: left; + display: inline-block; + white-space: normal; } }
\ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/styles.scss b/WebContent/VAADIN/themes/base/styles.scss index 89f76947f8..7a650d0818 100644 --- a/WebContent/VAADIN/themes/base/styles.scss +++ b/WebContent/VAADIN/themes/base/styles.scss @@ -3,7 +3,9 @@ // @include base-app; // everything included from base theme -// other themes should enclose corresponding definitions in theme selectors +// other themes should enclose corresponding definitions in theme selectors + +@include base-paintable; @include base-absolutelayout; @include base-accordion; @@ -13,6 +15,7 @@ // here for now to preserve old semantics @include base-common; +@include base-boxlayout; @include base-csslayout; @include base-customcomponent; @include base-customlayout; @@ -27,7 +30,6 @@ @include base-menubar; @include base-notification; @include base-orderedlayout; -@include base-paintable; @include base-panel; @include base-popupview; @include base-progressindicator; diff --git a/WebContent/VAADIN/themes/base/textfield/textfield.scss b/WebContent/VAADIN/themes/base/textfield/textfield.scss index b8e54e6887..dc6a4d9aa3 100644 --- a/WebContent/VAADIN/themes/base/textfield/textfield.scss +++ b/WebContent/VAADIN/themes/base/textfield/textfield.scss @@ -7,6 +7,7 @@ } .v-textarea { resize: none; + white-space: pre-wrap; } .v-textfield-focus, .v-textarea-focus { diff --git a/WebContent/VAADIN/themes/reindeer/common/common.scss b/WebContent/VAADIN/themes/reindeer/common/common.scss index 86f546a6a2..3971f1777d 100644 --- a/WebContent/VAADIN/themes/reindeer/common/common.scss +++ b/WebContent/VAADIN/themes/reindeer/common/common.scss @@ -43,7 +43,7 @@ } .v-errorindicator { width: 13px; - height: 16px; + height: 14px; background: transparent url(../common/icons/error.png) no-repeat 50%; } .v-tooltip { diff --git a/WebContent/VAADIN/themes/reindeer/layouts/layouts.scss b/WebContent/VAADIN/themes/reindeer/layouts/layouts.scss index 832e480010..e1bef65f1e 100644 --- a/WebContent/VAADIN/themes/reindeer/layouts/layouts.scss +++ b/WebContent/VAADIN/themes/reindeer/layouts/layouts.scss @@ -2,22 +2,26 @@ .v-orderedlayout-margin-top, .v-horizontallayout-margin-top, -.v-verticallayout-margin-top { +.v-verticallayout-margin-top, +.v-boxlayout.v-margin-top { padding-top: 18px; } .v-orderedlayout-margin-right, .v-horizontallayout-margin-right, -.v-verticallayout-margin-right { +.v-verticallayout-margin-right, +.v-boxlayout.v-margin-right { padding-right: 18px; } .v-orderedlayout-margin-bottom, .v-horizontallayout-margin-bottom, -.v-verticallayout-margin-bottom { +.v-verticallayout-margin-bottom, +.v-boxlayout.v-margin-bottom { padding-bottom: 18px; } .v-orderedlayout-margin-left, .v-horizontallayout-margin-left, -.v-verticallayout-margin-left { +.v-verticallayout-margin-left, +.v-boxlayout.v-margin-left { padding-left: 18px; } .v-orderedlayout-spacing-on, @@ -26,6 +30,10 @@ padding-top: 7px; padding-left: 6px; } +.v-spacing { + height: 7px; + width: 6px; +} /* Different for historical reasons: previously was inherited directly from Base theme */ /* TODO unify these values in version 7 */ .v-gridlayout-margin-top { diff --git a/WebContent/VAADIN/themes/runo/orderedlayout/orderedlayout.scss b/WebContent/VAADIN/themes/runo/orderedlayout/orderedlayout.scss index a8c85d9af6..37ae0279b6 100644 --- a/WebContent/VAADIN/themes/runo/orderedlayout/orderedlayout.scss +++ b/WebContent/VAADIN/themes/runo/orderedlayout/orderedlayout.scss @@ -3,25 +3,29 @@ .v-orderedlayout-margin-top, .v-horizontallayout-margin-top, .v-verticallayout-margin-top, -.v-csslayout-margin-top { +.v-csslayout-margin-top, +.v-boxlayout.v-margin-top { padding-top: 15px; } .v-orderedlayout-margin-right, .v-horizontallayout-margin-right, .v-verticallayout-margin-right, -.v-csslayout-margin-right { +.v-csslayout-margin-right, +.v-boxlayout.v-margin-right { padding-right: 18px; } .v-orderedlayout-margin-bottom, .v-horizontallayout-margin-bottom, .v-verticallayout-margin-bottom, -.v-csslayout-margin-bottom { +.v-csslayout-margin-bottom, +.v-boxlayout.v-margin-bottom { padding-bottom: 15px; } .v-orderedlayout-margin-left, .v-horizontallayout-margin-left, .v-verticallayout-margin-left, -.v-csslayout-margin-left { +.v-csslayout-margin-left, +.v-boxlayout.v-margin-left { padding-left: 18px; } .v-orderedlayout-spacing-on, @@ -30,6 +34,10 @@ padding-top: 8px; padding-left: 8px; } +.v-spacing { + width: 8px; + height: 8px; +} .v-verticallayout-darker, .v-horizontallayout-darker, .v-gridlayout-darker, diff --git a/WebContent/VAADIN/themes/tests-components/styles.css b/WebContent/VAADIN/themes/tests-components/styles.css index c38f32f132..45a96b6d16 100644 --- a/WebContent/VAADIN/themes/tests-components/styles.css +++ b/WebContent/VAADIN/themes/tests-components/styles.css @@ -36,4 +36,21 @@ .v-table-row-tables-test-cell-style-red-row, .v-table-cell-content-tables-test-cell-style-red-row { background: #f00; +} + +.v-boxlayout.test { + border: 1px solid #ddd; +} + +.v-boxlayout.test .target { + outline: 2px dashed blue; +} + +.fieldset { + padding: .5em 1em; + -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.2); + box-shadow: inset 0 1px 2px rgba(0,0,0,.2); + border-radius: .5em; + background: rgba(0,0,0,.02); }
\ No newline at end of file diff --git a/WebContent/layout-resize-test.html b/WebContent/layout-resize-test.html new file mode 100644 index 0000000000..b798402bb7 --- /dev/null +++ b/WebContent/layout-resize-test.html @@ -0,0 +1,41 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>LayoutResizeTest opener</title> +</head> +<body> + +<button onclick="testV7()">Open LayoutResizeTest (Vaadin 7)</button><br> +<button onclick="testV6()">Open LayoutResizeTest (Vaadin 6)</button><br> +<button onclick="resize1()">Resize to 650x450</button><br> +<button onclick="resize2()">Resize to 950x750</button> + + +<script> +var win1, win2; + +function testV7() { + win1 = window.open('/vaadin/run/com.vaadin.tests.components.orderedlayout.LayoutResizeTest?restartApplication&debug','layoutResizeTestV7','width=800,height=600'); +} + +function testV6() { + win2 = window.open('/LayoutBenchmark/?restartApplication&debug','layoutResizeTestV6','width=800,height=600'); +} + +function resize1() { + if(win1) + win1.resizeTo(650,450); + if(win2) + win2.resizeTo(650,450); +} + +function resize2() { + if(win1) + win1.resizeTo(950,750); + if(win2) + win2.resizeTo(950,750); +} +</script> +</body> +</html>
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java index f1a2b9b925..7c75913126 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ b/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java @@ -30,6 +30,7 @@ import com.vaadin.shared.communication.SharedState; import com.vaadin.terminal.gwt.client.ui.SubPartAware; import com.vaadin.terminal.gwt.client.ui.UI.VUI; import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout; +import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout; import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout; import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetPanel; import com.vaadin.terminal.gwt.client.ui.window.VWindow; @@ -498,6 +499,14 @@ public class ComponentLocator { // is always 0 which indicates the widget in the active tab widgetPosition = 0; } + if ("VVerticalLayout".equals(widgetClassName) + || "VHorizontalLayout".equals(widgetClassName)) { + widgetClassName = "VBoxLayout"; + } + if (w instanceof VBoxLayout + && "ChildComponentContainer".equals(widgetClassName)) { + widgetClassName = "VBoxLayout$Slot"; + } /* * The new grid and ordered layotus do not contain diff --git a/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java b/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java index 7662ba634b..6e17dcfab5 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java +++ b/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java @@ -95,19 +95,19 @@ public class ComputedStyle { // If we're not dealing with a regular pixel number // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = cs.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = cs.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java index c00f9bd865..3deb581848 100644 --- a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ b/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java @@ -215,7 +215,7 @@ public class LayoutManager { } } - private void layoutLater() { + public void layoutLater() { if (!layoutPending) { layoutPending = true; layoutTimer.schedule(100); @@ -1032,6 +1032,50 @@ public class LayoutManager { } /** + * Gets the combined top & bottom margin of the given element, provided that + * they have been measured. These elements are guaranteed to be measured: + * <ul> + * <li>ManagedLayotus and their child Connectors + * <li>Elements for which there is at least one ElementResizeListener + * <li>Elements for which at least one ManagedLayout has registered a + * dependency + * </ul> + * + * A negative number is returned if the element has not been measured. If 0 + * is returned, it might indicate that the element is not attached to the + * DOM. + * + * @param element + * the element to get the measured margin for + * @return the measured top+bottom margin of the element in pixels. + */ + public int getMarginHeight(Element element) { + return getMarginTop(element) + getMarginBottom(element); + } + + /** + * Gets the combined left & right margin of the given element, provided that + * they have been measured. These elements are guaranteed to be measured: + * <ul> + * <li>ManagedLayotus and their child Connectors + * <li>Elements for which there is at least one ElementResizeListener + * <li>Elements for which at least one ManagedLayout has registered a + * dependency + * </ul> + * + * A negative number is returned if the element has not been measured. If 0 + * is returned, it might indicate that the element is not attached to the + * DOM. + * + * @param element + * the element to get the measured margin for + * @return the measured left+right margin of the element in pixels. + */ + public int getMarginWidth(Element element) { + return getMarginLeft(element) + getMarginRight(element); + } + + /** * Registers the outer height (including margins, borders and paddings) of a * component. This can be used as an optimization by ManagedLayouts; by * informing the LayoutManager about what size a component will have, the diff --git a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java index d988c5f4a2..891e45edb5 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java @@ -87,6 +87,15 @@ public interface ServerConnector extends Connector { public HandlerRegistration addStateChangeHandler(StateChangeHandler handler); /** + * Removes a handler that is called whenever any part of the state has been + * updated by the server. + * + * @param handler + * The handler that should be removed. + */ + public void removeStateChangeHandler(StateChangeHandler handler); + + /** * Adds a handler that is called whenever the given part of the state has * been updated by the server. * @@ -102,6 +111,19 @@ public interface ServerConnector extends Connector { StateChangeHandler handler); /** + * Removes a handler that is called whenever any part of the state has been + * updated by the server. + * + * @param propertyName + * the name of the property for which the handler should be + * called + * @param handler + * The handler that should be removed. + */ + public void removeStateChangeHandler(String propertyName, + StateChangeHandler handler); + + /** * Sends the given event to all registered handlers. * * @param event diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java index f36107e947..14d7f4007e 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java @@ -69,8 +69,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector getConnection().getVTooltip().connectHandlersToWidget(getWidget()); - // Set v-connector style names for the widget - getWidget().setStyleName("v-connector", true); + // Set the core 'v' style name for the widget + getWidget().setStyleName("v", true); } /** diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java index b861ade0bf..fabd750f8b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java @@ -1,4 +1,4 @@ -/* +/* * Copyright 2011 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -45,7 +45,7 @@ import com.vaadin.terminal.gwt.client.metadata.TypeData; * */ public abstract class AbstractConnector implements ServerConnector, - StateChangeHandler { +StateChangeHandler { private ApplicationConnection connection; private String id; @@ -200,12 +200,24 @@ public abstract class AbstractConnector implements ServerConnector, } @Override + public void removeStateChangeHandler(StateChangeHandler handler) { + ensureHandlerManager().removeHandler(StateChangeEvent.TYPE, handler); + } + + @Override public HandlerRegistration addStateChangeHandler(String propertyName, StateChangeHandler handler) { return ensureHandlerManager(propertyName).addHandler( StateChangeEvent.TYPE, handler); } + @Override + public void removeStateChangeHandler(String propertyName, + StateChangeHandler handler) { + ensureHandlerManager(propertyName).removeHandler(StateChangeEvent.TYPE, + handler); + } + private HandlerManager ensureHandlerManager(String propertyName) { if (statePropertyHandlerManagers == null) { statePropertyHandlerManagers = new HashMap<String, HandlerManager>(); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java new file mode 100644 index 0000000000..bbf9aed570 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java @@ -0,0 +1,598 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.orderedlayout; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.Element; +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.ui.AlignmentInfo; +import com.vaadin.shared.ui.LayoutClickRpc; +import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; +import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; +import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.communication.RpcProxy; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; +import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; +import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector; +import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; +import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent; +import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener; +import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout.CaptionPosition; +import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout.Slot; + +public abstract class AbstractBoxLayoutConnector extends + AbstractLayoutConnector /* implements PostLayoutListener */{ + + AbstractOrderedLayoutServerRpc rpc; + + private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( + this) { + + @Override + protected ComponentConnector getChildComponent(Element element) { + return Util.getConnectorForElement(getConnection(), getWidget(), + element); + } + + @Override + protected LayoutClickRpc getLayoutClickRPC() { + return rpc; + }; + + }; + + @Override + public void init() { + super.init(); + rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this); + getWidget().setLayoutManager(getLayoutManager()); + } + + @Override + public AbstractOrderedLayoutState getState() { + return (AbstractOrderedLayoutState) super.getState(); + } + + @Override + public VBoxLayout getWidget() { + return (VBoxLayout) super.getWidget(); + } + + /** + * For bookkeeping. Used to determine if extra calculations are needed for + * horizontal layout. + */ + private HashSet<ComponentConnector> hasVerticalAlignment = new HashSet<ComponentConnector>(); + + /** + * For bookkeeping. Used to determine if extra calculations are needed for + * horizontal layout. + */ + private HashSet<ComponentConnector> hasRelativeHeight = new HashSet<ComponentConnector>(); + + /** + * For bookkeeping. Used to determine if extra calculations are needed for + * horizontal layout. + */ + private HashSet<ComponentConnector> hasExpandRatio = new HashSet<ComponentConnector>(); + + /** + * For bookkeeping. Used in extra calculations for horizontal layout. + */ + private HashSet<Element> needsMeasure = new HashSet<Element>(); + + /** + * For bookkeeping. Used in extra calculations for horizontal layout. + */ + // private HashMap<Element, Integer> childElementHeight = new + // HashMap<Element, Integer>(); + + /** + * For bookkeeping. Used in extra calculations for horizontal layout. + */ + private HashMap<Element, Integer> childCaptionElementHeight = new HashMap<Element, Integer>(); + + public void updateCaption(ComponentConnector child) { + Slot slot = getWidget().getSlot(child); + + String caption = child.getState().getCaption(); + String iconUrl = child.getState().getIcon() != null ? child.getState() + .getIcon().getURL() : null; + List<String> styles = child.getState().getStyles(); + String error = child.getState().getErrorMessage(); + boolean showError = error != null; + if (child.getState() instanceof AbstractFieldState) { + AbstractFieldState abstractFieldState = (AbstractFieldState) child + .getState(); + showError = showError && !abstractFieldState.isHideErrors(); + } + boolean required = false; + if (child instanceof AbstractFieldConnector) { + required = ((AbstractFieldConnector) child).isRequired(); + } + boolean enabled = child.getState().isEnabled(); + + slot.setCaption(caption, iconUrl, styles, error, showError, required, + enabled); + + slot.setRelativeWidth(child.isRelativeWidth()); + slot.setRelativeHeight(child.isRelativeHeight()); + + if (slot.hasCaption()) { + CaptionPosition pos = slot.getCaptionPosition(); + getLayoutManager().addElementResizeListener( + slot.getCaptionElement(), slotCaptionResizeListener); + if (child.isRelativeHeight() + && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) { + getWidget().updateCaptionOffset(slot.getCaptionElement()); + } else if (child.isRelativeWidth() + && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) { + getWidget().updateCaptionOffset(slot.getCaptionElement()); + } + } else { + childCaptionElementHeight.remove(child.getWidget().getElement()); + } + + updateLayoutHeight(); + + if (needsExpand()) { + updateExpand(); + } + } + + @Override + public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { + super.onConnectorHierarchyChange(event); + + List<ComponentConnector> previousChildren = event.getOldChildren(); + int currentIndex = 0; + VBoxLayout layout = getWidget(); + + for (ComponentConnector child : getChildComponents()) { + Slot slot = layout.getSlot(child); + if (slot.getParent() != layout) { + child.addStateChangeHandler(childStateChangeHandler); + } + layout.addOrMoveSlot(slot, currentIndex++); + } + + for (ComponentConnector child : previousChildren) { + if (child.getParent() != this) { + Slot slot = layout.getSlot(child); + hasVerticalAlignment.remove(child); + hasRelativeHeight.remove(child); + hasExpandRatio.remove(child); + needsMeasure.remove(child.getWidget().getElement()); + // childElementHeight.remove(child.getWidget().getElement()); + childCaptionElementHeight + .remove(child.getWidget().getElement()); + getLayoutManager().removeElementResizeListener( + child.getWidget().getElement(), + childComponentResizeListener); + if (slot.hasCaption()) { + getLayoutManager() + .removeElementResizeListener( + slot.getCaptionElement(), + slotCaptionResizeListener); + } + if (slot.getSpacingElement() != null) { + getLayoutManager().removeElementResizeListener( + slot.getSpacingElement(), spacingResizeListener); + } + child.removeStateChangeHandler(childStateChangeHandler); + layout.removeSlot(child.getWidget()); + } + } + + // If some component is added/removed, we need to recalculate the expand + if (needsExpand()) { + updateExpand(); + } else { + getWidget().clearExpand(); + } + + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + + clickEventHandler.handleEventHandlerRegistration(); + getWidget().setMargin(new VMarginInfo(getState().getMarginsBitmask())); + getWidget().setSpacing(getState().isSpacing()); + + hasExpandRatio.clear(); + hasVerticalAlignment.clear(); + hasRelativeHeight.clear(); + needsMeasure.clear(); + + boolean equalExpandRatio = getWidget().vertical ? !isUndefinedHeight() + : !isUndefinedWidth(); + for (ComponentConnector child : getChildComponents()) { + double expandRatio = getState().getChildData().get(child) + .getExpandRatio(); + if (expandRatio > 0) { + equalExpandRatio = false; + break; + } + } + + for (ComponentConnector child : getChildComponents()) { + Slot slot = getWidget().getSlot(child); + + AlignmentInfo alignment = new AlignmentInfo(getState() + .getChildData().get(child).getAlignmentBitmask()); + slot.setAlignment(alignment); + + double expandRatio = getState().getChildData().get(child) + .getExpandRatio(); + if (equalExpandRatio) { + expandRatio = 1; + } else if (expandRatio == 0) { + expandRatio = -1; + } + slot.setExpandRatio(expandRatio); + + // Bookkeeping to identify special cases that need extra + // calculations + if (alignment.isVerticalCenter() || alignment.isBottom()) { + hasVerticalAlignment.add(child); + } + + if (expandRatio > 0) { + hasExpandRatio.add(child); + } + + // if (child.getState().isRelativeHeight()) { + // hasRelativeHeight.add(child); + // } else { + // needsMeasure.add(child.getWidget().getElement()); + // } + } + + updateAllSlotListeners(); + + updateLayoutHeight(); + } + + StateChangeHandler childStateChangeHandler = new StateChangeHandler() { + public void onStateChanged(StateChangeEvent stateChangeEvent) { + + ComponentConnector child = (ComponentConnector) stateChangeEvent + .getConnector(); + + // We need to update the slot size if the component size is changed + // to relative + Slot slot = getWidget().getSlot(child); + slot.setRelativeWidth(child.isRelativeWidth()); + slot.setRelativeHeight(child.isRelativeHeight()); + + // For relative sized widgets, we need to set the caption offset + // if (slot.hasCaption()) { + // CaptionPosition pos = slot.getCaptionPosition(); + // if (child.isRelativeHeight() + // && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) + // { + // getWidget().updateCaptionOffset(slot.getCaptionElement()); + // } else if (child.isRelativeWidth() + // && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) + // { + // getWidget().updateCaptionOffset(slot.getCaptionElement()); + // } + // } + + updateSlotListeners(child); + // updateAllSlotListeners(); + + updateLayoutHeight(); + } + }; + + private boolean needsFixedHeight() { + if (!getWidget().vertical + && isUndefinedHeight() + && (hasRelativeHeight.size() > 0 || (hasVerticalAlignment + .size() > 0 && hasVerticalAlignment.size() < getChildren() + .size()))) { + return true; + } + return false; + } + + private boolean needsExpand() { + boolean canApplyExpand = (getWidget().vertical && !isUndefinedHeight()) + || (!getWidget().vertical && !isUndefinedWidth()); + return hasExpandRatio.size() > 0 && canApplyExpand; + } + + private void updateAllSlotListeners() { + for (ComponentConnector child : getChildComponents()) { + updateSlotListeners(child); + } + // if (needsFixedHeight()) { + // getWidget().clearHeight(); + // setLayoutHeightListener(true); + // getLayoutManager().setNeedsMeasure(AbstractBoxLayoutConnector.this); + // } else { + // setLayoutHeightListener(false); + // } + } + + /** + * Add/remove necessary ElementResizeListeners for one slot. This should be + * called after each update to the slot's or it's widget. + */ + private void updateSlotListeners(ComponentConnector child) { + Slot slot = getWidget().getSlot(child); + + // Clear all possible listeners first + dontListen(slot.getWidget().getElement(), childComponentResizeListener); + if (slot.hasCaption()) { + dontListen(slot.getCaptionElement(), slotCaptionResizeListener); + } + if (slot.hasSpacing()) { + dontListen(slot.getSpacingElement(), spacingResizeListener); + } + + // Add all necessary listeners + if (needsFixedHeight()) { + listen(slot.getWidget().getElement(), childComponentResizeListener); + if (slot.hasCaption()) { + listen(slot.getCaptionElement(), slotCaptionResizeListener); + } + } else if ((child.isRelativeHeight() || child.isRelativeWidth()) + && slot.hasCaption()) { + // If the slot has caption, we need to listen for it's size changes + // in order to update the padding/margin offset for relative sized + // components + listen(slot.getCaptionElement(), slotCaptionResizeListener); + } + + if (needsExpand()) { + listen(slot.getWidget().getElement(), childComponentResizeListener); + if (slot.hasSpacing()) { + listen(slot.getSpacingElement(), spacingResizeListener); + } + } + + if (child.isRelativeHeight()) { + hasRelativeHeight.add(child); + needsMeasure.remove(child.getWidget().getElement()); + } else { + hasRelativeHeight.remove(child); + needsMeasure.add(child.getWidget().getElement()); + } + + } + + // public void postLayout() { + // if (needsFixedHeight()) { + // // Re-measure all elements that are available + // for (Element el : needsMeasure) { + // childElementHeight.put(el, getLayoutManager() + // .getOuterHeight(el)); + // + // Element captionElement = el.getParentElement() + // .getFirstChildElement().cast(); + // if (captionElement.getClassName().contains("v-caption")) { + // childCaptionElementHeight.put(el, getLayoutManager() + // .getOuterHeight(captionElement)); + // } + // } + // // System.out.println(" ### Child sizes: " + // // + childElementHeight.values().toString()); + // // System.out.println(" ### Caption sizes: " + // // + childCaptionElementHeight.values().toString()); + // + // int height = getMaxHeight() + // + getLayoutManager().getBorderHeight( + // getWidget().getElement()) + // + getLayoutManager().getPaddingHeight( + // getWidget().getElement()); + // getWidget().getElement().getStyle().setHeight(height, Unit.PX); + // } + // } + + // private ElementResizeListener layoutResizeListener = new + // ElementResizeListener() { + // public void onElementResize(ElementResizeEvent e) { + // updateLayoutHeight(); + // if (needsExpand() && (isUndefinedHeight() || isUndefinedWidth())) { + // updateExpand(); + // } + // } + // }; + + private ElementResizeListener slotCaptionResizeListener = new ElementResizeListener() { + public void onElementResize(ElementResizeEvent e) { + + // Get all needed element references + Element captionElement = (Element) e.getElement().cast(); + + // Caption position determines if the widget element is the first or + // last child inside the caption wrap + CaptionPosition pos = getWidget().getCaptionPositionFromElement( + (Element) captionElement.getParentElement().cast()); + + // The default is the last child + Element widgetElement = captionElement.getParentElement() + .getLastChild().cast(); + + // ...but if caption position is bottom or right, the widget is the + // first child + if (pos == CaptionPosition.BOTTOM || pos == CaptionPosition.RIGHT) { + widgetElement = captionElement.getParentElement() + .getFirstChildElement().cast(); + } + + if (captionElement == widgetElement) { + // Caption element already detached + dontListen(captionElement, slotCaptionResizeListener); + childCaptionElementHeight.remove(widgetElement); + return; + } + + String widgetWidth = widgetElement.getStyle().getWidth(); + String widgetHeight = widgetElement.getStyle().getHeight(); + + if (widgetHeight.endsWith("%") + && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) { + getWidget().updateCaptionOffset(captionElement); + } else if (widgetWidth.endsWith("%") + && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) { + getWidget().updateCaptionOffset(captionElement); + } + + int h = getLayoutManager().getOuterHeight(captionElement) + - getLayoutManager().getMarginHeight(captionElement); + childCaptionElementHeight.put(widgetElement, h); + + // if (needsFixedHeight()) { + // getWidget().clearHeight(); + // getLayoutManager().setNeedsMeasure( + // AbstractBoxLayoutConnector.this); + // } + + updateLayoutHeight(); + + if (needsExpand()) { + updateExpand(); + } + } + }; + + private ElementResizeListener childComponentResizeListener = new ElementResizeListener() { + public void onElementResize(ElementResizeEvent e) { + // int h = getLayoutManager().getOuterHeight(e.getElement()); + // childElementHeight.put((Element) e.getElement().cast(), h); + updateLayoutHeight(); + + if (needsExpand()) { + updateExpand(); + } + } + }; + + private ElementResizeListener spacingResizeListener = new ElementResizeListener() { + public void onElementResize(ElementResizeEvent e) { + if (needsExpand()) { + updateExpand(); + } + } + }; + + private void updateLayoutHeight() { + if (needsFixedHeight()) { + int h = getMaxHeight(); + h += getLayoutManager().getBorderHeight(getWidget().getElement()) + + getLayoutManager().getPaddingHeight( + getWidget().getElement()); + getWidget().getElement().getStyle().setHeight(h, Unit.PX); + getLayoutManager().setNeedsMeasure(this); + } + } + + private void updateExpand() { + // System.out.println("All sizes: " + // + childElementHeight.values().toString() + " - Caption sizes: " + // + childCaptionElementHeight.values().toString()); + getWidget().updateExpand(); + } + + private int getMaxHeight() { + int highestNonRelative = -1; + int highestRelative = -1; + + for (ComponentConnector child : getChildComponents()) { + // TODO would be more efficient to measure the slot element if both + // caption and child widget elements need to be measured. Keeping + // track of what to measure is the most difficult part of this + // layout. + Element el = child.getWidget().getElement(); + CaptionPosition pos = getWidget().getCaptionPositionFromElement( + (Element) el.getParentElement().cast()); + if (needsMeasure.contains(el)) { + int h = getLayoutManager().getOuterHeight(el); + String sHeight = el.getStyle().getHeight(); + // Only add the caption size to the height of the slot if + // coption position is top or bottom + if (childCaptionElementHeight.containsKey(el) + && (sHeight == null || !sHeight.endsWith("%")) + && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) { + h += childCaptionElementHeight.get(el); + } + if (h > highestNonRelative) { + highestNonRelative = h; + } + } else { + int h = getLayoutManager().getOuterHeight(el); + if (childCaptionElementHeight.containsKey(el) + && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) { + h += childCaptionElementHeight.get(el); + } + if (h > highestRelative) { + highestRelative = h; + } + } + } + return highestNonRelative > -1 ? highestNonRelative : highestRelative; + } + + @Override + public void onUnregister() { + // Cleanup all ElementResizeListeners + + // dontListen(getWidget().getElement(), layoutResizeListener); + + for (ComponentConnector child : getChildComponents()) { + Slot slot = getWidget().getSlot(child); + if (slot.hasCaption()) { + dontListen(slot.getCaptionElement(), slotCaptionResizeListener); + } + + if (slot.getSpacingElement() != null) { + dontListen(slot.getSpacingElement(), spacingResizeListener); + } + + dontListen(slot.getWidget().getElement(), + childComponentResizeListener); + } + + super.onUnregister(); + } + + // private void setLayoutHeightListener(boolean add) { + // if (add) { + // listen(getWidget().getElement(), layoutResizeListener); + // } else { + // dontListen(getWidget().getElement(), layoutResizeListener); + // if (!needsExpand()) { + // System.out.println("Clearing element sizes"); + // childElementHeight.clear(); + // childCaptionElementHeight.clear(); + // } + // } + // } + + /* + * Convenience methods + */ + + private void listen(Element el, ElementResizeListener listener) { + getLayoutManager().addElementResizeListener(el, listener); + } + + private void dontListen(Element el, ElementResizeListener listener) { + getLayoutManager().removeElementResizeListener(el, listener); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java new file mode 100644 index 0000000000..d18ea8a178 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java @@ -0,0 +1,19 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.orderedlayout; + +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; +import com.vaadin.ui.HorizontalLayout; + +@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER) +public class HorizontalBoxLayoutConnector extends AbstractBoxLayoutConnector { + + @Override + public void init() { + super.init(); + getWidget().setVertical(false); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java index 195622854d..f22b558afd 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java @@ -15,11 +15,8 @@ */ package com.vaadin.terminal.gwt.client.ui.orderedlayout; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.HorizontalLayout; -@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER) +//@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER) public class HorizontalLayoutConnector extends AbstractOrderedLayoutConnector { @Override diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java new file mode 100644 index 0000000000..dcc33a36b7 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java @@ -0,0 +1,757 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.orderedlayout; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.UIObject; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.shared.ui.AlignmentInfo; +import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.LayoutManager; + +public class VBoxLayout extends FlowPanel { + + public static final String CLASSNAME = "v-boxlayout"; + + private static final String ALIGN_CLASS_PREFIX = "v-align-"; + + protected boolean spacing = false; + + protected boolean vertical = true; + + protected boolean definedHeight = false; + + private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>(); + + private LayoutManager layoutManager; + + public VBoxLayout() { + setStyleName(CLASSNAME); + setVertical(true); + } + + public void setVertical(boolean isVertical) { + vertical = isVertical; + if (vertical) { + addStyleName("v-vertical"); + removeStyleName("v-horizontal"); + } else { + addStyleName("v-horizontal"); + removeStyleName("v-vertical"); + } + } + + public void addOrMoveSlot(Slot slot, int index) { + if (slot.getParent() == this) { + int currentIndex = getWidgetIndex(slot); + if (index == currentIndex) { + return; + } + } + insert(slot, index); + } + + @Override + protected void insert(Widget child, Element container, int beforeIndex, + boolean domInsert) { + // Validate index; adjust if the widget is already a child of this + // panel. + beforeIndex = adjustIndex(child, beforeIndex); + + // Detach new child. + child.removeFromParent(); + + // Logical attach. + getChildren().insert(child, beforeIndex); + + // Physical attach. + container = expandWrapper != null ? expandWrapper : getElement(); + if (domInsert) { + DOM.insertChild(container, child.getElement(), + spacing ? beforeIndex * 2 : beforeIndex); + } else { + DOM.appendChild(container, child.getElement()); + } + + // Adopt. + adopt(child); + } + + public Slot removeSlot(Widget widget) { + Slot slot = widgetToSlot.get(widget); + remove(slot); + widgetToSlot.remove(widget); + return slot; + } + + public Slot getSlot(ComponentConnector connector) { + Slot slot = widgetToSlot.get(connector.getWidget()); + if (slot == null) { + slot = new Slot(connector); + widgetToSlot.put(connector.getWidget(), slot); + } + return slot; + } + + public enum CaptionPosition { + TOP, RIGHT, BOTTOM, LEFT + } + + protected class Slot extends SimplePanel { + + private ComponentConnector connector; + + private Element spacer; + + private Element captionWrap; + private Element caption; + private Element captionText; + private Icon icon; + private Element errorIcon; + private Element requiredIcon; + + // Caption is placed after component unless there is some part which + // moves it above. + private CaptionPosition captionPosition = CaptionPosition.RIGHT; + + private AlignmentInfo alignment; + private double expandRatio = -1; + + public Slot(ComponentConnector connector) { + this.connector = connector; + setWidget(connector.getWidget()); + setStylePrimaryName("v-slot"); + } + + public AlignmentInfo getAlignment() { + return alignment; + } + + public void setAlignment(AlignmentInfo alignment) { + this.alignment = alignment; + + if (alignment.isHorizontalCenter()) { + addStyleName(ALIGN_CLASS_PREFIX + "center"); + removeStyleName(ALIGN_CLASS_PREFIX + "right"); + } else if (alignment.isRight()) { + addStyleName(ALIGN_CLASS_PREFIX + "right"); + removeStyleName(ALIGN_CLASS_PREFIX + "center"); + } else { + removeStyleName(ALIGN_CLASS_PREFIX + "right"); + removeStyleName(ALIGN_CLASS_PREFIX + "center"); + } + if (alignment.isVerticalCenter()) { + addStyleName(ALIGN_CLASS_PREFIX + "middle"); + removeStyleName(ALIGN_CLASS_PREFIX + "bottom"); + } else if (alignment.isBottom()) { + addStyleName(ALIGN_CLASS_PREFIX + "bottom"); + removeStyleName(ALIGN_CLASS_PREFIX + "middle"); + } else { + removeStyleName(ALIGN_CLASS_PREFIX + "middle"); + removeStyleName(ALIGN_CLASS_PREFIX + "bottom"); + } + } + + public void setExpandRatio(double expandRatio) { + this.expandRatio = expandRatio; + } + + public double getExpandRatio() { + return expandRatio; + } + + public void setSpacing(boolean spacing) { + if (spacing && spacer == null) { + spacer = DOM.createDiv(); + spacer.addClassName("v-spacing"); + getElement().getParentElement().insertBefore(spacer, + getElement()); + } else if (!spacing && spacer != null) { + spacer.removeFromParent(); + spacer = null; + } + } + + public Element getSpacingElement() { + return spacer; + } + + public boolean hasSpacing() { + return getSpacingElement() != null; + } + + protected int getSpacingSize(boolean vertical) { + if (spacer == null) { + return 0; + } + + if (layoutManager != null) { + if (vertical) { + return layoutManager.getOuterHeight(spacer); + } else { + return layoutManager.getOuterWidth(spacer); + } + } + // TODO place for optimization (in expense of theme + // flexibility): only measure one of the elements and cache the + // value + return vertical ? spacer.getOffsetHeight() : spacer + .getOffsetWidth(); + // } + } + + public void setCaptionPosition(CaptionPosition captionPosition) { + if (caption == null) { + return; + } + + captionWrap.removeClassName("v-caption-on-" + + this.captionPosition.name().toLowerCase()); + + this.captionPosition = captionPosition; + if (captionPosition == CaptionPosition.BOTTOM + || captionPosition == CaptionPosition.RIGHT) { + captionWrap.appendChild(caption); + } else { + captionWrap.insertFirst(caption); + } + + captionWrap.addClassName("v-caption-on-" + + captionPosition.name().toLowerCase()); + } + + public CaptionPosition getCaptionPosition() { + return captionPosition; + } + + // TODO refactor VCaption and use that instead: creates a tight coupling + // between this layout and Vaadin, but it's already coupled + public void setCaption(String captionText, String iconUrl, + List<String> styles, String error, boolean showError, + boolean required, boolean enabled) { + + // TODO place for optimization: check if any of these have changed + // since last time, and only run those changes + + // Caption wrappers + if (captionText != null || iconUrl != null || error != null + || required) { + if (caption == null) { + caption = DOM.createDiv(); + captionWrap = DOM.createDiv(); + captionWrap.addClassName("v"); + captionWrap.addClassName("v-has-caption"); + getElement().appendChild(captionWrap); + captionWrap.appendChild(getWidget().getElement()); + } + } else if (caption != null) { + getElement().appendChild(getWidget().getElement()); + captionWrap.removeFromParent(); + caption = null; + captionWrap = null; + } + + // Caption text + if (captionText != null) { + if (this.captionText == null) { + this.captionText = DOM.createSpan(); + this.captionText.addClassName("v-captiontext"); + caption.appendChild(this.captionText); + } + if (captionText.trim().equals("")) { + this.captionText.setInnerHTML(" "); + } else { + this.captionText.setInnerText(captionText); + } + } else if (this.captionText != null) { + this.captionText.removeFromParent(); + this.captionText = null; + } + + // Icon + if (iconUrl != null) { + if (icon == null) { + icon = new Icon(); + // icon = DOM.createImg(); + // icon.setClassName("v-icon"); + caption.insertFirst(icon.getElement()); + } + // icon.setAttribute("src", iconUrl); + icon.setUri(iconUrl); + } else if (icon != null) { + icon.getElement().removeFromParent(); + icon = null; + } + + // Required + if (required) { + if (requiredIcon == null) { + requiredIcon = DOM.createSpan(); + // TODO decide something better (e.g. use CSS to insert the + // character) + requiredIcon.setInnerHTML("*"); + requiredIcon.setClassName("v-required-field-indicator"); + } + caption.appendChild(requiredIcon); + } else if (requiredIcon != null) { + requiredIcon.removeFromParent(); + requiredIcon = null; + } + + // Error + if (error != null && showError) { + if (errorIcon == null) { + errorIcon = DOM.createSpan(); + errorIcon.setClassName("v-errorindicator"); + } + caption.appendChild(errorIcon); + } else if (errorIcon != null) { + errorIcon.removeFromParent(); + errorIcon = null; + } + + if (caption != null) { + // Styles + caption.setClassName("v-caption"); + + if (styles != null) { + for (String style : styles) { + caption.addClassName("v-caption-" + style); + } + } + + if (enabled) { + caption.removeClassName("v-disabled"); + } else { + caption.addClassName("v-disabled"); + } + + // Caption position + if (captionText != null || iconUrl != null) { + setCaptionPosition(CaptionPosition.TOP); + } else { + setCaptionPosition(CaptionPosition.RIGHT); + } + } + + // TODO theme flexibility: add extra styles to captionWrap as well? + + } + + public boolean hasCaption() { + return caption != null; + } + + public Element getCaptionElement() { + return caption; + } + + public void setRelativeWidth(boolean relativeWidth) { + updateRelativeSize(relativeWidth, "width"); + } + + public void setRelativeHeight(boolean relativeHeight) { + updateRelativeSize(relativeHeight, "height"); + } + + private void updateRelativeSize(boolean isRelativeSize, String direction) { + if (isRelativeSize && hasCaption()) { + captionWrap.getStyle().setProperty( + direction, + getWidget().getElement().getStyle() + .getProperty(direction)); + captionWrap.addClassName("v-has-" + direction); + } else if (hasCaption()) { + if (direction.equals("height")) { + captionWrap.getStyle().clearHeight(); + } else { + captionWrap.getStyle().clearWidth(); + } + captionWrap.removeClassName("v-has-" + direction); + captionWrap.getStyle().clearPaddingTop(); + captionWrap.getStyle().clearPaddingRight(); + captionWrap.getStyle().clearPaddingBottom(); + captionWrap.getStyle().clearPaddingLeft(); + caption.getStyle().clearMarginTop(); + caption.getStyle().clearMarginRight(); + caption.getStyle().clearMarginBottom(); + caption.getStyle().clearMarginLeft(); + } + } + + @Override + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + if (DOM.eventGetType(event) == Event.ONLOAD + && icon.getElement() == DOM.eventGetTarget(event)) { + if (layoutManager != null) { + layoutManager.layoutLater(); + } else { + updateCaptionOffset(caption); + } + } + } + + @Override + protected Element getContainerElement() { + if (captionWrap == null) { + return getElement(); + } else { + return captionWrap; + } + } + + @Override + protected void onDetach() { + if (spacer != null) { + spacer.removeFromParent(); + } + super.onDetach(); + } + + @Override + protected void onAttach() { + super.onAttach(); + if (spacer != null) { + getElement().getParentElement().insertBefore(spacer, + getElement()); + } + } + + } + + protected class Icon extends UIObject { + public static final String CLASSNAME = "v-icon"; + private String myUrl; + + public Icon() { + setElement(DOM.createImg()); + DOM.setElementProperty(getElement(), "alt", ""); + setStyleName(CLASSNAME); + } + + public void setUri(String url) { + if (!url.equals(myUrl)) { + /* + * Start sinking onload events, widgets responsibility to react. + * We must do this BEFORE we set src as IE fires the event + * immediately if the image is found in cache (#2592). + */ + sinkEvents(Event.ONLOAD); + + DOM.setElementProperty(getElement(), "src", url); + myUrl = url; + } + } + + } + + void setLayoutManager(LayoutManager manager) { + layoutManager = manager; + } + + private static final RegExp captionPositionRegexp = RegExp + .compile("v-caption-on-(\\S+)"); + + CaptionPosition getCaptionPositionFromElement(Element captionWrap) { + // Get caption position from the classname + MatchResult matcher = captionPositionRegexp.exec(captionWrap + .getClassName()); + if (matcher == null || matcher.getGroupCount() < 2) { + return CaptionPosition.TOP; + } + String captionClass = matcher.getGroup(1); + CaptionPosition captionPosition = CaptionPosition.valueOf( + CaptionPosition.class, captionClass.toUpperCase()); + return captionPosition; + } + + void updateCaptionOffset(Element caption) { + + Element captionWrap = caption.getParentElement().cast(); + + Style captionWrapStyle = captionWrap.getStyle(); + captionWrapStyle.clearPaddingTop(); + captionWrapStyle.clearPaddingRight(); + captionWrapStyle.clearPaddingBottom(); + captionWrapStyle.clearPaddingLeft(); + + Style captionStyle = caption.getStyle(); + captionStyle.clearMarginTop(); + captionStyle.clearMarginRight(); + captionStyle.clearMarginBottom(); + captionStyle.clearMarginLeft(); + + // Get caption position from the classname + CaptionPosition captionPosition = getCaptionPositionFromElement(captionWrap); + + if (captionPosition == CaptionPosition.LEFT + || captionPosition == CaptionPosition.RIGHT) { + int captionWidth; + if (layoutManager != null) { + captionWidth = layoutManager.getOuterWidth(caption) + - layoutManager.getMarginWidth(caption); + } else { + captionWidth = caption.getOffsetWidth(); + } + if (captionWidth > 0) { + if (captionPosition == CaptionPosition.LEFT) { + captionWrapStyle.setPaddingLeft(captionWidth, Unit.PX); + captionStyle.setMarginLeft(-captionWidth, Unit.PX); + } else { + captionWrapStyle.setPaddingRight(captionWidth, Unit.PX); + captionStyle.setMarginRight(-captionWidth, Unit.PX); + } + } + } + if (captionPosition == CaptionPosition.TOP + || captionPosition == CaptionPosition.BOTTOM) { + int captionHeight; + if (layoutManager != null) { + captionHeight = layoutManager.getOuterHeight(caption) + - layoutManager.getMarginHeight(caption); + } else { + captionHeight = caption.getOffsetHeight(); + } + if (captionHeight > 0) { + if (captionPosition == CaptionPosition.TOP) { + captionWrapStyle.setPaddingTop(captionHeight, Unit.PX); + captionStyle.setMarginTop(-captionHeight, Unit.PX); + } else { + captionWrapStyle.setPaddingBottom(captionHeight, Unit.PX); + captionStyle.setMarginBottom(-captionHeight, Unit.PX); + } + } + } + } + + private void toggleStyleName(String name, boolean enabled) { + if (enabled) { + addStyleName(name); + } else { + removeStyleName(name); + } + } + + void setMargin(VMarginInfo marginInfo) { + toggleStyleName("v-margin-top", marginInfo.hasTop()); + toggleStyleName("v-margin-right", marginInfo.hasRight()); + toggleStyleName("v-margin-bottom", marginInfo.hasBottom()); + toggleStyleName("v-margin-left", marginInfo.hasLeft()); + } + + protected void setSpacing(boolean spacingEnabled) { + spacing = spacingEnabled; + for (Slot slot : widgetToSlot.values()) { + if (getWidgetIndex(slot) > 0) { + slot.setSpacing(spacingEnabled); + } + } + } + + private void recalculateExpands() { + double total = 0; + for (Slot slot : widgetToSlot.values()) { + if (slot.getExpandRatio() > -1) { + total += slot.getExpandRatio(); + } else { + if (vertical) { + slot.getElement().getStyle().clearHeight(); + } else { + slot.getElement().getStyle().clearWidth(); + } + } + } + for (Slot slot : widgetToSlot.values()) { + if (slot.getExpandRatio() > -1) { + if (vertical) { + slot.setHeight((100 * (slot.getExpandRatio() / total)) + + "%"); + if (slot.connector.isRelativeHeight()) { + layoutManager.setNeedsMeasure(slot.connector); + } + } else { + slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%"); + if (slot.connector.isRelativeWidth()) { + layoutManager.setNeedsMeasure(slot.connector); + } + } + } + } + } + + private Element expandWrapper; + + void clearExpand() { + if (expandWrapper != null) { + for (; expandWrapper.getChildCount() > 0;) { + Element el = expandWrapper.getChild(0).cast(); + getElement().appendChild(el); + if (vertical) { + el.getStyle().clearHeight(); + el.getStyle().clearMarginTop(); + } else { + el.getStyle().clearWidth(); + el.getStyle().clearMarginLeft(); + } + } + expandWrapper.removeFromParent(); + expandWrapper = null; + } + } + + public void updateExpand() { + boolean isExpanding = false; + for (Widget slot : getChildren()) { + if (((Slot) slot).getExpandRatio() > -1) { + isExpanding = true; + } else { + if (vertical) { + slot.getElement().getStyle().clearHeight(); + } else { + slot.getElement().getStyle().clearWidth(); + } + } + slot.getElement().getStyle().clearMarginLeft(); + slot.getElement().getStyle().clearMarginTop(); + } + + if (isExpanding) { + if (expandWrapper == null) { + expandWrapper = DOM.createDiv(); + expandWrapper.setClassName("v-expand"); + for (; getElement().getChildCount() > 0;) { + Node el = getElement().getChild(0); + expandWrapper.appendChild(el); + } + getElement().appendChild(expandWrapper); + } + + int totalSize = 0; + for (Widget w : getChildren()) { + Slot slot = (Slot) w; + if (slot.getExpandRatio() == -1) { + if (layoutManager != null) { + // TODO check caption position + if (vertical) { + int size = layoutManager.getOuterHeight(slot + .getWidget().getElement()) + - layoutManager.getMarginHeight(slot + .getWidget().getElement()); + if (slot.hasCaption()) { + size += layoutManager.getOuterHeight(slot + .getCaptionElement()) + - layoutManager.getMarginHeight(slot + .getCaptionElement()); + } + if (size > 0) { + totalSize += size; + } + } else { + int max = -1; + max = layoutManager.getOuterWidth(slot.getWidget() + .getElement()) + - layoutManager.getMarginWidth(slot + .getWidget().getElement()); + if (slot.hasCaption()) { + int max2 = layoutManager.getOuterWidth(slot + .getCaptionElement()) + - layoutManager.getMarginWidth(slot + .getCaptionElement()); + max = Math.max(max, max2); + } + if (max > 0) { + totalSize += max; + } + } + } else { + totalSize += vertical ? slot.getOffsetHeight() : slot + .getOffsetWidth(); + } + } + // TODO fails in Opera, always returns 0 + int spacingSize = slot.getSpacingSize(vertical); + if (spacingSize > 0) { + totalSize += spacingSize; + } + } + + // When we set the margin to the first child, we don't need + // overflow:hidden in the layout root element, since the wrapper + // would otherwise be placed outside of the layout root element + // and block events on elements below it. + if (vertical) { + expandWrapper.getStyle().setPaddingTop(totalSize, Unit.PX); + expandWrapper.getFirstChildElement().getStyle() + .setMarginTop(-totalSize, Unit.PX); + } else { + expandWrapper.getStyle().setPaddingLeft(totalSize, Unit.PX); + expandWrapper.getFirstChildElement().getStyle() + .setMarginLeft(-totalSize, Unit.PX); + } + + recalculateExpands(); + } + } + + public void recalculateLayoutHeight() { + // Only needed if a horizontal layout is undefined high, and contains + // relative height children or vertical alignments + if (vertical || definedHeight) { + return; + } + + boolean hasRelativeHeightChildren = false; + boolean hasVAlign = false; + + for (Widget slot : getChildren()) { + Widget widget = ((Slot) slot).getWidget(); + String h = widget.getElement().getStyle().getHeight(); + if (h != null && h.indexOf("%") > -1) { + hasRelativeHeightChildren = true; + } + AlignmentInfo a = ((Slot) slot).getAlignment(); + if (a != null && (a.isVerticalCenter() || a.isBottom())) { + hasVAlign = true; + } + } + + if (hasRelativeHeightChildren || hasVAlign) { + int newHeight; + if (layoutManager != null) { + newHeight = layoutManager.getOuterHeight(getElement()) + - layoutManager.getMarginHeight(getElement()); + } else { + newHeight = getElement().getOffsetHeight(); + } + VBoxLayout.this.getElement().getStyle() + .setHeight(newHeight, Unit.PX); + } + + } + + void clearHeight() { + getElement().getStyle().clearHeight(); + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + definedHeight = (height != null && !"".equals(height)); + } +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java new file mode 100644 index 0000000000..a480a79b2e --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java @@ -0,0 +1,19 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.orderedlayout; + +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; +import com.vaadin.ui.VerticalLayout; + +@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER) +public class VerticalBoxLayoutConnector extends AbstractBoxLayoutConnector { + + @Override + public void init() { + super.init(); + getWidget().setVertical(true); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java index 441ba9c156..c53494775c 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java @@ -15,11 +15,8 @@ */ package com.vaadin.terminal.gwt.client.ui.orderedlayout; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.VerticalLayout; -@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER) +//@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER) public class VerticalLayoutConnector extends AbstractOrderedLayoutConnector { @Override diff --git a/shared/src/com/vaadin/shared/ComponentState.java b/shared/src/com/vaadin/shared/ComponentState.java index 92afad0520..6c9f055732 100644 --- a/shared/src/com/vaadin/shared/ComponentState.java +++ b/shared/src/com/vaadin/shared/ComponentState.java @@ -92,6 +92,16 @@ public class ComponentState extends SharedState { } /** + * Returns true if the component height is relative to the parent, i.e. + * percentage, false if it is fixed/auto. + * + * @return true if component height is relative (percentage) + */ + public boolean isRelativeHeight() { + return getHeight().endsWith("%"); + } + + /** * Returns the component width as set by the server. * * Can be relative (containing the percent sign) or absolute, or empty @@ -130,6 +140,16 @@ public class ComponentState extends SharedState { } /** + * Returns true if the component width is relative to the parent, i.e. + * percentage, false if it is fixed/auto. + * + * @return true if component width is relative (percentage) + */ + public boolean isRelativeWidth() { + return getWidth().endsWith("%"); + } + + /** * Returns true if the component is in read-only mode. * * @see com.vaadin.ui.Component#isReadOnly() diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java new file mode 100644 index 0000000000..86015a0109 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/BoxLayoutTest.java @@ -0,0 +1,469 @@ +package com.vaadin.tests.components.orderedlayout; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.vaadin.annotations.Theme; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.terminal.ThemeResource; +import com.vaadin.terminal.UserError; +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.Component; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.Reindeer; + +@Theme("tests-components") +public class BoxLayoutTest extends AbstractTestRoot { + + protected AbstractOrderedLayout view; + + protected AbstractOrderedLayout l; + + protected AbstractComponent target; + + protected NativeSelect componentWidth; + protected NativeSelect componentHeight; + protected NativeSelect componentCaption; + protected NativeSelect componentIcon; + protected TextField componentDescription; + protected CheckBox componentError; + protected CheckBox componentRequired; + + protected NativeSelect align; + protected CheckBox expand; + + @Override + protected void setup(WrappedRequest request) { + + view = new VerticalLayout(); + // view.setSizeFull(); + view.setMargin(true); + view.setSpacing(true); + + // view.addComponent(createControls(false)); + // view.addComponent(createTestLayout(false)); + // view.setExpandRatio(view.getComponent(1), 1); + + for (int i = 0; i < 20; i++) { + view.addComponent(createHorizontalTest()); + } + + setContent(view); + getApplication().setRootPreserved(true); + } + + private Component createHorizontalTest() { + HorizontalLayout l = new HorizontalLayout(); + l.setWidth("100%"); + l.setSpacing(true); + + Label exp; + + // l.addComponent(new Embedded(null, new ThemeResource( + // "../runo/icons/32/document.png"))); + l.addComponent(exp = new Label( + "Mauris iaculis porttitor posuere. Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec.")); + // exp.setWidth("300px"); + l.addComponent(new Button("Edit")); + l.addComponent(new Button("Delete")); + l.setExpandRatio(exp, 1); + + for (int i = 0; i < l.getComponentCount(); i++) { + l.setComponentAlignment(l.getComponent(i), Alignment.MIDDLE_LEFT); + } + + return l; + } + + protected AbstractOrderedLayout createControls(boolean horizontal) { + VerticalLayout root = new VerticalLayout(); + root.setSpacing(true); + + // First row + HorizontalLayout header = new HorizontalLayout(); + header.setSpacing(true); + root.addComponent(header); + + Label title = new Label("BoxLayout Test"); + title.addStyleName(Reindeer.LABEL_H1); + header.addComponent(title); + + final CheckBox vertical = new CheckBox("Vertical", !horizontal); + vertical.setImmediate(true); + vertical.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + view.removeAllComponents(); + + view.addComponent(createControls(!vertical.getValue() + .booleanValue())); + view.addComponent(createTestLayout(!vertical.getValue() + .booleanValue())); + + view.setExpandRatio(view.getComponent(1), 1); + + } + }); + header.addComponent(vertical); + + Button addComponent = new Button("Add Component", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + GridLayout grid = new GridLayout(2, 2); + Button grow = new Button("Grow Me", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + if (event.getButton().getWidth() == -1) { + event.getButton().setHeight("50px"); + event.getButton().setWidth("200px"); + } else { + event.getButton() + .setSizeUndefined(); + } + } + }); + grid.addComponent(new Label("Grid cell 1")); + grid.addComponent(new Label("Grid cell 2")); + grid.addComponent(grow); + grid.addComponent(new Label("Grid cell 4")); + l.addComponent(grid); + // l.addComponent(new TextField("Some field")); + } + }); + header.addComponent(addComponent); + + Button removeComponent = new Button("Remove Component", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + Component last = l.getComponent(l.getComponentCount() - 1); + l.removeComponent(last); + } + }); + header.addComponent(removeComponent); + + // Second row + HorizontalLayout controls = new HorizontalLayout(); + controls.setSpacing(true); + root.addComponent(controls); + + // Layout controls + HorizontalLayout layout = new HorizontalLayout(); + layout.addStyleName("fieldset"); + layout.setSpacing(true); + controls.addComponent(layout); + layout.addComponent(new Label("Layout")); + + ArrayList<String> sizes = new ArrayList<String>(); + sizes.addAll(Arrays.asList("100px", "30em", "100%")); + + final NativeSelect width = new NativeSelect(null, sizes); + width.setImmediate(true); + width.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (width.getValue() != null) { + l.setWidth(width.getValue().toString()); + } else { + l.setWidth(null); + } + } + }); + layout.addComponent(width); + layout.addComponent(new Label("×", ContentMode.XHTML)); + final NativeSelect height = new NativeSelect(null, sizes); + height.setImmediate(true); + height.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (height.getValue() != null) { + l.setHeight(height.getValue().toString()); + } else { + l.setHeight(null); + } + } + }); + layout.addComponent(height); + + final CheckBox margin = new CheckBox("Margin", false); + margin.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + l.setMargin(margin.getValue().booleanValue()); + } + }); + margin.setImmediate(true); + layout.addComponent(margin); + layout.addComponent(margin); + + final CheckBox spacing = new CheckBox("Spacing", false); + spacing.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + l.setSpacing(spacing.getValue().booleanValue()); + } + }); + spacing.setImmediate(true); + layout.addComponent(spacing); + + // Cell controls + HorizontalLayout cell = new HorizontalLayout(); + cell.addStyleName("fieldset"); + cell.setSpacing(true); + controls.addComponent(cell); + cell.addComponent(new Label("Cell")); + + ArrayList<Alignment> alignments = new ArrayList<Alignment>(); + alignments.addAll(Arrays.asList(Alignment.TOP_LEFT, + Alignment.MIDDLE_LEFT, Alignment.BOTTOM_LEFT, + Alignment.TOP_CENTER, Alignment.MIDDLE_CENTER, + Alignment.BOTTOM_CENTER, Alignment.TOP_RIGHT, + Alignment.MIDDLE_RIGHT, Alignment.BOTTOM_RIGHT)); + + align = new NativeSelect(null, alignments); + for (Alignment a : alignments) { + align.setItemCaption(a, + a.getVerticalAlignment() + "-" + a.getHorizontalAlignment()); + } + align.setImmediate(true); + align.setEnabled(false); + align.setNullSelectionAllowed(false); + align.select(Alignment.TOP_LEFT); + align.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (target == null) { + return; + } + l.setComponentAlignment(target, ((Alignment) align.getValue())); + } + }); + cell.addComponent(align); + + expand = new CheckBox("Expand"); + expand.setImmediate(true); + expand.setEnabled(false); + expand.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (target != null) { + l.setExpandRatio(target, expand.getValue() ? 1 : 0); + } + } + }); + cell.addComponent(expand); + + // Component controls + HorizontalLayout component = new HorizontalLayout(); + component.addStyleName("fieldset"); + component.setSpacing(true); + root.addComponent(component); + component.addComponent(new Label("Component")); + + sizes = new ArrayList<String>(); + sizes.addAll(Arrays.asList("50px", "200px", "10em", "50%", "100%")); + + componentWidth = new NativeSelect(null, sizes); + componentWidth.setImmediate(true); + componentWidth.setEnabled(false); + componentWidth.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (target == null) { + return; + } + if (componentWidth.getValue() != null) { + target.setWidth(componentWidth.getValue().toString()); + } else { + target.setWidth(null); + } + } + }); + component.addComponent(componentWidth); + component.addComponent(new Label("×", ContentMode.XHTML)); + + componentHeight = new NativeSelect(null, sizes); + componentHeight.setImmediate(true); + componentHeight.setEnabled(false); + componentHeight.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (componentHeight.getValue() != null) { + target.setHeight(componentHeight.getValue().toString()); + } else { + target.setHeight(null); + } + } + }); + component.addComponent(componentHeight); + + componentCaption = new NativeSelect("Caption", Arrays.asList("Short", + "Slightly Longer Caption")); + componentCaption.setImmediate(true); + componentCaption.setEnabled(false); + componentCaption.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (componentCaption.getValue() != null) { + target.setCaption(componentCaption.getValue().toString()); + } else { + target.setCaption(null); + } + } + }); + component.addComponent(componentCaption); + + componentIcon = new NativeSelect("Icon", Arrays.asList( + "../runo/icons/16/folder.png", "../runo/icons/32/document.png")); + componentIcon.setImmediate(true); + componentIcon.setEnabled(false); + componentIcon.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (componentIcon.getValue() != null) { + target.setIcon(new ThemeResource(componentIcon.getValue() + .toString())); + } else { + target.setIcon(null); + } + } + }); + component.addComponent(componentIcon); + + componentDescription = new TextField("Description"); + componentDescription.setImmediate(true); + componentDescription.setEnabled(false); + componentDescription.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + target.setDescription(componentDescription.getValue()); + } + }); + component.addComponent(componentDescription); + + componentError = new CheckBox("Error"); + componentError.setImmediate(true); + componentError.setEnabled(false); + componentError.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (target != null) { + target.setComponentError(componentError.getValue() ? new UserError( + "Error message") : null); + } + } + }); + component.addComponent(componentError); + + componentRequired = new CheckBox("Required"); + componentRequired.setImmediate(true); + componentRequired.setEnabled(false); + componentRequired.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + if (target != null && target instanceof AbstractField) { + ((AbstractField<?>) target).setRequired(componentRequired + .getValue()); + } + } + }); + component.addComponent(componentRequired); + + for (int i = 0; i < component.getComponentCount(); i++) { + component.setComponentAlignment(component.getComponent(i), + Alignment.MIDDLE_LEFT); + } + + return root; + } + + protected AbstractOrderedLayout createTestLayout(boolean horizontal) { + l = horizontal ? new HorizontalLayout() : new VerticalLayout(); + l.setSizeUndefined(); + l.addStyleName("test"); + + Label label = new Label("Component 1"); + l.addComponent(label); + l.addComponent(new Button("Component 2")); + + l.addListener(new LayoutClickListener() { + public void layoutClick(LayoutClickEvent event) { + if (event.getChildComponent() == null + || target == event.getChildComponent()) { + if (target != null) { + target.removeStyleName("target"); + } + target = null; + } else if (target != event.getChildComponent()) { + if (target != null) { + target.removeStyleName("target"); + } + target = (AbstractComponent) event.getChildComponent(); + target.addStyleName("target"); + } + componentWidth.setEnabled(target != null); + componentHeight.setEnabled(target != null); + componentCaption.setEnabled(target != null); + componentIcon.setEnabled(target != null); + componentDescription.setEnabled(target != null); + componentError.setEnabled(target != null); + componentRequired.setEnabled(target != null + && target instanceof AbstractField); + align.setEnabled(target != null); + expand.setEnabled(target != null); + if (target != null) { + if (target.getWidth() > -1) { + componentWidth.select(new Float(target.getWidth()) + .intValue() + + target.getWidthUnits().getSymbol()); + } else { + componentWidth.select(null); + } + if (target.getHeight() > -1) { + componentHeight.select(new Float(target.getHeight()) + .intValue() + + target.getHeightUnits().getSymbol()); + } else { + componentHeight.select(null); + } + + align.select(l.getComponentAlignment(target)); + expand.setValue(new Boolean(l.getExpandRatio(target) > 0)); + + componentCaption.select(target.getCaption()); + if (target.getIcon() != null) { + componentIcon.select(((ThemeResource) target.getIcon()) + .getResourceId()); + } else { + componentIcon.select(null); + } + componentDescription.setValue(target.getDescription()); + componentError.setValue(target.getComponentError() != null); + if (target instanceof AbstractField) { + componentRequired.setValue(((AbstractField<?>) target) + .isRequired()); + } + } + } + }); + + target = null; + + return l; + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +}
\ No newline at end of file diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutRenderTimeTest.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutRenderTimeTest.java new file mode 100644 index 0000000000..871a467877 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutRenderTimeTest.java @@ -0,0 +1,58 @@ +package com.vaadin.tests.components.orderedlayout; + +import com.vaadin.Application.LegacyApplication; +import com.vaadin.terminal.ThemeResource; +import com.vaadin.ui.Button; +import com.vaadin.ui.Embedded; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Root; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.Reindeer; + +public class LayoutRenderTimeTest extends LegacyApplication { + + @Override + public void init() { + Root.LegacyWindow main = new Root.LegacyWindow(); + setMainWindow(main); + + VerticalLayout root = new VerticalLayout(); + root.setWidth("100%"); + main.setContent(root); + + for (int i = 1; i <= 100; i++) { + root.addComponent(getRow(i)); + } + } + + private HorizontalLayout getRow(int i) { + HorizontalLayout row = new HorizontalLayout(); + // row.setWidth("100%"); + // row.setSpacing(true); + + Embedded icon = new Embedded(null, new ThemeResource( + "../runo/icons/32/document.png")); + // row.addComponent(icon); + // row.setComponentAlignment(icon, Alignment.MIDDLE_LEFT); + + Label text = new Label( + "Row content #" + + i + + ". In pellentesque faucibus vestibulum. Nulla at nulla justo, eget luctus tortor. Nulla facilisi. Duis aliquet."); + // row.addComponent(text); + // row.setExpandRatio(text, 1); + + Button button = new Button("Edit"); + button.addStyleName(Reindeer.BUTTON_SMALL); + row.addComponent(button); + // row.setComponentAlignment(button, Alignment.MIDDLE_LEFT); + + button = new Button("Delete"); + button.addStyleName(Reindeer.BUTTON_SMALL); + row.addComponent(button); + // row.setComponentAlignment(button, Alignment.MIDDLE_LEFT); + + return row; + } +} diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java index 07562b7cfe..62c552ee75 100644 --- a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutResizeTest.java @@ -9,7 +9,6 @@ import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Embedded; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalSplitPanel; -import com.vaadin.ui.JavaScript; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; @@ -40,8 +39,10 @@ public class LayoutResizeTest extends TestBase { new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { - JavaScript - .getCurrent() + event.getButton() + .getRoot() + .getPage() + .getJavaScript() .execute( "setTimeout(function() {window.resizeTo(700,400)}, 500)"); } @@ -51,8 +52,10 @@ public class LayoutResizeTest extends TestBase { resize = new Button("Resize to 900x600", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { - JavaScript - .getCurrent() + event.getButton() + .getRoot() + .getPage() + .getJavaScript() .execute( "setTimeout(function() {window.resizeTo(900,600)}, 500)"); } diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/OrderedLayoutCases.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/OrderedLayoutCases.java index 5aaaaec6a6..a10e69e188 100644 --- a/tests/testbench/com/vaadin/tests/components/orderedlayout/OrderedLayoutCases.java +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/OrderedLayoutCases.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import com.vaadin.annotations.Theme; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.terminal.WrappedRequest; @@ -20,57 +21,59 @@ import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.VerticalLayout; +@Theme("tests-components") public class OrderedLayoutCases extends AbstractTestUI { + private static final String[] dimensionValues = { "-1px", "5px", "350px", - "800px", "100%", "50%" }; + "800px", "100%", "50%" }; private static class SampleChild extends VerticalLayout { public SampleChild() { setStyleName("sampleChild"); addComponent(createSimpleSelector("Child width", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - setWidth(event.getProperty().getValue().toString()); - } - }, dimensionValues)); + @Override + public void valueChange(ValueChangeEvent event) { + setWidth(event.getProperty().getValue().toString()); + } + }, dimensionValues)); addComponent(createSimpleSelector("Child height", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - setHeight(event.getProperty().getValue().toString()); - } - }, dimensionValues)); + @Override + public void valueChange(ValueChangeEvent event) { + setHeight(event.getProperty().getValue().toString()); + } + }, dimensionValues)); addComponent(createSimpleSelector("Caption", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - String value = event.getProperty().getValue() - .toString(); - if (value.length() == 0) { - setCaption(null); - } else if (value.equals("Long")) { - setCaption("A rather long caption just to see what happens"); - } else { - setCaption(value); - } - } - }, "", "Short", "Long")); + @Override + public void valueChange(ValueChangeEvent event) { + String value = event.getProperty().getValue() + .toString(); + if (value.length() == 0) { + setCaption(null); + } else if (value.equals("Long")) { + setCaption("A rather long caption just to see what happens"); + } else { + setCaption(value); + } + } + }, "", "Short", "Long")); addComponent(createSimpleSelector("Expand ratio", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - AbstractOrderedLayout parent = (AbstractOrderedLayout) getParent(); - if (parent == null) { - return; - } - String value = event.getProperty().getValue() - .toString(); - parent.setExpandRatio(SampleChild.this, - Float.parseFloat(value)); - } - }, "0", "1", "2")); + @Override + public void valueChange(ValueChangeEvent event) { + AbstractOrderedLayout parent = (AbstractOrderedLayout) getParent(); + if (parent == null) { + return; + } + String value = event.getProperty().getValue() + .toString(); + parent.setExpandRatio(SampleChild.this, + Float.parseFloat(value)); + } + }, "0", "1", "2")); // Why is Alignment not an enum? Now we have to use reflection just // to get the different values as hardcoding is never an option! ;) @@ -83,29 +86,29 @@ public class OrderedLayoutCases extends AbstractTestUI { } addComponent(createSimpleSelector("Alignment", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - String value = event.getProperty().getValue() - .toString(); - AlignmentHandler parent = (AlignmentHandler) getParent(); - if (parent == null) { - return; - } - try { - Field field = Alignment.class - .getDeclaredField(value); - Alignment alignment = (Alignment) field - .get(null); - parent.setComponentAlignment(SampleChild.this, - alignment); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }, alignmentValues, "TOP_LEFT")); // Sorry for not using - // more reflection magic - // just to find the - // default value... + @Override + public void valueChange(ValueChangeEvent event) { + String value = event.getProperty().getValue() + .toString(); + AlignmentHandler parent = (AlignmentHandler) getParent(); + if (parent == null) { + return; + } + try { + Field field = Alignment.class + .getDeclaredField(value); + Alignment alignment = (Alignment) field + .get(null); + parent.setComponentAlignment(SampleChild.this, + alignment); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }, alignmentValues, "TOP_LEFT")); // Sorry for not using + // more reflection magic + // just to find the + // default value... } } @@ -116,12 +119,12 @@ public class OrderedLayoutCases extends AbstractTestUI { @Override protected void setup(WrappedRequest request) { TestUtils - .injectCSS( - getUI(), - ".sampleChild, .theLayout {border: 1px solid black;}" - + ".theLayout > div:first-child {background: aqua;}" - + ".theLayout > div:first-child + div {background: yellow;}" - + ".theLayout > div:first-child + div + div {background: lightgrey;}"); + .injectCSS( + getUI(), + ".sampleChild, .theLayout {border: 1px solid black;}" + + ".theLayout > div:first-child {background: aqua;}" + + ".theLayout > div:first-child + div {background: yellow;}" + + ".theLayout > div:first-child + div + div {background: lightgrey;}"); currentLayout = new HorizontalLayout(); for (int i = 0; i < 3; i++) { @@ -133,196 +136,196 @@ public class OrderedLayoutCases extends AbstractTestUI { sizeBar.addComponent(createSimpleSelector("Layout width", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - currentLayout.setWidth(event.getProperty().getValue() - .toString()); - } - }, dimensionValues)); + @Override + public void valueChange(ValueChangeEvent event) { + currentLayout.setWidth(event.getProperty().getValue() + .toString()); + } + }, dimensionValues)); sizeBar.addComponent(createSimpleSelector("Layout height", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - currentLayout.setHeight(event.getProperty().getValue() - .toString()); - } - }, dimensionValues)); + @Override + public void valueChange(ValueChangeEvent event) { + currentLayout.setHeight(event.getProperty().getValue() + .toString()); + } + }, dimensionValues)); sizeBar.addComponent(createSimpleSelector("Spacing", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - currentLayout.setSpacing(Boolean.parseBoolean(event - .getProperty().getValue().toString())); - } - }, "false", "true")); + @Override + public void valueChange(ValueChangeEvent event) { + currentLayout.setSpacing(Boolean.parseBoolean(event + .getProperty().getValue().toString())); + } + }, "false", "true")); sizeBar.addComponent(createSimpleSelector("Margin", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - currentLayout.setMargin(Boolean.parseBoolean(event - .getProperty().getValue().toString())); - } - }, "false", "true")); + @Override + public void valueChange(ValueChangeEvent event) { + currentLayout.setMargin(Boolean.parseBoolean(event + .getProperty().getValue().toString())); + } + }, "false", "true")); sizeBar.addComponent(createSimpleSelector("Direction", new ValueChangeListener() { - @Override - public void valueChange(ValueChangeEvent event) { - Object value = event.getProperty().getValue(); - - AbstractOrderedLayout newLayout; - if (value.equals("Horizontal")) { - newLayout = new HorizontalLayout(); - } else { - newLayout = new VerticalLayout(); - } - - while (currentLayout.getComponentCount() > 0) { - newLayout.addComponent(currentLayout - .getComponent(0)); - } - newLayout.setStyleName("theLayout"); - - newLayout.setHeight(currentLayout.getHeight(), - currentLayout.getHeightUnits()); - newLayout.setWidth(currentLayout.getWidth(), - currentLayout.getWidthUnits()); - - newLayout.setMargin(currentLayout.getMargin()); - newLayout.setSpacing(currentLayout.isSpacing()); - - getLayout().replaceComponent(currentLayout, newLayout); - getLayout().setExpandRatio(newLayout, 1); - currentLayout = newLayout; - } - }, "Horizontal", "Vertical")); + @Override + public void valueChange(ValueChangeEvent event) { + Object value = event.getProperty().getValue(); + + AbstractOrderedLayout newLayout; + if (value.equals("Horizontal")) { + newLayout = new HorizontalLayout(); + } else { + newLayout = new VerticalLayout(); + } + + while (currentLayout.getComponentCount() > 0) { + newLayout.addComponent(currentLayout + .getComponent(0)); + } + newLayout.setStyleName("theLayout"); + + newLayout.setHeight(currentLayout.getHeight(), + currentLayout.getHeightUnits()); + newLayout.setWidth(currentLayout.getWidth(), + currentLayout.getWidthUnits()); + + newLayout.setMargin(currentLayout.getMargin()); + newLayout.setSpacing(currentLayout.isSpacing()); + + getLayout().replaceComponent(currentLayout, newLayout); + getLayout().setExpandRatio(newLayout, 1); + currentLayout = newLayout; + } + }, "Horizontal", "Vertical")); HorizontalLayout caseBar = new HorizontalLayout(); caseBar.addComponent(new Button("Undefined without relative", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - setState(sizeBar, 2, 1); - // width: 350px to middle child - setChildState(1, 0, 2); - // middle center allign to middle child - setChildState(1, 4, 5); - // long captions to right child - setChildState(2, 2, 2); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + setState(sizeBar, 2, 1); + // width: 350px to middle child + setChildState(1, 0, 2); + // middle center allign to middle child + setChildState(1, 4, 5); + // long captions to right child + setChildState(2, 2, 2); + } + })); caseBar.addComponent(new Button("Undefined with relative", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // width: 100% to middle child - setChildState(1, 0, 4); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // width: 100% to middle child + setChildState(1, 0, 4); + } + })); caseBar.addComponent(new Button("Fixed with overflow", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // layout width: 350px - setState(sizeBar, 0, 2); - // layout margin enabled - setState(sizeBar, 3, 1); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // layout width: 350px + setState(sizeBar, 0, 2); + // layout margin enabled + setState(sizeBar, 3, 1); + } + })); caseBar.addComponent(new Button("Fixed with extra space", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // Layout width: 800px - setState(sizeBar, 0, 3); - // layout margin enabled - setState(sizeBar, 3, 1); - // width: 350px to middle child - setChildState(1, 0, 2); - // short caption for middle child - setChildState(1, 2, 1); - // top center align for middle child - setChildState(1, 4, 2); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // Layout width: 800px + setState(sizeBar, 0, 3); + // layout margin enabled + setState(sizeBar, 3, 1); + // width: 350px to middle child + setChildState(1, 0, 2); + // short caption for middle child + setChildState(1, 2, 1); + // top center align for middle child + setChildState(1, 4, 2); + } + })); caseBar.addComponent(new Button("Expand with alignment", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // Layout width: 800px - setState(sizeBar, 0, 3); - // Layout height: 350px - setState(sizeBar, 1, 2); - // Expand: 1 to middle child - setChildState(1, 3, 1); - // Align bottom left to middle child - setChildState(1, 4, 6); - // Long caption to middle child - setChildState(1, 2, 2); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // Layout width: 800px + setState(sizeBar, 0, 3); + // Layout height: 350px + setState(sizeBar, 1, 2); + // Expand: 1 to middle child + setChildState(1, 3, 1); + // Align bottom left to middle child + setChildState(1, 4, 6); + // Long caption to middle child + setChildState(1, 2, 2); + } + })); caseBar.addComponent(new Button("Multiple expands", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // Layout width: 800px - setState(sizeBar, 0, 3); - // Layout height: 350px - setState(sizeBar, 1, 2); - // Long caption to left child - setChildState(0, 2, 2); - // Width 350px to middle child - setChildState(1, 0, 2); - // Apply to left and middle child - for (int i = 0; i < 2; i++) { - // Expand: 1 - setChildState(i, 3, 1); - // Align: middle center - setChildState(i, 4, 5); - } - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // Layout width: 800px + setState(sizeBar, 0, 3); + // Layout height: 350px + setState(sizeBar, 1, 2); + // Long caption to left child + setChildState(0, 2, 2); + // Width 350px to middle child + setChildState(1, 0, 2); + // Apply to left and middle child + for (int i = 0; i < 2; i++) { + // Expand: 1 + setChildState(i, 3, 1); + // Align: middle center + setChildState(i, 4, 5); + } + } + })); caseBar.addComponent(new Button("Fixed + relative height", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // Layout height: 100% - setState(sizeBar, 1, 4); - // Height: 350px to left child - setChildState(0, 1, 2); - // Height: 100% to middle child - setChildState(1, 1, 4); - // Short caption to middle child - setChildState(1, 2, 1); - // Alignment: bottom left to right child - setChildState(2, 4, 7); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // Layout height: 100% + setState(sizeBar, 1, 4); + // Height: 350px to left child + setChildState(0, 1, 2); + // Height: 100% to middle child + setChildState(1, 1, 4); + // Short caption to middle child + setChildState(1, 2, 1); + // Alignment: bottom left to right child + setChildState(2, 4, 7); + } + })); caseBar.addComponent(new Button("Undefined + relative height", new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - resetState(); - // Height: 350px to left child - setChildState(0, 1, 2); - // Short caption to left child - setChildState(0, 2, 1); - // Height: 100% to middle child - setChildState(1, 1, 4); - // Alignment: bottom left to right child - setChildState(2, 4, 7); - } - })); + @Override + public void buttonClick(ClickEvent event) { + resetState(); + // Height: 350px to left child + setChildState(0, 1, 2); + // Short caption to left child + setChildState(0, 2, 1); + // Height: 100% to middle child + setChildState(1, 1, 4); + // Alignment: bottom left to right child + setChildState(2, 4, 7); + } + })); caseBar.setSpacing(true); diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/VaadinTunesLayout.java b/tests/testbench/com/vaadin/tests/components/orderedlayout/VaadinTunesLayout.java new file mode 100644 index 0000000000..973bd63d76 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/VaadinTunesLayout.java @@ -0,0 +1,341 @@ +package com.vaadin.tests.components.orderedlayout; + +import com.vaadin.annotations.Theme; +import com.vaadin.terminal.Sizeable; +import com.vaadin.terminal.ThemeResource; +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.Embedded; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Label; +import com.vaadin.ui.NativeButton; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.Slider; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +@Theme("tests-components") +public class VaadinTunesLayout extends AbstractTestRoot { + + @Override + public void setup(WrappedRequest request) { + + /* + * We'll build the whole UI here, since the application will not contain + * any logic. Otherwise it would be more practical to separate parts of + * the UI into different classes and methods. + */ + + // Main (browser) window, needed in all Vaadin applications + VerticalLayout rootLayout = new VerticalLayout(); + // final Window root = new Window("VaadinTunes", rootLayout); + + /* + * We'll attach the window to the browser view already here, so we won't + * forget it later. + */ + setContent(rootLayout); + + // root.showNotification( + // "This is an example of how you can do layouts in Vaadin.<br/>It is not a working sound player.", + // Notification.TYPE_HUMANIZED_MESSAGE); + + // Our root window contains one VerticalLayout, let's make + // sure it's 100% sized, and remove unwanted margins + rootLayout.setSizeFull(); + rootLayout.setMargin(false); + + // Top area, containing playback and volume controls, play status, view + // modes and search + HorizontalLayout top = new HorizontalLayout(); + top.setWidth("100%"); + top.setMargin(false, true, false, true); // Enable horizontal margins + top.setSpacing(true); + + // Let's attach that one straight away too + rootLayout.addComponent(top); + + // Create the placeholders for all the components in the top area + HorizontalLayout playback = new HorizontalLayout(); + HorizontalLayout volume = new HorizontalLayout(); + HorizontalLayout status = new HorizontalLayout(); + HorizontalLayout viewmodes = new HorizontalLayout(); + ComboBox search = new ComboBox(); + + // Add the components and align them properly + top.addComponent(playback); + top.addComponent(volume); + top.addComponent(status); + top.addComponent(viewmodes); + top.addComponent(search); + top.setComponentAlignment(playback, Alignment.MIDDLE_LEFT); + top.setComponentAlignment(volume, Alignment.MIDDLE_LEFT); + top.setComponentAlignment(status, Alignment.MIDDLE_CENTER); + top.setComponentAlignment(viewmodes, Alignment.MIDDLE_LEFT); + top.setComponentAlignment(search, Alignment.MIDDLE_LEFT); + + /* + * We want our status area to expand if the user resizes the root + * window, and we want it to accommodate as much space as there is + * available. All other components in the top layout should stay fixed + * sized, so we don't need to specify any expand ratios for them (they + * will automatically revert to zero after the following line). + */ + top.setExpandRatio(status, 1.0F); + + // Playback controls + Button prev = new NativeButton("Previous"); + Button play = new NativeButton("Play/pause"); + Button next = new NativeButton("Next"); + playback.addComponent(prev); + playback.addComponent(play); + playback.addComponent(next); + // Set spacing between the buttons + playback.setSpacing(true); + + // Volume controls + Button mute = new NativeButton("mute"); + Slider vol = new Slider(); + vol.setOrientation(Slider.ORIENTATION_HORIZONTAL); + vol.setWidth("100px"); + Button max = new NativeButton("max"); + volume.addComponent(mute); + volume.addComponent(vol); + volume.addComponent(max); + + // Status area + status.setWidth("80%"); + status.setSpacing(true); + + Button toggleVisualization = new NativeButton("Mode"); + Label timeFromStart = new Label("0:00"); + + // We'll need another layout to show currently playing track and + // progress + VerticalLayout trackDetails = new VerticalLayout(); + trackDetails.setWidth("100%"); + Label track = new Label("Track Name"); + Label album = new Label("Album Name - Artist"); + track.setWidth(null); + album.setWidth(null); + Slider progress = new Slider(); + progress.setOrientation(Slider.ORIENTATION_HORIZONTAL); + progress.setWidth("100%"); + trackDetails.addComponent(track); + trackDetails.addComponent(album); + trackDetails.addComponent(progress); + trackDetails.setComponentAlignment(track, Alignment.TOP_CENTER); + trackDetails.setComponentAlignment(album, Alignment.TOP_CENTER); + + Label timeToEnd = new Label("-4:46"); + Button jumpToTrack = new NativeButton("Show"); + + // Place all components to the status layout and align them properly + status.addComponent(toggleVisualization); + status.setComponentAlignment(toggleVisualization, Alignment.MIDDLE_LEFT); + status.addComponent(timeFromStart); + status.setComponentAlignment(timeFromStart, Alignment.BOTTOM_LEFT); + status.addComponent(trackDetails); + status.addComponent(timeToEnd); + status.setComponentAlignment(timeToEnd, Alignment.BOTTOM_LEFT); + status.addComponent(jumpToTrack); + status.setComponentAlignment(jumpToTrack, Alignment.MIDDLE_LEFT); + + // Then remember to specify the expand ratio + status.setExpandRatio(trackDetails, 1.0F); + + // View mode buttons + Button viewAsTable = new NativeButton("Table"); + Button viewAsGrid = new NativeButton("Grid"); + Button coverflow = new NativeButton("Coverflow"); + viewmodes.addComponent(viewAsTable); + viewmodes.addComponent(viewAsGrid); + viewmodes.addComponent(coverflow); + + /* + * That covers the top bar. Now let's move on to the sidebar and track + * listing + */ + + // We'll need one splitpanel to separate the sidebar and track listing + HorizontalSplitPanel bottom = new HorizontalSplitPanel(); + rootLayout.addComponent(bottom); + + // The splitpanel is by default 100% x 100%, but we'll need to adjust + // our main window layout to accomodate the height + rootLayout.setExpandRatio(bottom, 1.0F); + + // Give the sidebar less space than the listing + bottom.setSplitPosition(200, Sizeable.UNITS_PIXELS); + + // Let's add some content to the sidebar + // First, we need a layout to but all components in + VerticalLayout sidebar = new VerticalLayout(); + sidebar.setSizeFull(); + bottom.setFirstComponent(sidebar); + + /* + * Then we need some labels and buttons, and an album cover image The + * labels and buttons go into their own vertical layout, since we want + * the 'sidebar' layout to be expanding (cover image in the bottom). + * VerticalLayout is by default 100% wide. + */ + VerticalLayout selections = new VerticalLayout(); + Label library = new Label("Library"); + Button music = new NativeButton("Music"); + music.setWidth("100%"); + + Label store = new Label("Store"); + Button vaadinTunesStore = new NativeButton("VaadinTunes Store"); + vaadinTunesStore.setWidth("100%"); + Button purchased = new NativeButton("Purchased"); + purchased.setWidth("100%"); + + Label playlists = new Label("Playlists"); + Button genius = new NativeButton("Geniues"); + genius.setWidth("100%"); + Button recent = new NativeButton("Recently Added"); + recent.setWidth("100%"); + + // Lets add them to the 'selections' layout + selections.addComponent(library); + selections.addComponent(music); + selections.addComponent(store); + selections.addComponent(vaadinTunesStore); + selections.addComponent(purchased); + selections.addComponent(playlists); + selections.addComponent(genius); + selections.addComponent(recent); + + // Then add the selections to the sidebar, and set it expanding + sidebar.addComponent(selections); + sidebar.setExpandRatio(selections, 1.0F); + + // Then comes the cover artwork (we'll add the actual image in the + // themeing section) + Embedded cover = new Embedded("Currently Playing"); + sidebar.addComponent(cover); + + /* + * And lastly, we need the track listing table It should fill the whole + * left side of our bottom layout + */ + Table listing = new Table(); + listing.setSizeFull(); + listing.setSelectable(true); + bottom.setSecondComponent(listing); + + // Add the table headers + listing.addContainerProperty("Name", String.class, ""); + listing.addContainerProperty("Time", String.class, "0:00"); + listing.addContainerProperty("Artist", String.class, ""); + listing.addContainerProperty("Album", String.class, ""); + listing.addContainerProperty("Genre", String.class, ""); + listing.addContainerProperty("Rating", NativeSelect.class, + new NativeSelect()); + + // Lets populate the table with random data + String[] tracks = new String[] { "Red Flag", "Millstone", + "Not The Sun", "Breath", "Here We Are", "Deep Heaven", + "Her Voice Resides", "Natural Tan", "End It All", "Kings", + "Daylight Slaving", "Mad Man", "Resolve", "Teargas", + "African Air", "Passing Bird" }; + String[] times = new String[] { "4:12", "6:03", "5:43", "4:32", "3:42", + "4:45", "2:56", "9:34", "2:10", "3:44", "5:49", "6:30", "5:18", + "7:42", "3:13", "2:52" }; + String[] artists = new String[] { "Billy Talent", "Brand New", + "Breaking Benjamin", "Becoming The Archetype", + "Bullet For My Valentine", "Chasing Victory", "Chimaira", + "Danko Jones", "Deadlock", "Deftones", "From Autumn To Ashes", + "Haste The Day", "Four Year Strong", "In Flames", "Kemopetrol", + "John Legend" }; + String[] albums = new String[] { "Once Again", "The Caitiff Choir", + "The Devil And God", "Light Grenades", "Dicthonomy", + "Back In Black", "Dreamer", "Come Clarity", "Year Zero", + "Frames", "Fortress", "Phobia", "The Poison", "Manifesto", + "White Pony", "The Big Dirty" }; + String[] genres = new String[] { "Rock", "Metal", "Hardcore", "Indie", + "Pop", "Alternative", "Blues", "Jazz", "Hip Hop", + "Electronica", "Punk", "Hard Rock", "Dance", "R'n'B", "Gospel", + "Country" }; + for (int i = 0; i < 1000; i++) { + NativeSelect s = new NativeSelect(); + s.addItem("1 star"); + s.addItem("2 stars"); + s.addItem("3 stars"); + s.addItem("4 stars"); + s.addItem("5 stars"); + s.select(i % 5 + " stars"); + final int index = i % 16; + listing.addItem(new Object[] { tracks[index], times[index], + artists[index], albums[index], genres[index], s }, i); + } + + // We'll align the track time column to right as well + listing.setColumnAlignment("Time", Table.ALIGN_RIGHT); + + // TODO the footer + + // Now what's left to do? Themeing of course. + // setTheme("vaadintunes"); + + /* + * Let's give a namespace to our application window. This way, if + * someone uses the same theme for different applications, we don't get + * unwanted style conflicts. + */ + // root.setStyleName("tTunes"); + + top.setStyleName("top"); + top.setHeight("75px"); // Same as the background image height + + playback.setStyleName("playback"); + playback.setMargin(false, true, false, false); // Add right-side margin + play.setStyleName("play"); + next.setStyleName("next"); + prev.setStyleName("prev"); + playback.setComponentAlignment(prev, Alignment.MIDDLE_LEFT); + playback.setComponentAlignment(next, Alignment.MIDDLE_LEFT); + + volume.setStyleName("volume"); + mute.setStyleName("mute"); + max.setStyleName("max"); + vol.setWidth("78px"); + + status.setStyleName("status"); + status.setMargin(true); + status.setHeight("46px"); // Height of the background image + + toggleVisualization.setStyleName("toggle-vis"); + jumpToTrack.setStyleName("jump"); + + viewAsTable.setStyleName("viewmode-table"); + viewAsGrid.setStyleName("viewmode-grid"); + coverflow.setStyleName("viewmode-coverflow"); + + sidebar.setStyleName("sidebar"); + + music.setStyleName("selected"); + + cover.setSource(new ThemeResource("images/album-cover.jpg")); + // Because this is an image, it will retain it's aspect ratio + cover.setWidth("100%"); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +}
\ No newline at end of file diff --git a/tests/testbench/com/vaadin/tests/components/table/TextFieldRelativeWidth.java b/tests/testbench/com/vaadin/tests/components/table/TextFieldRelativeWidth.java index ae3f4c42a4..5c7479d060 100644 --- a/tests/testbench/com/vaadin/tests/components/table/TextFieldRelativeWidth.java +++ b/tests/testbench/com/vaadin/tests/components/table/TextFieldRelativeWidth.java @@ -27,8 +27,7 @@ public class TextFieldRelativeWidth extends TestBase { public class EditTable extends Table implements Button.ClickListener { - private Button addButton = new Button("Add new row", - (Button.ClickListener) this); + private Button addButton = new Button("Add new row", this); private String inputPrompt; diff --git a/tests/testbench/com/vaadin/tests/themes/LiferayThemeTest.java b/tests/testbench/com/vaadin/tests/themes/LiferayThemeTest.java new file mode 100644 index 0000000000..fa15d88799 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/themes/LiferayThemeTest.java @@ -0,0 +1,37 @@ +package com.vaadin.tests.themes; + +import com.vaadin.annotations.Theme; +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.ui.Label; +import com.vaadin.ui.Panel; +import com.vaadin.ui.themes.LiferayTheme; + +@Theme("liferay") +public class LiferayThemeTest extends AbstractTestRoot { + + @Override + protected void setup(WrappedRequest request) { + Panel p = new Panel("Panel"); + addComponent(p); + p.addComponent(new Label("Panel content")); + + p = new Panel("Light Panel"); + p.addStyleName(LiferayTheme.PANEL_LIGHT); + addComponent(p); + p.addComponent(new Label("Panel content")); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +} |