aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/base.scss2
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/colorpicker.scss209
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/images/gradient.pngbin0 -> 24998 bytes
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/images/gradient2.pngbin0 -> 14708 bytes
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.pngbin0 -> 974 bytes
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/images/resizebg.pngbin0 -> 735 bytes
-rw-r--r--WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.pngbin0 -> 396 bytes
-rw-r--r--WebContent/VAADIN/themes/base/datefield/datefield.scss4
-rw-r--r--WebContent/VAADIN/themes/chameleon/components/colorpicker/colorpicker.scss15
-rw-r--r--WebContent/VAADIN/themes/chameleon/components/components.scss2
-rw-r--r--WebContent/VAADIN/themes/liferay/colorpicker/colorpicker.scss19
-rw-r--r--WebContent/VAADIN/themes/liferay/liferay.scss2
-rw-r--r--WebContent/VAADIN/themes/reindeer/colorpicker/colorpicker.scss15
-rw-r--r--WebContent/VAADIN/themes/reindeer/reindeer.scss2
-rw-r--r--WebContent/VAADIN/themes/runo/colorpicker/colorpicker.scss20
-rw-r--r--WebContent/VAADIN/themes/runo/runo.scss4
-rw-r--r--client/src/com/vaadin/client/ComponentLocator.java14
-rw-r--r--client/src/com/vaadin/client/ui/VColorPicker.java73
-rw-r--r--client/src/com/vaadin/client/ui/VColorPickerArea.java181
-rw-r--r--client/src/com/vaadin/client/ui/VHorizontalLayout.java3
-rw-r--r--client/src/com/vaadin/client/ui/VOrderedLayout.java1196
-rw-r--r--client/src/com/vaadin/client/ui/VVerticalLayout.java3
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java86
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java53
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java52
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java71
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java80
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java176
-rw-r--r--client/src/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java132
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java9
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/CaptionPosition.java24
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/Slot.java658
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java552
-rw-r--r--server/src/com/vaadin/ui/AbstractColorPicker.java450
-rw-r--r--server/src/com/vaadin/ui/ColorPicker.java64
-rw-r--r--server/src/com/vaadin/ui/ColorPickerArea.java62
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorChangeEvent.java28
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorChangeListener.java27
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java129
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerGrid.java240
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java200
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java766
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java143
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java218
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorSelector.java28
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/HasColorChangeListener.java19
-rw-r--r--server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java9
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/Color.java378
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientServerRpc.java21
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientState.java18
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridServerRpc.java26
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridState.java22
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerServerRpc.java21
-rw-r--r--shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerState.java25
-rw-r--r--theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml2
-rw-r--r--uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.html339
-rw-r--r--uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.java492
-rw-r--r--uitest/src/com/vaadin/tests/components/customfield/AddressField.java2
-rw-r--r--uitest/src/com/vaadin/tests/components/uitest/reindeer_theme_test.html8
59 files changed, 6172 insertions, 1222 deletions
diff --git a/WebContent/VAADIN/themes/base/base.scss b/WebContent/VAADIN/themes/base/base.scss
index a16b063ba8..640978d316 100644
--- a/WebContent/VAADIN/themes/base/base.scss
+++ b/WebContent/VAADIN/themes/base/base.scss
@@ -5,6 +5,7 @@
@import "button/checkbox.scss";
@import "layout/layout.scss";
@import "caption/caption.scss";
+@import "colorpicker/colorpicker.scss";
@import "common/common.scss";
@import "csslayout/csslayout.scss";
@import "customcomponent/customcomponent.scss";
@@ -61,6 +62,7 @@
@include base-nativebutton;
@include base-checkbox;
@include base-caption;
+ @include base-colorpicker;
// here for now to preserve old semantics
@include base-common;
diff --git a/WebContent/VAADIN/themes/base/colorpicker/colorpicker.scss b/WebContent/VAADIN/themes/base/colorpicker/colorpicker.scss
new file mode 100644
index 0000000000..bd4420b55b
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/colorpicker.scss
@@ -0,0 +1,209 @@
+@mixin base-colorpicker($name : v-colorpicker) {
+
+.#{$name} {
+ text-align: center;
+}
+
+.#{$name}-button-color {
+ border: 1px solid silver;
+ float: left;
+ width: 10px;
+ height: 10px;
+ margin-top: 2px;
+ margin-right: 5px;
+}
+
+.#{$name}-area {
+ border: 1px solid silver;
+ margin: 1px auto;
+}
+
+
+/***************** COLOR HISTORY COMPONENT *****************************/
+.#{$name}-history {
+ margin: 5px;
+}
+
+.#{$name}-history td {
+ border: 1px solid silver !important;
+}
+
+.#{$name}-history td {
+ line-height: 15px;
+}
+/***********************************************************************/
+
+
+/**************** COLOR POPUP COMPONENT ********************************/
+.#{$name}-popup {
+ width: 244px;
+}
+
+.#{$name}-popup .v-scrollable {
+ background-color: #dddddd;
+}
+
+.#{$name}-popup .v-tabsheet-content .v-scrollable {
+ background-color: #eaeaea;
+}
+
+.#{$name}-popup .v-tabsheet-content .v-tabsheet-tabsheetpanel {
+ background: transparent;
+}
+
+.#{$name}-popup .resize-button {
+ border: 0px solid silver;
+ background: url(images/resizebg.png);
+ margin-top: 5px;
+}
+
+.#{$name}-popup .resize-button-caption {
+ display: none;
+}
+
+.#{$name}-popup .resize-button:hover {
+ background: url(images/resizebg-selected.png);
+}
+
+.#{$name}-popup .resize-button:focus {
+ outline: none;
+}
+
+/***********************************************************************/
+
+
+/*********************** COLOR GRADIENT *******************************/
+.#{$name}-gradient {
+ width: 220px;
+ height: 220px;
+ padding-left: 10px;
+ margin-top: 0px;
+}
+
+.#{$name}-gradient .#{$name}-gradient-clicklayer {
+ background-color: white;
+ filter: alpha(opacity = 0);
+ opacity: 0;
+}
+
+.#{$name}-popup #rgb-gradient .#{$name}-gradient-background {
+ width: 220px;
+ height: 220px;
+ background: url(images/gradient2.png);
+}
+
+.#{$name}-popup #hsv-gradient .#{$name}-gradient-foreground {
+ background: url(images/gradient.png);
+}
+
+.#{$name}-popup .#{$name}-gradient-lowerbox {
+ border-right: 1px solid white;
+ border-top: 1px solid white;
+}
+
+.#{$name}-popup .#{$name}-gradient-higherbox {
+ border-left: 1px solid white;
+ border-bottom: 1px solid white;
+}
+/**********************************************************************/
+
+
+/************************ COLOR SLIDER ********************************/
+.#{$name}-popup .rgb-sliders {
+ width: 227px;
+ padding-left: 10px;
+ color: #444444;
+ text-shadow: 0 1px 0 #FFFFFF;
+}
+
+.#{$name}-popup .rgb-sliders .red .v-slider-base {
+ background-color: red;
+}
+
+.#{$name}-popup .rgb-sliders .green .v-slider-base {
+ background-color: green;
+}
+
+.#{$name}-popup .rgb-sliders .blue .v-slider-base {
+ background-color: blue;
+}
+
+.#{$name}-popup .hsv-sliders {
+ padding-left: 10px;
+ color: #444444;
+ text-shadow: 0 1px 0 #FFFFFF;
+}
+
+.#{$name}-popup .hue-slider {
+ height: 10px;
+ border: 0px solid silver;
+ background-image: url(images/slider_hue_bg.png);
+ background-color: transparent;
+ background-repeat: no-repeat;
+ background-position: 0 3px;
+ margin-top: 0px;
+}
+
+.#{$name}-popup .hue-slider .v-slider-handle {
+ margin-top: -2px;
+}
+
+.#{$name}-popup .hue-slider .v-slider-base {
+ border: 0px none;
+ height: 0px;
+ background-color: transparent;
+}
+/****************************************************************/
+
+
+/****************** COLOR PREVIEW *******************************/
+.#{$name}-popup .#{$name}-preview {
+ margin-top: 5px;
+ padding-left: 11px;
+ padding-right: 10px;
+ margin-bottom: 0px;
+}
+
+.#{$name}-popup .v-absolutelayout-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.#{$name}-popup .#{$name}-preview-textfield {
+ background: none;
+ overflow: hidden;
+ overflow-y: hidden;
+ overflow-x: hidden;
+}
+
+.#{$name}-popup .v-textfield-dark {
+ color: #FFFFFF;
+}
+
+.#{$name}-popup .v-textfield-light {
+ color: #000000;
+}
+/****************************************************************/
+
+
+/*************** COLOR SELECT ***********************************/
+.#{$name}-popup .colorselect {
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+.#{$name}-popup .v-tabsheet .#{$name}-grid {
+ height: 319px;
+}
+
+.#{$name}-popup .colorselect td {
+ line-height: 15px;
+}
+
+.#{$name}-popup .v-filterselect {
+ padding-right: 16px;
+}
+/****************************************************************/
+
+} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/gradient.png b/WebContent/VAADIN/themes/base/colorpicker/images/gradient.png
new file mode 100644
index 0000000000..def063a8ab
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/images/gradient.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png b/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png
new file mode 100644
index 0000000000..f51ed752a7
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png
new file mode 100644
index 0000000000..6e56ec0cc7
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png
new file mode 100644
index 0000000000..b6e3532713
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png b/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png
new file mode 100644
index 0000000000..bcef2c5575
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/datefield/datefield.scss b/WebContent/VAADIN/themes/base/datefield/datefield.scss
index dcefe27f09..e6309aadd3 100644
--- a/WebContent/VAADIN/themes/base/datefield/datefield.scss
+++ b/WebContent/VAADIN/themes/base/datefield/datefield.scss
@@ -8,6 +8,10 @@
.#{$primaryStyleName}-textfield {
vertical-align: top;
}
+.v-ie & .#{$primaryStyleName}-button:after {
+ content: "\200B";
+}
+
.#{$primaryStyleName}-button {
cursor: pointer;
}
diff --git a/WebContent/VAADIN/themes/chameleon/components/colorpicker/colorpicker.scss b/WebContent/VAADIN/themes/chameleon/components/colorpicker/colorpicker.scss
new file mode 100644
index 0000000000..98f00f0626
--- /dev/null
+++ b/WebContent/VAADIN/themes/chameleon/components/colorpicker/colorpicker.scss
@@ -0,0 +1,15 @@
+@mixin chameleon-colorpicker($name : v-colorpicker) {
+
+.#{$name}-button-color {
+ border: 1px solid #8B8B8B;
+}
+
+.#{$name}-popup {
+ width: 248px;
+}
+
+.#{$name}-popup .v-tabsheet .#{$name}-grid {
+ height: 308px;
+}
+
+} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/chameleon/components/components.scss b/WebContent/VAADIN/themes/chameleon/components/components.scss
index 79b5a2d468..9f29827de0 100644
--- a/WebContent/VAADIN/themes/chameleon/components/components.scss
+++ b/WebContent/VAADIN/themes/chameleon/components/components.scss
@@ -1,5 +1,6 @@
@import "accordion/accordion.scss";
@import "button/button.scss";
+@import "colorpicker/colorpicker.scss";
@import "label/label.scss";
@import "menubar/menubar.scss";
@import "notification/notification.scss";
@@ -22,6 +23,7 @@
@include chameleon-accordion;
@include chameleon-button;
+ @include chameleon-colorpicker;
@include chameleon-label;
@include chameleon-menubar;
@include chameleon-notification;
diff --git a/WebContent/VAADIN/themes/liferay/colorpicker/colorpicker.scss b/WebContent/VAADIN/themes/liferay/colorpicker/colorpicker.scss
new file mode 100644
index 0000000000..fc50297388
--- /dev/null
+++ b/WebContent/VAADIN/themes/liferay/colorpicker/colorpicker.scss
@@ -0,0 +1,19 @@
+@mixin liferay-colorpicker($name : v-colorpicker) {
+
+.#{$name}-button-color {
+ border: 1px solid #999999;
+}
+
+.#{$name}-popup {
+ width: 252px;
+}
+
+.#{$name}-popup .v-tabsheet .#{$name}-grid {
+ height: 312px;
+}
+
+.#{$name}-popup .v-filterselect {
+ padding-right: 24px;
+}
+
+} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/liferay/liferay.scss b/WebContent/VAADIN/themes/liferay/liferay.scss
index 3128e48c76..299542fea0 100644
--- a/WebContent/VAADIN/themes/liferay/liferay.scss
+++ b/WebContent/VAADIN/themes/liferay/liferay.scss
@@ -2,6 +2,7 @@
@import "accordion/accordion.scss";
@import "button/button.scss";
+@import "colorpicker/colorpicker.scss";
@import "common/common.scss";
@@ -29,6 +30,7 @@
// TODO @each
@include liferay-accordion;
@include liferay-button;
+ @include liferay-colorpicker;
@include liferay-common;
@include liferay-contextmenu;
diff --git a/WebContent/VAADIN/themes/reindeer/colorpicker/colorpicker.scss b/WebContent/VAADIN/themes/reindeer/colorpicker/colorpicker.scss
new file mode 100644
index 0000000000..4224691d12
--- /dev/null
+++ b/WebContent/VAADIN/themes/reindeer/colorpicker/colorpicker.scss
@@ -0,0 +1,15 @@
+@mixin reindeer-colorpicker($name : v-colorpicker) {
+
+.#{$name}-popup {
+ width: 246px;
+}
+
+.#{$name}-popup .v-tabsheet .#{$name}-grid {
+ height: 284px;
+}
+
+.#{$name}-popup .v-filterselect {
+ padding-right: 25px;
+}
+
+} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/reindeer/reindeer.scss b/WebContent/VAADIN/themes/reindeer/reindeer.scss
index ce6b54610e..f02fcf18a8 100644
--- a/WebContent/VAADIN/themes/reindeer/reindeer.scss
+++ b/WebContent/VAADIN/themes/reindeer/reindeer.scss
@@ -5,6 +5,7 @@
@import "a-sprite-definitions/a-sprite-definitions.scss";
@import "button/button.scss";
@import "button/nativebutton.scss";
+@import "colorpicker/colorpicker.scss";
@import "common/common.scss";
@@ -42,6 +43,7 @@
// TODO @include a-sprite-definitions;
@include reindeer-button;
@include reindeer-nativebutton;
+ @include reindeer-colorpicker;
@include reindeer-common;
@include reindeer-datefield;
@include reindeer-inlinedatefield;
diff --git a/WebContent/VAADIN/themes/runo/colorpicker/colorpicker.scss b/WebContent/VAADIN/themes/runo/colorpicker/colorpicker.scss
new file mode 100644
index 0000000000..df48c10a86
--- /dev/null
+++ b/WebContent/VAADIN/themes/runo/colorpicker/colorpicker.scss
@@ -0,0 +1,20 @@
+@mixin runo-colorpicker($name : v-colorpicker) {
+
+.#{$name}-popup {
+ width: 248px;
+}
+
+.#{$name}-popup .v-tabsheet .#{$name}-grid {
+ height: 305px;
+}
+
+.#{$name}-popup .v-tabsheet-deco {
+ background: none;
+ height: 0;
+}
+
+.#{$name}-popup .v-filterselect {
+ padding-right: 25px;
+}
+
+} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/runo/runo.scss b/WebContent/VAADIN/themes/runo/runo.scss
index de4d2b3bbd..395f4d0b1b 100644
--- a/WebContent/VAADIN/themes/runo/runo.scss
+++ b/WebContent/VAADIN/themes/runo/runo.scss
@@ -4,6 +4,7 @@
@import "accordion/accordion.scss";
@import "button/button.scss";
@import "caption/caption.scss";
+@import "colorpicker/colorpicker.scss";
@import "common/common.scss";
@import "datefield/datefield.scss";
@import "inlinedatefield/inlinedatefield.scss";
@@ -39,6 +40,7 @@
@include runo-accordion;
@include runo-button;
@include runo-caption;
+ @include runo-colorpicker;
@include runo-common;
@@ -63,4 +65,4 @@
@include runo-textfield;
@include runo-tree;
@include runo-window;
-} \ No newline at end of file
+}
diff --git a/client/src/com/vaadin/client/ComponentLocator.java b/client/src/com/vaadin/client/ComponentLocator.java
index 854c8535c4..249c3f78f4 100644
--- a/client/src/com/vaadin/client/ComponentLocator.java
+++ b/client/src/com/vaadin/client/ComponentLocator.java
@@ -29,10 +29,10 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.ui.VCssLayout;
import com.vaadin.client.ui.VGridLayout;
-import com.vaadin.client.ui.VOrderedLayout;
import com.vaadin.client.ui.VTabsheetPanel;
import com.vaadin.client.ui.VUI;
import com.vaadin.client.ui.VWindow;
+import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout;
import com.vaadin.client.ui.window.WindowConnector;
import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.Connector;
@@ -315,7 +315,7 @@ public class ComponentLocator {
String childIndexString = part.substring("domChild[".length(),
part.length() - 1);
- if (Util.findWidget(baseElement, null) instanceof VOrderedLayout) {
+ if (Util.findWidget(baseElement, null) instanceof VAbstractOrderedLayout) {
if (element.hasChildNodes()) {
Element e = element.getFirstChildElement().cast();
String cn = e.getClassName();
@@ -563,10 +563,10 @@ public class ComponentLocator {
}
// ChildComponentContainer has been removed and replaced with
- // VOrderLayout.Slot's
- if (w instanceof VOrderedLayout
+ // Slot
+ if (w instanceof VAbstractOrderedLayout
&& "ChildComponentContainer".equals(widgetClassName)) {
- widgetClassName = "VOrderedLayout$Slot";
+ widgetClassName = "Slot";
}
if (w instanceof VTabsheetPanel && widgetPosition != 0) {
@@ -662,8 +662,8 @@ public class ComponentLocator {
}
widgetPosition--;
- } else if (w instanceof VOrderedLayout
- && "VOrderedLayout$Slot".equals(simpleName2)) {
+ } else if (w instanceof VAbstractOrderedLayout
+ && "Slot".equals(simpleName2)) {
child = ((SimplePanel) child).getWidget();
simpleName2 = Util.getSimpleName(child);
if (widgetClassName.equals(simpleName2)) {
diff --git a/client/src/com/vaadin/client/ui/VColorPicker.java b/client/src/com/vaadin/client/ui/VColorPicker.java
new file mode 100644
index 0000000000..7cd5fbfed7
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/VColorPicker.java
@@ -0,0 +1,73 @@
+package com.vaadin.client.ui;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.HTML;
+
+/**
+ * Client side implementation for ColorPicker.
+ *
+ * @since 7.0.0
+ */
+public class VColorPicker extends VButton implements ClickHandler {
+
+ private String color = null;
+
+ private boolean isOpen = false;
+
+ private HTML colorIcon;
+
+ @Override
+ public void onClick(ClickEvent event) {
+ super.onClick(event);
+
+ setOpen(!isOpen);
+ }
+
+ /**
+ * Set the color of the component, e.g. #ffffff
+ *
+ * @param color
+ */
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ /**
+ * Mark the popup opened/closed.
+ *
+ * @param open
+ */
+ public void setOpen(boolean open) {
+ isOpen = open;
+ }
+
+ /**
+ * Check the popup's marked state.
+ *
+ * @return true if the popup has been marked being open, false otherwise.
+ */
+ public boolean isOpen() {
+ return isOpen;
+ }
+
+ /**
+ * Update color icon to show the currently selected color.
+ */
+ public void refreshColor() {
+ if (color != null) {
+
+ if (colorIcon == null) {
+ colorIcon = new HTML();
+ colorIcon.setStylePrimaryName("v-colorpicker-button-color");
+ wrapper.insertBefore(colorIcon.getElement(), captionElement);
+ }
+
+ // Set the color
+ DOM.setStyleAttribute(colorIcon.getElement(), "background", color);
+
+ }
+ }
+
+}
diff --git a/client/src/com/vaadin/client/ui/VColorPickerArea.java b/client/src/com/vaadin/client/ui/VColorPickerArea.java
new file mode 100644
index 0000000000..2327b79f8a
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/VColorPickerArea.java
@@ -0,0 +1,181 @@
+package com.vaadin.client.ui;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Client side implementation for ColorPickerArea.
+ *
+ * @since 7.0.0
+ */
+public class VColorPickerArea extends Widget implements ClickHandler, HasHTML,
+ HasClickHandlers {
+
+ private String color = null;
+
+ private boolean isOpen;
+
+ private HTML caption;
+ private HTML area;
+
+ /**
+ * Initializes an area-style color picker widget.
+ */
+ public VColorPickerArea() {
+ super();
+ setElement(DOM.createDiv());
+
+ caption = new HTML();
+ caption.addStyleName("v-caption");
+ caption.setWidth("");
+
+ area = new HTML();
+ area.setStylePrimaryName(getStylePrimaryName() + "-area");
+
+ getElement().appendChild(caption.getElement());
+ getElement().appendChild(area.getElement());
+
+ addClickHandler(this);
+ }
+
+ /**
+ * Adds a click handler to the widget and sinks the click event.
+ *
+ * @param handler
+ * @return HandlerRegistration used to remove the handler
+ */
+ public HandlerRegistration addClickHandler(ClickHandler handler) {
+ return addDomHandler(handler, ClickEvent.getType());
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ setOpen(!isOpen);
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ int type = DOM.eventGetType(event);
+ switch (type) {
+ case Event.ONCLICK:
+ if (DOM.isOrHasChild(area.getElement(), DOM.eventGetTarget(event))) {
+ super.onBrowserEvent(event);
+ }
+ break;
+ default:
+ super.onBrowserEvent(event);
+ }
+ }
+
+ /**
+ * Mark the popup opened/closed.
+ *
+ * @param open
+ */
+ public void setOpen(boolean open) {
+ isOpen = open;
+ }
+
+ /**
+ * Check the popup's marked state.
+ *
+ * @return true if the popup has been marked being open, false otherwise.
+ */
+ public boolean isOpen() {
+ return isOpen;
+ }
+
+ /**
+ * Sets the caption's content to the given text.
+ *
+ * @param text
+ *
+ * @see Label#setText(String)
+ */
+ @Override
+ public void setText(String text) {
+ caption.setText(text);
+ }
+
+ /**
+ * Gets the caption's contents as text.
+ *
+ * @return the caption's text
+ */
+ @Override
+ public String getText() {
+ return caption.getText();
+ }
+
+ /**
+ * Sets the caption's content to the given HTML.
+ *
+ * @param html
+ */
+ @Override
+ public void setHTML(String html) {
+ caption.setHTML(html);
+ }
+
+ /**
+ * Gets the caption's contents as HTML.
+ *
+ * @return the caption's HTML
+ */
+ @Override
+ public String getHTML() {
+ return caption.getHTML();
+ }
+
+ /**
+ * Sets the color for the area.
+ *
+ * @param color
+ */
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ /**
+ * Update the color area with the currently set color.
+ */
+ public void refreshColor() {
+ if (color != null) {
+ // Set the color
+ DOM.setStyleAttribute(area.getElement(), "background", color);
+ }
+ }
+
+ @Override
+ public void setStylePrimaryName(String style) {
+ super.setStylePrimaryName(style);
+ area.setStylePrimaryName(getStylePrimaryName() + "-area");
+ }
+
+ /**
+ * Sets the color area's height. This height does not include caption or
+ * decorations such as border, margin, and padding.
+ */
+ @Override
+ public void setHeight(String height) {
+ area.setHeight(height);
+ }
+
+ /**
+ * Sets the color area's width. This width does not include caption or
+ * decorations such as border, margin, and padding.
+ */
+ @Override
+ public void setWidth(String width) {
+ area.setWidth(width);
+ }
+
+}
diff --git a/client/src/com/vaadin/client/ui/VHorizontalLayout.java b/client/src/com/vaadin/client/ui/VHorizontalLayout.java
index 53a933e374..a75e681bcf 100644
--- a/client/src/com/vaadin/client/ui/VHorizontalLayout.java
+++ b/client/src/com/vaadin/client/ui/VHorizontalLayout.java
@@ -16,11 +16,12 @@
package com.vaadin.client.ui;
import com.vaadin.client.StyleConstants;
+import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout;
/**
* Represents a layout where the children is ordered vertically
*/
-public class VHorizontalLayout extends VOrderedLayout {
+public class VHorizontalLayout extends VAbstractOrderedLayout {
public static final String CLASSNAME = "v-horizontallayout";
diff --git a/client/src/com/vaadin/client/ui/VOrderedLayout.java b/client/src/com/vaadin/client/ui/VOrderedLayout.java
deleted file mode 100644
index bbcb2f85a4..0000000000
--- a/client/src/com/vaadin/client/ui/VOrderedLayout.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.vaadin.client.ui;
-
-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.client.LayoutManager;
-import com.vaadin.client.StyleConstants;
-import com.vaadin.client.Util;
-import com.vaadin.client.ui.layout.ElementResizeListener;
-import com.vaadin.shared.ui.AlignmentInfo;
-import com.vaadin.shared.ui.MarginInfo;
-
-/**
- * Base class for ordered layouts
- */
-public class VOrderedLayout extends FlowPanel {
-
- private static final String ALIGN_CLASS_PREFIX = "v-align-";
-
- protected boolean spacing = false;
-
- /** For internal use only. May be removed or replaced in the future. */
- public boolean vertical = true;
-
- protected boolean definedHeight = false;
-
- private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>();
-
- private Element expandWrapper;
-
- private LayoutManager layoutManager;
-
- public VOrderedLayout(boolean vertical) {
- this.vertical = vertical;
- }
-
- /**
- * Add or move a slot to another index.
- * <p>
- * For internal use only. May be removed or replaced in the future.
- * <p>
- * You should note that the index does not refer to the DOM index if
- * spacings are used. If spacings are used then the index will be adjusted
- * to include the spacings when inserted.
- * <p>
- * For instance when using spacing the index converts to DOM index in the
- * following way:
- *
- * <pre>
- * index : 0 -> DOM index: 0
- * index : 1 -> DOM index: 1
- * index : 2 -> DOM index: 3
- * index : 3 -> DOM index: 5
- * index : 4 -> DOM index: 7
- * </pre>
- *
- * When using this method never account for spacings.
- * </p>
- *
- * @param slot
- * The slot to move or add
- * @param index
- * The index where the slot should be placed.
- */
- public void addOrMoveSlot(Slot slot, int index) {
- if (slot.getParent() == this) {
- int currentIndex = getWidgetIndex(slot);
- if (index == currentIndex) {
- return;
- }
- }
-
- insert(slot, index);
-
- /*
- * We need to confirm spacings are correctly applied after each insert.
- */
- setSpacing(spacing);
- }
-
- /**
- * {@inheritDoc}
- */
- @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) {
- if (spacing) {
- if (beforeIndex != 0) {
- /*
- * Since the spacing elements are located at the same DOM
- * level as the slots we need to take them into account when
- * calculating the slot position.
- *
- * The spacing elements are always located before the actual
- * slot except for the first slot which do not have a
- * spacing element like this
- *
- * |<slot1><spacing2><slot2><spacing3><slot3>...|
- */
- beforeIndex = beforeIndex * 2 - 1;
- }
- }
- DOM.insertChild(container, child.getElement(), beforeIndex);
- } else {
- DOM.appendChild(container, child.getElement());
- }
-
- // Adopt.
- adopt(child);
- }
-
- /**
- * Remove a slot from the layout
- *
- * @param widget
- * @return
- */
- public void removeWidget(Widget widget) {
- Slot slot = widgetToSlot.get(widget);
- remove(slot);
- widgetToSlot.remove(widget);
- }
-
- /**
- * Get the containing slot for a widget. If no slot is found a new slot is
- * created and returned.
- *
- * @param widget
- * The widget whose slot you want to get
- *
- * @return
- */
- public Slot getSlot(Widget widget) {
- Slot slot = widgetToSlot.get(widget);
- if (slot == null) {
- slot = new Slot(widget);
- widgetToSlot.put(widget, slot);
- }
- return slot;
- }
-
- /**
- * Gets a slot based on the widget element. If no slot is found then null is
- * returned.
- *
- * @param widgetElement
- * The element of the widget ( Same as getWidget().getElement() )
- * @return
- */
- public Slot getSlot(Element widgetElement) {
- for (Map.Entry<Widget, Slot> entry : widgetToSlot.entrySet()) {
- if (entry.getKey().getElement() == widgetElement) {
- return entry.getValue();
- }
- }
- return null;
- }
-
- /**
- * Defines where the caption should be placed
- */
- public enum CaptionPosition {
- TOP, RIGHT, BOTTOM, LEFT
- }
-
- /**
- * Represents a slot which contains the actual widget in the layout.
- */
- public final class Slot extends SimplePanel {
-
- public static final String SLOT_CLASSNAME = "v-slot";
-
- private Element spacer;
- private Element captionWrap;
- private Element caption;
- private Element captionText;
- private Icon icon;
- private Element errorIcon;
- private Element requiredIcon;
-
- private ElementResizeListener captionResizeListener;
-
- private ElementResizeListener widgetResizeListener;
-
- private ElementResizeListener spacingResizeListener;
-
- // 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;
-
- /**
- * Constructor
- *
- * @param widget
- * The widget to put in the slot
- *
- * @param layoutManager
- * The layout manager used by the layout
- */
- private Slot(Widget widget) {
- setStyleName(SLOT_CLASSNAME);
- setWidget(widget);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.SimplePanel#remove(com.google.gwt.user
- * .client.ui.Widget)
- */
- @Override
- public boolean remove(Widget w) {
- detachListeners();
- return super.remove(w);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.SimplePanel#setWidget(com.google.gwt
- * .user.client.ui.Widget)
- */
- @Override
- public void setWidget(Widget w) {
- detachListeners();
- super.setWidget(w);
- attachListeners();
- }
-
- /**
- * Attached resize listeners to the widget, caption and spacing elements
- */
- private void attachListeners() {
- if (getWidget() != null && getLayoutManager() != null) {
- LayoutManager lm = getLayoutManager();
- if (getCaptionElement() != null
- && captionResizeListener != null) {
- lm.addElementResizeListener(getCaptionElement(),
- captionResizeListener);
- }
- if (widgetResizeListener != null) {
- lm.addElementResizeListener(getWidget().getElement(),
- widgetResizeListener);
- }
- if (getSpacingElement() != null
- && spacingResizeListener != null) {
- lm.addElementResizeListener(getSpacingElement(),
- spacingResizeListener);
- }
- }
- }
-
- /**
- * Detaches resize listeners from the widget, caption and spacing
- * elements
- */
- private void detachListeners() {
- if (getWidget() != null && getLayoutManager() != null) {
- LayoutManager lm = getLayoutManager();
- if (getCaptionElement() != null
- && captionResizeListener != null) {
- lm.removeElementResizeListener(getCaptionElement(),
- captionResizeListener);
- }
- if (widgetResizeListener != null) {
- lm.removeElementResizeListener(getWidget().getElement(),
- widgetResizeListener);
- }
- if (getSpacingElement() != null
- && spacingResizeListener != null) {
- lm.removeElementResizeListener(getSpacingElement(),
- spacingResizeListener);
- }
- }
- }
-
- public ElementResizeListener getCaptionResizeListener() {
- return captionResizeListener;
- }
-
- public void setCaptionResizeListener(
- ElementResizeListener captionResizeListener) {
- detachListeners();
- this.captionResizeListener = captionResizeListener;
- attachListeners();
- }
-
- public ElementResizeListener getWidgetResizeListener() {
- return widgetResizeListener;
- }
-
- public void setWidgetResizeListener(
- ElementResizeListener widgetResizeListener) {
- detachListeners();
- this.widgetResizeListener = widgetResizeListener;
- attachListeners();
- }
-
- public ElementResizeListener getSpacingResizeListener() {
- return spacingResizeListener;
- }
-
- public void setSpacingResizeListener(
- ElementResizeListener spacingResizeListener) {
- detachListeners();
- this.spacingResizeListener = spacingResizeListener;
- attachListeners();
- }
-
- /**
- * Returns the alignment for the slot
- *
- */
- public AlignmentInfo getAlignment() {
- return alignment;
- }
-
- /**
- * Sets the style names for the slot containing the widget
- *
- * @param stylenames
- * The style names for the slot
- */
- protected void setStyleNames(String... stylenames) {
- setStyleName(SLOT_CLASSNAME);
- if (stylenames != null) {
- for (String stylename : stylenames) {
- addStyleDependentName(stylename);
- }
- }
-
- // Ensure alignment style names are correct
- setAlignment(alignment);
- }
-
- /**
- * Sets how the widget is aligned inside the slot
- *
- * @param alignment
- * The alignment inside the slot
- */
- public void setAlignment(AlignmentInfo alignment) {
- this.alignment = alignment;
-
- if (alignment != null && alignment.isHorizontalCenter()) {
- addStyleName(ALIGN_CLASS_PREFIX + "center");
- removeStyleName(ALIGN_CLASS_PREFIX + "right");
- } else if (alignment != null && 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 != null && alignment.isVerticalCenter()) {
- addStyleName(ALIGN_CLASS_PREFIX + "middle");
- removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
- } else if (alignment != null && alignment.isBottom()) {
- addStyleName(ALIGN_CLASS_PREFIX + "bottom");
- removeStyleName(ALIGN_CLASS_PREFIX + "middle");
- } else {
- removeStyleName(ALIGN_CLASS_PREFIX + "middle");
- removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
- }
- }
-
- /**
- * Set how the slot should be expanded relative to the other slots
- *
- * @param expandRatio
- * The ratio of the space the slot should occupy
- *
- */
- public void setExpandRatio(double expandRatio) {
- this.expandRatio = expandRatio;
- }
-
- /**
- * Get the expand ratio for the slot. The expand ratio describes how the
- * slot should be resized compared to other slots in the layout
- *
- * @return
- */
- public double getExpandRatio() {
- return expandRatio;
- }
-
- /**
- * Set the spacing for the slot. The spacing determines if there should
- * be empty space around the slot when the slot.
- *
- * @param spacing
- * Should spacing be enabled
- */
- public void setSpacing(boolean spacing) {
- if (spacing && spacer == null) {
- spacer = DOM.createDiv();
- spacer.addClassName("v-spacing");
-
- /*
- * This has to be done here for the initial render. In other
- * cases where the spacer already exists onAttach will handle
- * it.
- */
- getElement().getParentElement().insertBefore(spacer,
- getElement());
- } else if (!spacing && spacer != null) {
- spacer.removeFromParent();
- spacer = null;
- }
- }
-
- /**
- * Get the element which is added to make the spacing
- *
- * @return
- */
- public Element getSpacingElement() {
- return spacer;
- }
-
- /**
- * Does the slot have spacing
- */
- public boolean hasSpacing() {
- return getSpacingElement() != null;
- }
-
- /**
- * Get the vertical amount in pixels of the spacing
- */
- protected int getVerticalSpacing() {
- if (spacer == null) {
- return 0;
- } else if (getLayoutManager() != null) {
- return getLayoutManager().getOuterHeight(spacer);
- }
- return spacer.getOffsetHeight();
- }
-
- /**
- * Get the horizontal amount of pixels of the spacing
- *
- * @return
- */
- protected int getHorizontalSpacing() {
- if (spacer == null) {
- return 0;
- } else if (getLayoutManager() != null) {
- return getLayoutManager().getOuterWidth(spacer);
- }
- return spacer.getOffsetWidth();
- }
-
- /**
- * Set the position of the caption relative to the slot
- *
- * @param captionPosition
- * The position of the caption
- */
- 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());
- }
-
- /**
- * Get the position of the caption relative to the slot
- */
- public CaptionPosition getCaptionPosition() {
- return captionPosition;
- }
-
- /**
- * Set the caption of the slot
- *
- * @param captionText
- * The text of the caption
- * @param iconUrl
- * The icon URL
- * @param styles
- * The style names
- * @param error
- * The error message
- * @param showError
- * Should the error message be shown
- * @param required
- * Is the (field) required
- * @param enabled
- * Is the component enabled
- */
- 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(StyleConstants.UI_WIDGET);
- 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("&nbsp;");
- } 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();
- caption.insertFirst(icon.getElement());
- }
- 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);
- }
- }
- }
-
- /**
- * Does the slot have a caption
- */
- public boolean hasCaption() {
- return caption != null;
- }
-
- /**
- * Get the slots caption element
- */
- public Element getCaptionElement() {
- return caption;
- }
-
- /**
- * Set if the slot has a relative width
- *
- * @param relativeWidth
- * True if slot uses relative width, false if the slot has a
- * static width
- */
- private boolean relativeWidth = false;
-
- public void setRelativeWidth(boolean relativeWidth) {
- this.relativeWidth = relativeWidth;
- updateRelativeSize(relativeWidth, "width");
- }
-
- /**
- * Set if the slot has a relative height
- *
- * @param relativeHeight
- * Trie if the slot uses a relative height, false if the slot
- * has a static height
- */
- private boolean relativeHeight = false;
-
- public void setRelativeHeight(boolean relativeHeight) {
- this.relativeHeight = relativeHeight;
- updateRelativeSize(relativeHeight, "height");
- }
-
- /**
- * Updates the captions size if the slot is relative
- *
- * @param isRelativeSize
- * Is the slot relatived sized
- * @param direction
- * The directorion of the caption
- */
- 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();
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
- * .user.client.Event)
- */
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (DOM.eventGetType(event) == Event.ONLOAD
- && icon.getElement() == DOM.eventGetTarget(event)) {
- if (getLayoutManager() != null) {
- getLayoutManager().layoutLater();
- } else {
- updateCaptionOffset(caption);
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.google.gwt.user.client.ui.SimplePanel#getContainerElement()
- */
- @Override
- protected Element getContainerElement() {
- if (captionWrap == null) {
- return getElement();
- } else {
- return captionWrap;
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.google.gwt.user.client.ui.Widget#onDetach()
- */
- @Override
- protected void onDetach() {
- if (spacer != null) {
- spacer.removeFromParent();
- }
- super.onDetach();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.google.gwt.user.client.ui.Widget#onAttach()
- */
- @Override
- protected void onAttach() {
- super.onAttach();
- if (spacer != null) {
- getElement().getParentElement().insertBefore(spacer,
- getElement());
- }
- }
- }
-
- /**
- * The icon for each widget. Located in the caption of the slot.
- */
- public static class Icon extends UIObject {
-
- public static final String CLASSNAME = "v-icon";
-
- private String myUrl;
-
- /**
- * Constructor
- */
- public Icon() {
- setElement(DOM.createImg());
- DOM.setElementProperty(getElement(), "alt", "");
- setStyleName(CLASSNAME);
- }
-
- /**
- * Set the URL where the icon is located
- *
- * @param url
- * A fully qualified URL
- */
- 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;
- }
- }
- }
-
- /**
- * Set the layout manager for the layout
- *
- * @param manager
- * The layout manager to use
- */
- public void setLayoutManager(LayoutManager manager) {
- layoutManager = manager;
- }
-
- /**
- * Get the layout manager used by this layout
- *
- */
- public LayoutManager getLayoutManager() {
- return layoutManager;
- }
-
- /**
- * Deducts the caption position by examining the wrapping element.
- * <p>
- * For internal use only. May be removed or replaced in the future.
- *
- * @param captionWrap
- * The wrapping element
- *
- * @return The caption position
- */
- public CaptionPosition getCaptionPositionFromElement(Element captionWrap) {
- RegExp captionPositionRegexp = RegExp.compile("v-caption-on-(\\S+)");
-
- // 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;
- }
-
- /**
- * Update the offset off the caption relative to the slot
- * <p>
- * For internal use only. May be removed or replaced in the future.
- *
- * @param caption
- * The caption element
- */
- public 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);
- }
- }
- }
- }
-
- /**
- * Set the margin of the layout
- *
- * @param marginInfo
- * The margin information
- */
- public void setMargin(MarginInfo marginInfo) {
- if (marginInfo != null) {
- setStyleName("v-margin-top", marginInfo.hasTop());
- setStyleName("v-margin-right", marginInfo.hasRight());
- setStyleName("v-margin-bottom", marginInfo.hasBottom());
- setStyleName("v-margin-left", marginInfo.hasLeft());
- }
- }
-
- /**
- * Turn on or off spacing in the layout
- *
- * @param spacing
- * True if spacing should be used, false if not
- */
- public void setSpacing(boolean spacing) {
- this.spacing = spacing;
- for (Slot slot : widgetToSlot.values()) {
- if (getWidgetIndex(slot) > 0) {
- slot.setSpacing(spacing);
- } else {
- slot.setSpacing(false);
- }
- }
- }
-
- /**
- * Triggers a recalculation of the expand width and heights
- */
- 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.relativeHeight) {
- Util.notifyParentOfSizeChange(this, true);
- }
- } else {
- slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%");
- if (slot.relativeWidth) {
- Util.notifyParentOfSizeChange(this, true);
- }
- }
- }
- }
- }
-
- /**
- * Removes elements used to expand a slot.
- * <p>
- * For internal use only. May be removed or replaced in the future.
- */
- public 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;
- }
- }
-
- /**
- * Adds elements used to expand a slot
- */
- 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 = vertical ? slot.getVerticalSpacing() : slot
- .getHorizontalSpacing();
- 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();
- }
- }
-
- /**
- * Perform a recalculation of the layout height
- */
- 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();
- }
- VOrderedLayout.this.getElement().getStyle()
- .setHeight(newHeight, Unit.PX);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setHeight(String height) {
- super.setHeight(height);
- definedHeight = (height != null && !"".equals(height));
- }
-
- /**
- * Sets the slots style names. The style names will be prefixed with the
- * v-slot prefix.
- *
- * @param stylenames
- * The style names of the slot.
- */
- public void setSlotStyleNames(Widget widget, String... stylenames) {
- Slot slot = getSlot(widget);
- if (slot == null) {
- throw new IllegalArgumentException(
- "A slot for the widget could not be found. Has the widget been added to the layout?");
- }
- slot.setStyleNames(stylenames);
- }
-
-}
diff --git a/client/src/com/vaadin/client/ui/VVerticalLayout.java b/client/src/com/vaadin/client/ui/VVerticalLayout.java
index 1a3ce332f5..2a81e61d9a 100644
--- a/client/src/com/vaadin/client/ui/VVerticalLayout.java
+++ b/client/src/com/vaadin/client/ui/VVerticalLayout.java
@@ -16,11 +16,12 @@
package com.vaadin.client.ui;
import com.vaadin.client.StyleConstants;
+import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout;
/**
* Represents a layout where the children is ordered vertically
*/
-public class VVerticalLayout extends VOrderedLayout {
+public class VVerticalLayout extends VAbstractOrderedLayout {
public static final String CLASSNAME = "v-verticallayout";
diff --git a/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java b/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java
new file mode 100644
index 0000000000..27261b3812
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java
@@ -0,0 +1,86 @@
+package com.vaadin.client.ui.colorpicker;
+
+import java.util.Set;
+
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.shared.ui.colorpicker.ColorPickerState;
+
+/**
+ * An abstract class that defines default implementation for a color picker
+ * connector.
+ *
+ * @since 7.0.0
+ */
+public abstract class AbstractColorPickerConnector extends
+ AbstractComponentConnector implements ClickHandler {
+
+ @Override
+ public ColorPickerState getState() {
+ return (ColorPickerState) super.getState();
+ }
+
+ @Override
+ public boolean delegateCaptionHandling() {
+ return false;
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ // NOTE: this method is called after @DelegateToWidget
+ super.onStateChanged(stateChangeEvent);
+ Set<String> changedProperties = stateChangeEvent.getChangedProperties();
+ if (changedProperties.contains("color")) {
+ refreshColor();
+
+ if (getState().showDefaultCaption
+ && (getState().caption == null || ""
+ .equals(getState().caption))) {
+
+ setCaption(getState().color);
+ }
+ }
+ if (changedProperties.contains("caption")
+ || changedProperties.contains("htmlContentAllowed")
+ || changedProperties.contains("showDefaultCaption")) {
+
+ setCaption(getCaption());
+ }
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ if (getWidget() instanceof HasClickHandlers) {
+ ((HasClickHandlers) getWidget()).addClickHandler(this);
+ }
+ }
+
+ /**
+ * Get caption for the color picker widget.
+ *
+ * @return
+ */
+ protected String getCaption() {
+ if (getState().showDefaultCaption
+ && (getState().caption == null || "".equals(getState().caption))) {
+ return getState().color;
+ }
+ return getState().caption;
+ }
+
+ /**
+ * Set caption of the color picker widget.
+ *
+ * @param caption
+ */
+ protected abstract void setCaption(String caption);
+
+ /**
+ * Update the widget to show the currently selected color.
+ */
+ protected abstract void refreshColor();
+
+}
diff --git a/client/src/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java
new file mode 100644
index 0000000000..12bc23966f
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java
@@ -0,0 +1,53 @@
+package com.vaadin.client.ui.colorpicker;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.communication.RpcProxy;
+import com.vaadin.client.ui.VColorPickerArea;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc;
+
+/**
+ * A class that defines an implementation for a color picker connector. Connects
+ * the server side {@link com.vaadin.ui.ColorPickerArea} with the client side
+ * counterpart {@link VColorPickerArea}
+ *
+ * @since 7.0.0
+ */
+@Connect(com.vaadin.ui.ColorPickerArea.class)
+public class ColorPickerAreaConnector extends AbstractColorPickerConnector {
+
+ private ColorPickerServerRpc rpc = RpcProxy.create(
+ ColorPickerServerRpc.class, this);
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VColorPickerArea.class);
+ }
+
+ @Override
+ public VColorPickerArea getWidget() {
+ return (VColorPickerArea) super.getWidget();
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ rpc.openPopup(getWidget().isOpen());
+ }
+
+ @Override
+ protected void setCaption(String caption) {
+ if (getState().htmlContentAllowed) {
+ getWidget().setHTML(caption);
+ } else {
+ getWidget().setText(caption);
+ }
+ }
+
+ @Override
+ protected void refreshColor() {
+ getWidget().refreshColor();
+ }
+
+}
diff --git a/client/src/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java
new file mode 100644
index 0000000000..7329bffa09
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java
@@ -0,0 +1,52 @@
+package com.vaadin.client.ui.colorpicker;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.communication.RpcProxy;
+import com.vaadin.client.ui.VColorPicker;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc;
+
+/**
+ * A class that defines default implementation for a color picker connector.
+ * Connects the server side {@link com.vaadin.ui.ColorPicker} with the client
+ * side counterpart {@link VColorPicker}
+ *
+ * @since 7.0.0
+ */
+@Connect(com.vaadin.ui.ColorPicker.class)
+public class ColorPickerConnector extends AbstractColorPickerConnector {
+
+ private ColorPickerServerRpc rpc = RpcProxy.create(
+ ColorPickerServerRpc.class, this);
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VColorPicker.class);
+ }
+
+ @Override
+ public VColorPicker getWidget() {
+ return (VColorPicker) super.getWidget();
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ rpc.openPopup(getWidget().isOpen());
+ }
+
+ @Override
+ protected void setCaption(String caption) {
+ if (getState().htmlContentAllowed) {
+ getWidget().setHtml(caption);
+ } else {
+ getWidget().setText(caption);
+ }
+ }
+
+ @Override
+ protected void refreshColor() {
+ getWidget().refreshColor();
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java
new file mode 100644
index 0000000000..9a9dd09999
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java
@@ -0,0 +1,71 @@
+package com.vaadin.client.ui.colorpicker;
+
+import java.util.Set;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.communication.RpcProxy;
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGradientServerRpc;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGradientState;
+
+/**
+ * A class that defines the default implementation for a color picker gradient
+ * connector. Connects the server side
+ * {@link com.vaadin.ui.components.colorpicker.ColorPickerGradient} with the
+ * client side counterpart {@link VColorPickerGradient}
+ *
+ * @since 7.0.0
+ */
+@Connect(com.vaadin.ui.components.colorpicker.ColorPickerGradient.class)
+public class ColorPickerGradientConnector extends AbstractComponentConnector
+ implements MouseUpHandler {
+
+ private ColorPickerGradientServerRpc rpc = RpcProxy.create(
+ ColorPickerGradientServerRpc.class, this);
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VColorPickerGradient.class);
+ }
+
+ @Override
+ public VColorPickerGradient getWidget() {
+ return (VColorPickerGradient) super.getWidget();
+ }
+
+ @Override
+ public ColorPickerGradientState getState() {
+ return (ColorPickerGradientState) super.getState();
+ }
+
+ @Override
+ public void onMouseUp(MouseUpEvent event) {
+ rpc.select(getWidget().getCursorX(), getWidget().getCursorY());
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+ Set<String> changedProperties = stateChangeEvent.getChangedProperties();
+ if (changedProperties.contains("cursorX")
+ || changedProperties.contains("cursorY")) {
+
+ getWidget().setCursor(getState().cursorX, getState().cursorY);
+ }
+ if (changedProperties.contains("bgColor")) {
+ getWidget().setBGColor(getState().bgColor);
+ }
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ getWidget().addMouseUpHandler(this);
+ }
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java
new file mode 100644
index 0000000000..dbce0dd925
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java
@@ -0,0 +1,80 @@
+package com.vaadin.client.ui.colorpicker;
+
+import java.util.Set;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.communication.RpcProxy;
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGridServerRpc;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGridState;
+
+/**
+ * A class that defines the default implementation for a color picker grid
+ * connector. Connects the server side
+ * {@link com.vaadin.ui.components.colorpicker.ColorPickerGrid} with the client
+ * side counterpart {@link VColorPickerGrid}
+ *
+ * @since 7.0.0
+ */
+@Connect(com.vaadin.ui.components.colorpicker.ColorPickerGrid.class)
+public class ColorPickerGridConnector extends AbstractComponentConnector
+ implements ClickHandler {
+
+ private ColorPickerGridServerRpc rpc = RpcProxy.create(
+ ColorPickerGridServerRpc.class, this);
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VColorPickerGrid.class);
+ }
+
+ @Override
+ public VColorPickerGrid getWidget() {
+ return (VColorPickerGrid) super.getWidget();
+ }
+
+ @Override
+ public ColorPickerGridState getState() {
+ return (ColorPickerGridState) super.getState();
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ rpc.select(getWidget().getSelectedX(), getWidget().getSelectedY());
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+ Set<String> changedProperties = stateChangeEvent.getChangedProperties();
+ if (changedProperties.contains("rowCount")
+ || changedProperties.contains("columnCount")
+ || changedProperties.contains("updateGrid")) {
+
+ getWidget().updateGrid(getState().rowCount, getState().columnCount);
+ }
+ if (changedProperties.contains("changedX")
+ || changedProperties.contains("changedY")
+ || changedProperties.contains("changedColor")
+ || changedProperties.contains("updateColor")) {
+
+ getWidget().updateColor(getState().changedColor,
+ getState().changedX, getState().changedY);
+
+ if (!getWidget().isGridLoaded()) {
+ rpc.refresh();
+ }
+ }
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ getWidget().addClickHandler(this);
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java b/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java
new file mode 100644
index 0000000000..6defc57996
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java
@@ -0,0 +1,176 @@
+package com.vaadin.client.ui.colorpicker;
+
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.AbsolutePanel;
+import com.google.gwt.user.client.ui.FocusPanel;
+import com.google.gwt.user.client.ui.HTML;
+
+/**
+ * Client side implementation for ColorPickerGradient.
+ *
+ * @since 7.0.0
+ *
+ */
+public class VColorPickerGradient extends FocusPanel implements
+ MouseDownHandler, MouseUpHandler, MouseMoveHandler {
+
+ /** Set the CSS class name to allow styling. */
+ public static final String CLASSNAME = "v-colorpicker-gradient";
+ public static final String CLASSNAME_BACKGROUND = CLASSNAME + "-background";
+ public static final String CLASSNAME_FOREGROUND = CLASSNAME + "-foreground";
+ public static final String CLASSNAME_LOWERBOX = CLASSNAME + "-lowerbox";
+ public static final String CLASSNAME_HIGHERBOX = CLASSNAME + "-higherbox";
+ public static final String CLASSNAME_CONTAINER = CLASSNAME + "-container";
+ public static final String CLASSNAME_CLICKLAYER = CLASSNAME + "-clicklayer";
+
+ private final HTML background;
+ private final HTML foreground;
+ private final HTML lowercross;
+ private final HTML highercross;
+ private final HTML clicklayer;
+ private final AbsolutePanel container;
+
+ private boolean mouseIsDown = false;
+
+ private int cursorX;
+ private int cursorY;
+
+ /**
+ * Instantiates the client side component for a color picker gradient.
+ */
+ public VColorPickerGradient() {
+ super();
+
+ setStyleName(CLASSNAME);
+
+ int width = 220;
+ int height = 220;
+
+ background = new HTML();
+ background.setStyleName(CLASSNAME_BACKGROUND);
+ background.setPixelSize(width, height);
+
+ foreground = new HTML();
+ foreground.setStyleName(CLASSNAME_FOREGROUND);
+ foreground.setPixelSize(width, height);
+
+ clicklayer = new HTML();
+ clicklayer.setStyleName(CLASSNAME_CLICKLAYER);
+ clicklayer.setPixelSize(width, height);
+ clicklayer.addMouseDownHandler(this);
+ clicklayer.addMouseUpHandler(this);
+ clicklayer.addMouseMoveHandler(this);
+
+ lowercross = new HTML();
+ lowercross.setPixelSize(width / 2, height / 2);
+ lowercross.setStyleName(CLASSNAME_LOWERBOX);
+
+ highercross = new HTML();
+ highercross.setPixelSize(width / 2, height / 2);
+ highercross.setStyleName(CLASSNAME_HIGHERBOX);
+
+ container = new AbsolutePanel();
+ container.setStyleName(CLASSNAME_CONTAINER);
+ container.setPixelSize(width, height);
+ container.add(background, 0, 0);
+ container.add(foreground, 0, 0);
+ container.add(lowercross, 0, height / 2);
+ container.add(highercross, width / 2, 0);
+ container.add(clicklayer, 0, 0);
+
+ add(container);
+ }
+
+ /**
+ * Returns the latest x-coordinate for pressed-down mouse cursor.
+ */
+ protected int getCursorX() {
+ return cursorX;
+ }
+
+ /**
+ * Returns the latest y-coordinate for pressed-down mouse cursor.
+ */
+ protected int getCursorY() {
+ return cursorY;
+ }
+
+ /**
+ * Sets the given css color as the background.
+ *
+ * @param bgColor
+ */
+ protected void setBGColor(String bgColor) {
+ background.getElement().getStyle().setProperty("background", bgColor);
+ }
+
+ @Override
+ public void onMouseDown(MouseDownEvent event) {
+ event.preventDefault();
+
+ mouseIsDown = true;
+ setCursor(event.getX(), event.getY());
+ }
+
+ @Override
+ public void onMouseUp(MouseUpEvent event) {
+ event.preventDefault();
+ mouseIsDown = false;
+ setCursor(event.getX(), event.getY());
+
+ cursorX = event.getX();
+ cursorY = event.getY();
+ }
+
+ @Override
+ public void onMouseMove(MouseMoveEvent event) {
+ event.preventDefault();
+
+ if (mouseIsDown) {
+ setCursor(event.getX(), event.getY());
+ }
+ }
+
+ /**
+ * Sets the latest coordinates for pressed-down mouse cursor and updates the
+ * cross elements.
+ *
+ * @param x
+ * @param y
+ */
+ public void setCursor(int x, int y) {
+ cursorX = x;
+ cursorY = y;
+ if (x >= 0) {
+ DOM.setStyleAttribute(lowercross.getElement(), "width",
+ String.valueOf(x) + "px");
+ }
+ if (y >= 0) {
+ DOM.setStyleAttribute(lowercross.getElement(), "top",
+ String.valueOf(y) + "px");
+ }
+ if (y >= 0) {
+ DOM.setStyleAttribute(lowercross.getElement(), "height",
+ String.valueOf((background.getOffsetHeight() - y)) + "px");
+ }
+
+ if (x >= 0) {
+ DOM.setStyleAttribute(highercross.getElement(), "width",
+ String.valueOf((background.getOffsetWidth() - x)) + "px");
+ }
+ if (x >= 0) {
+ DOM.setStyleAttribute(highercross.getElement(), "left",
+ String.valueOf(x) + "px");
+ }
+ if (y >= 0) {
+ DOM.setStyleAttribute(highercross.getElement(), "height",
+ String.valueOf((y)) + "px");
+ }
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java b/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java
new file mode 100644
index 0000000000..1af65733aa
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java
@@ -0,0 +1,132 @@
+package com.vaadin.client.ui.colorpicker;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.AbsolutePanel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTMLTable.Cell;
+
+/**
+ * Client side implementation for ColorPickerGrid.
+ *
+ * @since 7.0.0
+ *
+ */
+public class VColorPickerGrid extends AbsolutePanel implements ClickHandler,
+ HasClickHandlers {
+
+ private int rows = 1;
+ private int columns = 1;
+
+ private Grid grid;
+
+ private boolean gridLoaded = false;
+
+ private int selectedX;
+ private int selectedY;
+
+ /**
+ * Instantiates the client side component for a color picker grid.
+ */
+ public VColorPickerGrid() {
+ super();
+
+ this.add(createGrid(), 0, 0);
+ }
+
+ /**
+ * Creates a grid according to the current row and column count information.
+ *
+ * @return grid
+ */
+ private Grid createGrid() {
+ grid = new Grid(rows, columns);
+ grid.setWidth("100%");
+ grid.setHeight("100%");
+ grid.addClickHandler(this);
+ return grid;
+ }
+
+ /**
+ * Updates the row and column count and creates a new grid based on them.
+ * The new grid replaces the old grid if one existed.
+ *
+ * @param rowCount
+ * @param columnCount
+ */
+ protected void updateGrid(int rowCount, int columnCount) {
+ rows = rowCount;
+ columns = columnCount;
+ this.remove(grid);
+ this.add(createGrid(), 0, 0);
+ }
+
+ /**
+ * Updates the changed colors within the grid based on the given x- and
+ * y-coordinates. Nothing happens if any of the parameters is null or the
+ * parameter lengths don't match.
+ *
+ * @param changedColor
+ * @param changedX
+ * @param changedY
+ */
+ protected void updateColor(String[] changedColor, String[] changedX,
+ String[] changedY) {
+ if (changedColor != null && changedX != null && changedY != null) {
+ if (changedColor.length == changedX.length
+ && changedX.length == changedY.length) {
+ for (int c = 0; c < changedColor.length; c++) {
+ Element element = grid.getCellFormatter().getElement(
+ Integer.parseInt(changedX[c]),
+ Integer.parseInt(changedY[c]));
+ element.getStyle().setProperty("background",
+ changedColor[c]);
+ }
+ }
+
+ gridLoaded = true;
+ }
+ }
+
+ /**
+ * Returns currently selected x-coordinate of the grid.
+ */
+ protected int getSelectedX() {
+ return selectedX;
+ }
+
+ /**
+ * Returns currently selected y-coordinate of the grid.
+ */
+ protected int getSelectedY() {
+ return selectedY;
+ }
+
+ /**
+ * Returns true if the colors have been successfully updated at least once,
+ * false otherwise.
+ */
+ protected boolean isGridLoaded() {
+ return gridLoaded;
+ }
+
+ @Override
+ public void onClick(ClickEvent event) {
+ Cell cell = grid.getCellForEvent(event);
+ if (cell == null) {
+ return;
+ }
+
+ selectedY = cell.getRowIndex();
+ selectedX = cell.getCellIndex();
+ }
+
+ @Override
+ public HandlerRegistration addClickHandler(ClickHandler handler) {
+ return addDomHandler(handler, ClickEvent.getType());
+ }
+
+}
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
index 65736397cb..e062d37dd6 100644
--- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
@@ -29,9 +29,6 @@ import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.AbstractLayoutConnector;
import com.vaadin.client.ui.LayoutClickEventHandler;
-import com.vaadin.client.ui.VOrderedLayout;
-import com.vaadin.client.ui.VOrderedLayout.CaptionPosition;
-import com.vaadin.client.ui.VOrderedLayout.Slot;
import com.vaadin.client.ui.layout.ElementResizeEvent;
import com.vaadin.client.ui.layout.ElementResizeListener;
import com.vaadin.shared.AbstractFieldState;
@@ -199,8 +196,8 @@ public abstract class AbstractOrderedLayoutConnector extends
* @see com.vaadin.client.ui.AbstractComponentConnector#getWidget()
*/
@Override
- public VOrderedLayout getWidget() {
- return (VOrderedLayout) super.getWidget();
+ public VAbstractOrderedLayout getWidget() {
+ return (VAbstractOrderedLayout) super.getWidget();
}
/**
@@ -300,7 +297,7 @@ public abstract class AbstractOrderedLayoutConnector extends
List<ComponentConnector> previousChildren = event.getOldChildren();
int currentIndex = 0;
- VOrderedLayout layout = getWidget();
+ VAbstractOrderedLayout layout = getWidget();
layout.setSpacing(getState().spacing);
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/CaptionPosition.java b/client/src/com/vaadin/client/ui/orderedlayout/CaptionPosition.java
new file mode 100644
index 0000000000..612d00b574
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/orderedlayout/CaptionPosition.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.client.ui.orderedlayout;
+
+/**
+ * Defines where the caption should be placed
+ */
+public enum CaptionPosition {
+ TOP, RIGHT, BOTTOM, LEFT
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java
new file mode 100644
index 0000000000..094a7f1f0a
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2012 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.client.ui.orderedlayout;
+
+import java.util.List;
+
+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.SimplePanel;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.LayoutManager;
+import com.vaadin.client.StyleConstants;
+import com.vaadin.client.ui.layout.ElementResizeListener;
+import com.vaadin.shared.ui.AlignmentInfo;
+
+/**
+ * Represents a slot which contains the actual widget in the layout.
+ */
+public final class Slot extends SimplePanel {
+ /**
+ * The icon for each widget. Located in the caption of the slot.
+ */
+ private static class Icon extends UIObject {
+
+ public static final String CLASSNAME = "v-icon";
+
+ private String myUrl;
+
+ /**
+ * Constructor
+ */
+ public Icon() {
+ setElement(DOM.createImg());
+ DOM.setElementProperty(getElement(), "alt", "");
+ setStyleName(CLASSNAME);
+ }
+
+ /**
+ * Set the URL where the icon is located
+ *
+ * @param url
+ * A fully qualified URL
+ */
+ 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;
+ }
+ }
+ }
+
+ private static final String ALIGN_CLASS_PREFIX = "v-align-";
+
+ private final VAbstractOrderedLayout layout;
+
+ public static final String SLOT_CLASSNAME = "v-slot";
+
+ private Element spacer;
+ private Element captionWrap;
+ private Element caption;
+ private Element captionText;
+ private Icon icon;
+ private Element errorIcon;
+ private Element requiredIcon;
+
+ private ElementResizeListener captionResizeListener;
+
+ private ElementResizeListener widgetResizeListener;
+
+ private ElementResizeListener spacingResizeListener;
+
+ // 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;
+
+ /**
+ * Constructor
+ *
+ * @param widget
+ * The widget to put in the slot
+ * @param layout
+ * TODO
+ *
+ * @param layoutManager
+ * The layout manager used by the layout
+ */
+ public Slot(VAbstractOrderedLayout layout, Widget widget) {
+ this.layout = layout;
+ setStyleName(SLOT_CLASSNAME);
+ setWidget(widget);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.SimplePanel#remove(com.google.gwt.user
+ * .client.ui.Widget)
+ */
+ @Override
+ public boolean remove(Widget w) {
+ detachListeners();
+ return super.remove(w);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.SimplePanel#setWidget(com.google.gwt
+ * .user.client.ui.Widget)
+ */
+ @Override
+ public void setWidget(Widget w) {
+ detachListeners();
+ super.setWidget(w);
+ attachListeners();
+ }
+
+ /**
+ * Attached resize listeners to the widget, caption and spacing elements
+ */
+ private void attachListeners() {
+ if (getWidget() != null && layout.getLayoutManager() != null) {
+ LayoutManager lm = layout.getLayoutManager();
+ if (getCaptionElement() != null && captionResizeListener != null) {
+ lm.addElementResizeListener(getCaptionElement(),
+ captionResizeListener);
+ }
+ if (widgetResizeListener != null) {
+ lm.addElementResizeListener(getWidget().getElement(),
+ widgetResizeListener);
+ }
+ if (getSpacingElement() != null && spacingResizeListener != null) {
+ lm.addElementResizeListener(getSpacingElement(),
+ spacingResizeListener);
+ }
+ }
+ }
+
+ /**
+ * Detaches resize listeners from the widget, caption and spacing elements
+ */
+ private void detachListeners() {
+ if (getWidget() != null && layout.getLayoutManager() != null) {
+ LayoutManager lm = layout.getLayoutManager();
+ if (getCaptionElement() != null && captionResizeListener != null) {
+ lm.removeElementResizeListener(getCaptionElement(),
+ captionResizeListener);
+ }
+ if (widgetResizeListener != null) {
+ lm.removeElementResizeListener(getWidget().getElement(),
+ widgetResizeListener);
+ }
+ if (getSpacingElement() != null && spacingResizeListener != null) {
+ lm.removeElementResizeListener(getSpacingElement(),
+ spacingResizeListener);
+ }
+ }
+ }
+
+ public ElementResizeListener getCaptionResizeListener() {
+ return captionResizeListener;
+ }
+
+ public void setCaptionResizeListener(
+ ElementResizeListener captionResizeListener) {
+ detachListeners();
+ this.captionResizeListener = captionResizeListener;
+ attachListeners();
+ }
+
+ public ElementResizeListener getWidgetResizeListener() {
+ return widgetResizeListener;
+ }
+
+ public void setWidgetResizeListener(
+ ElementResizeListener widgetResizeListener) {
+ detachListeners();
+ this.widgetResizeListener = widgetResizeListener;
+ attachListeners();
+ }
+
+ public ElementResizeListener getSpacingResizeListener() {
+ return spacingResizeListener;
+ }
+
+ public void setSpacingResizeListener(
+ ElementResizeListener spacingResizeListener) {
+ detachListeners();
+ this.spacingResizeListener = spacingResizeListener;
+ attachListeners();
+ }
+
+ /**
+ * Returns the alignment for the slot
+ *
+ */
+ public AlignmentInfo getAlignment() {
+ return alignment;
+ }
+
+ /**
+ * Sets the style names for the slot containing the widget
+ *
+ * @param stylenames
+ * The style names for the slot
+ */
+ protected void setStyleNames(String... stylenames) {
+ setStyleName(SLOT_CLASSNAME);
+ if (stylenames != null) {
+ for (String stylename : stylenames) {
+ addStyleDependentName(stylename);
+ }
+ }
+
+ // Ensure alignment style names are correct
+ setAlignment(alignment);
+ }
+
+ /**
+ * Sets how the widget is aligned inside the slot
+ *
+ * @param alignment
+ * The alignment inside the slot
+ */
+ public void setAlignment(AlignmentInfo alignment) {
+ this.alignment = alignment;
+
+ if (alignment != null && alignment.isHorizontalCenter()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "center");
+ removeStyleName(ALIGN_CLASS_PREFIX + "right");
+ } else if (alignment != null && 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 != null && alignment.isVerticalCenter()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "middle");
+ removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ } else if (alignment != null && alignment.isBottom()) {
+ addStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+ } else {
+ removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+ removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+ }
+ }
+
+ /**
+ * Set how the slot should be expanded relative to the other slots
+ *
+ * @param expandRatio
+ * The ratio of the space the slot should occupy
+ *
+ */
+ public void setExpandRatio(double expandRatio) {
+ this.expandRatio = expandRatio;
+ }
+
+ /**
+ * Get the expand ratio for the slot. The expand ratio describes how the
+ * slot should be resized compared to other slots in the layout
+ *
+ * @return
+ */
+ public double getExpandRatio() {
+ return expandRatio;
+ }
+
+ /**
+ * Set the spacing for the slot. The spacing determines if there should be
+ * empty space around the slot when the slot.
+ *
+ * @param spacing
+ * Should spacing be enabled
+ */
+ public void setSpacing(boolean spacing) {
+ if (spacing && spacer == null) {
+ spacer = DOM.createDiv();
+ spacer.addClassName("v-spacing");
+
+ /*
+ * This has to be done here for the initial render. In other cases
+ * where the spacer already exists onAttach will handle it.
+ */
+ getElement().getParentElement().insertBefore(spacer, getElement());
+ } else if (!spacing && spacer != null) {
+ spacer.removeFromParent();
+ spacer = null;
+ }
+ }
+
+ /**
+ * Get the element which is added to make the spacing
+ *
+ * @return
+ */
+ public Element getSpacingElement() {
+ return spacer;
+ }
+
+ /**
+ * Does the slot have spacing
+ */
+ public boolean hasSpacing() {
+ return getSpacingElement() != null;
+ }
+
+ /**
+ * Get the vertical amount in pixels of the spacing
+ */
+ protected int getVerticalSpacing() {
+ if (spacer == null) {
+ return 0;
+ } else if (layout.getLayoutManager() != null) {
+ return layout.getLayoutManager().getOuterHeight(spacer);
+ }
+ return spacer.getOffsetHeight();
+ }
+
+ /**
+ * Get the horizontal amount of pixels of the spacing
+ *
+ * @return
+ */
+ protected int getHorizontalSpacing() {
+ if (spacer == null) {
+ return 0;
+ } else if (layout.getLayoutManager() != null) {
+ return layout.getLayoutManager().getOuterWidth(spacer);
+ }
+ return spacer.getOffsetWidth();
+ }
+
+ /**
+ * Set the position of the caption relative to the slot
+ *
+ * @param captionPosition
+ * The position of the caption
+ */
+ 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());
+ }
+
+ /**
+ * Get the position of the caption relative to the slot
+ */
+ public CaptionPosition getCaptionPosition() {
+ return captionPosition;
+ }
+
+ /**
+ * Set the caption of the slot
+ *
+ * @param captionText
+ * The text of the caption
+ * @param iconUrl
+ * The icon URL
+ * @param styles
+ * The style names
+ * @param error
+ * The error message
+ * @param showError
+ * Should the error message be shown
+ * @param required
+ * Is the (field) required
+ * @param enabled
+ * Is the component enabled
+ */
+ 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(StyleConstants.UI_WIDGET);
+ 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("&nbsp;");
+ } 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();
+ caption.insertFirst(icon.getElement());
+ }
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Does the slot have a caption
+ */
+ public boolean hasCaption() {
+ return caption != null;
+ }
+
+ /**
+ * Get the slots caption element
+ */
+ public Element getCaptionElement() {
+ return caption;
+ }
+
+ private boolean relativeWidth = false;
+
+ /**
+ * Set if the slot has a relative width
+ *
+ * @param relativeWidth
+ * True if slot uses relative width, false if the slot has a
+ * static width
+ */
+ public void setRelativeWidth(boolean relativeWidth) {
+ this.relativeWidth = relativeWidth;
+ updateRelativeSize(relativeWidth, "width");
+ }
+
+ public boolean hasRelativeWidth() {
+ return relativeWidth;
+ }
+
+ private boolean relativeHeight = false;
+
+ /**
+ * Set if the slot has a relative height
+ *
+ * @param relativeHeight
+ * True if the slot uses a relative height, false if the slot has
+ * a static height
+ */
+ public void setRelativeHeight(boolean relativeHeight) {
+ this.relativeHeight = relativeHeight;
+ updateRelativeSize(relativeHeight, "height");
+ }
+
+ public boolean hasRelativeHeight() {
+ return relativeHeight;
+ }
+
+ /**
+ * Updates the captions size if the slot is relative
+ *
+ * @param isRelativeSize
+ * Is the slot relatively sized
+ * @param direction
+ * The direction of the caption
+ */
+ 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();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
+ * .user.client.Event)
+ */
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ if (DOM.eventGetType(event) == Event.ONLOAD
+ && icon.getElement() == DOM.eventGetTarget(event)) {
+ if (layout.getLayoutManager() != null) {
+ layout.getLayoutManager().layoutLater();
+ } else {
+ layout.updateCaptionOffset(caption);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.SimplePanel#getContainerElement()
+ */
+ @Override
+ protected Element getContainerElement() {
+ if (captionWrap == null) {
+ return getElement();
+ } else {
+ return captionWrap;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.Widget#onDetach()
+ */
+ @Override
+ protected void onDetach() {
+ if (spacer != null) {
+ spacer.removeFromParent();
+ }
+ super.onDetach();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.Widget#onAttach()
+ */
+ @Override
+ protected void onAttach() {
+ super.onAttach();
+ if (spacer != null) {
+ getElement().getParentElement().insertBefore(spacer, getElement());
+ }
+ }
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
new file mode 100644
index 0000000000..00b7092d81
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
@@ -0,0 +1,552 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.ui.orderedlayout;
+
+import java.util.HashMap;
+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.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.LayoutManager;
+import com.vaadin.client.Util;
+import com.vaadin.shared.ui.AlignmentInfo;
+import com.vaadin.shared.ui.MarginInfo;
+
+/**
+ * Base class for ordered layouts
+ */
+public class VAbstractOrderedLayout extends FlowPanel {
+
+ protected boolean spacing = false;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public boolean vertical = true;
+
+ protected boolean definedHeight = false;
+
+ private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>();
+
+ private Element expandWrapper;
+
+ private LayoutManager layoutManager;
+
+ public VAbstractOrderedLayout(boolean vertical) {
+ this.vertical = vertical;
+ }
+
+ /**
+ * Add or move a slot to another index.
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ * <p>
+ * You should note that the index does not refer to the DOM index if
+ * spacings are used. If spacings are used then the index will be adjusted
+ * to include the spacings when inserted.
+ * <p>
+ * For instance when using spacing the index converts to DOM index in the
+ * following way:
+ *
+ * <pre>
+ * index : 0 -> DOM index: 0
+ * index : 1 -> DOM index: 1
+ * index : 2 -> DOM index: 3
+ * index : 3 -> DOM index: 5
+ * index : 4 -> DOM index: 7
+ * </pre>
+ *
+ * When using this method never account for spacings.
+ * </p>
+ *
+ * @param slot
+ * The slot to move or add
+ * @param index
+ * The index where the slot should be placed.
+ */
+ public void addOrMoveSlot(Slot slot, int index) {
+ if (slot.getParent() == this) {
+ int currentIndex = getWidgetIndex(slot);
+ if (index == currentIndex) {
+ return;
+ }
+ }
+
+ insert(slot, index);
+
+ /*
+ * We need to confirm spacings are correctly applied after each insert.
+ */
+ setSpacing(spacing);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @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) {
+ if (spacing) {
+ if (beforeIndex != 0) {
+ /*
+ * Since the spacing elements are located at the same DOM
+ * level as the slots we need to take them into account when
+ * calculating the slot position.
+ *
+ * The spacing elements are always located before the actual
+ * slot except for the first slot which do not have a
+ * spacing element like this
+ *
+ * |<slot1><spacing2><slot2><spacing3><slot3>...|
+ */
+ beforeIndex = beforeIndex * 2 - 1;
+ }
+ }
+ DOM.insertChild(container, child.getElement(), beforeIndex);
+ } else {
+ DOM.appendChild(container, child.getElement());
+ }
+
+ // Adopt.
+ adopt(child);
+ }
+
+ /**
+ * Remove a slot from the layout
+ *
+ * @param widget
+ * @return
+ */
+ public void removeWidget(Widget widget) {
+ Slot slot = widgetToSlot.get(widget);
+ remove(slot);
+ widgetToSlot.remove(widget);
+ }
+
+ /**
+ * Get the containing slot for a widget. If no slot is found a new slot is
+ * created and returned.
+ *
+ * @param widget
+ * The widget whose slot you want to get
+ *
+ * @return
+ */
+ public Slot getSlot(Widget widget) {
+ Slot slot = widgetToSlot.get(widget);
+ if (slot == null) {
+ slot = new Slot(this, widget);
+ widgetToSlot.put(widget, slot);
+ }
+ return slot;
+ }
+
+ /**
+ * Gets a slot based on the widget element. If no slot is found then null is
+ * returned.
+ *
+ * @param widgetElement
+ * The element of the widget ( Same as getWidget().getElement() )
+ * @return
+ */
+ public Slot getSlot(Element widgetElement) {
+ for (Map.Entry<Widget, Slot> entry : widgetToSlot.entrySet()) {
+ if (entry.getKey().getElement() == widgetElement) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Set the layout manager for the layout
+ *
+ * @param manager
+ * The layout manager to use
+ */
+ public void setLayoutManager(LayoutManager manager) {
+ layoutManager = manager;
+ }
+
+ /**
+ * Get the layout manager used by this layout
+ *
+ */
+ public LayoutManager getLayoutManager() {
+ return layoutManager;
+ }
+
+ /**
+ * Deducts the caption position by examining the wrapping element.
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ *
+ * @param captionWrap
+ * The wrapping element
+ *
+ * @return The caption position
+ */
+ public CaptionPosition getCaptionPositionFromElement(Element captionWrap) {
+ RegExp captionPositionRegexp = RegExp.compile("v-caption-on-(\\S+)");
+
+ // 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;
+ }
+
+ /**
+ * Update the offset off the caption relative to the slot
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ *
+ * @param caption
+ * The caption element
+ */
+ public 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);
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the margin of the layout
+ *
+ * @param marginInfo
+ * The margin information
+ */
+ public void setMargin(MarginInfo marginInfo) {
+ if (marginInfo != null) {
+ setStyleName("v-margin-top", marginInfo.hasTop());
+ setStyleName("v-margin-right", marginInfo.hasRight());
+ setStyleName("v-margin-bottom", marginInfo.hasBottom());
+ setStyleName("v-margin-left", marginInfo.hasLeft());
+ }
+ }
+
+ /**
+ * Turn on or off spacing in the layout
+ *
+ * @param spacing
+ * True if spacing should be used, false if not
+ */
+ public void setSpacing(boolean spacing) {
+ this.spacing = spacing;
+ for (Slot slot : widgetToSlot.values()) {
+ if (getWidgetIndex(slot) > 0) {
+ slot.setSpacing(spacing);
+ } else {
+ slot.setSpacing(false);
+ }
+ }
+ }
+
+ /**
+ * Triggers a recalculation of the expand width and heights
+ */
+ 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.hasRelativeHeight()) {
+ Util.notifyParentOfSizeChange(this, true);
+ }
+ } else {
+ slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%");
+ if (slot.hasRelativeWidth()) {
+ Util.notifyParentOfSizeChange(this, true);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes elements used to expand a slot.
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public 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;
+ }
+ }
+
+ /**
+ * Adds elements used to expand a slot
+ */
+ 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 = vertical ? slot.getVerticalSpacing() : slot
+ .getHorizontalSpacing();
+ 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();
+ }
+ }
+
+ /**
+ * Perform a recalculation of the layout height
+ */
+ 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();
+ }
+ getElement().getStyle().setHeight(newHeight, Unit.PX);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setHeight(String height) {
+ super.setHeight(height);
+ definedHeight = (height != null && !"".equals(height));
+ }
+
+ /**
+ * Sets the slots style names. The style names will be prefixed with the
+ * v-slot prefix.
+ *
+ * @param stylenames
+ * The style names of the slot.
+ */
+ public void setSlotStyleNames(Widget widget, String... stylenames) {
+ Slot slot = getSlot(widget);
+ if (slot == null) {
+ throw new IllegalArgumentException(
+ "A slot for the widget could not be found. Has the widget been added to the layout?");
+ }
+ slot.setStyleNames(stylenames);
+ }
+
+}
diff --git a/server/src/com/vaadin/ui/AbstractColorPicker.java b/server/src/com/vaadin/ui/AbstractColorPicker.java
new file mode 100644
index 0000000000..38cbeddcb5
--- /dev/null
+++ b/server/src/com/vaadin/ui/AbstractColorPicker.java
@@ -0,0 +1,450 @@
+package com.vaadin.ui;
+
+import java.lang.reflect.Method;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc;
+import com.vaadin.shared.ui.colorpicker.ColorPickerState;
+import com.vaadin.ui.Window.CloseEvent;
+import com.vaadin.ui.Window.CloseListener;
+import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
+import com.vaadin.ui.components.colorpicker.ColorChangeListener;
+import com.vaadin.ui.components.colorpicker.ColorPickerPopup;
+import com.vaadin.ui.components.colorpicker.ColorSelector;
+
+/**
+ * An abstract class that defines default implementation for a color picker
+ * component.
+ *
+ * @since 7.0.0
+ */
+public abstract class AbstractColorPicker extends AbstractComponent implements
+ CloseListener, ColorSelector {
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ /**
+ * Interface for converting 2d-coordinates to a Color
+ */
+ public interface Coordinates2Color {
+
+ /**
+ * Calculate color from coordinates
+ *
+ * @param x
+ * the x-coordinate
+ * @param y
+ * the y-coordinate
+ *
+ * @return the color
+ */
+ public Color calculate(int x, int y);
+
+ /**
+ * Calculate coordinates from color
+ *
+ * @param c
+ * the c
+ *
+ * @return the integer array with the coordinates
+ */
+ public int[] calculate(Color c);
+ }
+
+ public enum PopupStyle {
+ POPUP_NORMAL("normal"), POPUP_SIMPLE("simple");
+
+ private String style;
+
+ PopupStyle(String styleName) {
+ style = styleName;
+ }
+
+ @Override
+ public String toString() {
+ return style;
+ }
+ }
+
+ private ColorPickerServerRpc rpc = new ColorPickerServerRpc() {
+
+ @Override
+ public void openPopup(boolean open) {
+ showPopup(open);
+ }
+ };
+
+ protected static final String STYLENAME_DEFAULT = "v-colorpicker";
+ protected static final String STYLENAME_BUTTON = "v-button";
+ protected static final String STYLENAME_AREA = "v-colorpicker-area";
+
+ protected PopupStyle popupStyle = PopupStyle.POPUP_NORMAL;
+
+ /** The popup window. */
+ private ColorPickerPopup window;
+
+ /** The color. */
+ protected Color color;
+
+ /** The UI. */
+ private UI parent;
+
+ protected String popupCaption = null;
+ private int positionX = 0;
+ private int positionY = 0;
+
+ protected boolean rgbVisible = true;
+ protected boolean hsvVisible = true;
+ protected boolean swatchesVisible = true;
+ protected boolean historyVisible = true;
+ protected boolean textfieldVisible = true;
+
+ /**
+ * Instantiates a new color picker.
+ */
+ public AbstractColorPicker() {
+ this("Colors", Color.WHITE);
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * the caption of the popup window
+ */
+ public AbstractColorPicker(String popupCaption) {
+ this(popupCaption, Color.WHITE);
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * the caption of the popup window
+ * @param initialColor
+ * the initial color
+ */
+ public AbstractColorPicker(String popupCaption, Color initialColor) {
+ super();
+ registerRpc(rpc);
+ setColor(initialColor);
+ this.popupCaption = popupCaption;
+ setDefaultStyles();
+ setCaption("");
+ }
+
+ @Override
+ public void setColor(Color color) {
+ this.color = color;
+
+ if (window != null) {
+ window.setColor(color);
+ }
+ getState().color = color.getCSS();
+ }
+
+ @Override
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Set true if the component should show a default caption (css-code for the
+ * currently selected color, e.g. #ffffff) when no other caption is
+ * available.
+ *
+ * @param enabled
+ */
+ public void setDefaultCaptionEnabled(boolean enabled) {
+ getState().showDefaultCaption = enabled;
+ }
+
+ /**
+ * Returns true if the component shows the default caption (css-code for the
+ * currently selected color, e.g. #ffffff) if no other caption is available.
+ */
+ public boolean isDefaultCaptionEnabled() {
+ return getState().showDefaultCaption;
+ }
+
+ /**
+ * Sets the position of the popup window
+ *
+ * @param x
+ * the x-coordinate
+ * @param y
+ * the y-coordinate
+ */
+ public void setPosition(int x, int y) {
+ positionX = x;
+ positionY = y;
+
+ if (window != null) {
+ window.setPositionX(x);
+ window.setPositionY(y);
+ }
+ }
+
+ @Override
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ @Override
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ @Override
+ public void windowClose(CloseEvent e) {
+ if (e.getWindow() == window) {
+ getState().popupVisible = false;
+ }
+ }
+
+ /**
+ * Fired when a color change event occurs
+ *
+ * @param event
+ * The color change event
+ */
+ protected void colorChanged(ColorChangeEvent event) {
+ setColor(event.getColor());
+ fireColorChanged();
+ }
+
+ /**
+ * Notifies the listeners that the selected color has changed
+ */
+ public void fireColorChanged() {
+ fireEvent(new ColorChangeEvent(this, color));
+ }
+
+ /**
+ * The style for the popup window
+ *
+ * @param style
+ * The style
+ */
+ public void setPopupStyle(PopupStyle style) {
+ popupStyle = style;
+
+ switch (style) {
+ case POPUP_NORMAL: {
+ setRGBVisibility(true);
+ setHSVVisibility(true);
+ setSwatchesVisibility(true);
+ setHistoryVisibility(true);
+ setTextfieldVisibility(true);
+ break;
+ }
+
+ case POPUP_SIMPLE: {
+ setRGBVisibility(false);
+ setHSVVisibility(false);
+ setSwatchesVisibility(true);
+ setHistoryVisibility(false);
+ setTextfieldVisibility(false);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Set the visibility of the RGB Tab
+ *
+ * @param visible
+ * The visibility
+ */
+ public void setRGBVisibility(boolean visible) {
+
+ if (!visible && !hsvVisible && !swatchesVisible) {
+ throw new IllegalArgumentException("Cannot hide all tabs.");
+ }
+
+ rgbVisible = visible;
+ if (window != null) {
+ window.setRGBTabVisible(visible);
+ }
+ }
+
+ /**
+ * Set the visibility of the HSV Tab
+ *
+ * @param visible
+ * The visibility
+ */
+ public void setHSVVisibility(boolean visible) {
+ if (!visible && !rgbVisible && !swatchesVisible) {
+ throw new IllegalArgumentException("Cannot hide all tabs.");
+ }
+
+ hsvVisible = visible;
+ if (window != null) {
+ window.setHSVTabVisible(visible);
+ }
+ }
+
+ /**
+ * Set the visibility of the Swatches Tab
+ *
+ * @param visible
+ * The visibility
+ */
+ public void setSwatchesVisibility(boolean visible) {
+ if (!visible && !hsvVisible && !rgbVisible) {
+ throw new IllegalArgumentException("Cannot hide all tabs.");
+ }
+
+ swatchesVisible = visible;
+ if (window != null) {
+ window.setSwatchesTabVisible(visible);
+ }
+ }
+
+ /**
+ * Sets the visibility of the Color History
+ *
+ * @param visible
+ * The visibility
+ */
+ public void setHistoryVisibility(boolean visible) {
+ historyVisible = visible;
+ if (window != null) {
+ window.setHistoryVisible(visible);
+ }
+ }
+
+ /**
+ * Sets the visibility of the CSS color code text field
+ *
+ * @param visible
+ * The visibility
+ */
+ public void setTextfieldVisibility(boolean visible) {
+ textfieldVisible = visible;
+ if (window != null) {
+ window.setPreviewVisible(visible);
+ }
+ }
+
+ @Override
+ protected ColorPickerState getState() {
+ return (ColorPickerState) super.getState();
+ }
+
+ /**
+ * Sets the default styles of the component
+ *
+ */
+ abstract protected void setDefaultStyles();
+
+ /**
+ * Shows a popup-window for color selection.
+ */
+ public void showPopup() {
+ showPopup(true);
+ }
+
+ /**
+ * Hides a popup-window for color selection.
+ */
+ public void hidePopup() {
+ showPopup(false);
+ }
+
+ /**
+ * Shows or hides popup-window depending on the given parameter. If there is
+ * no such window yet, one is created.
+ *
+ * @param open
+ */
+ protected void showPopup(boolean open) {
+ if (open && !isReadOnly()) {
+ if (parent == null) {
+ parent = getUI();
+ }
+
+ if (window == null) {
+
+ // Create the popup
+ window = new ColorPickerPopup(color);
+ window.setCaption(popupCaption);
+
+ window.setRGBTabVisible(rgbVisible);
+ window.setHSVTabVisible(hsvVisible);
+ window.setSwatchesTabVisible(swatchesVisible);
+ window.setHistoryVisible(historyVisible);
+ window.setPreviewVisible(textfieldVisible);
+
+ window.setImmediate(true);
+ window.addCloseListener(this);
+ window.addColorChangeListener(new ColorChangeListener() {
+ public void colorChanged(ColorChangeEvent event) {
+ AbstractColorPicker.this.colorChanged(event);
+ }
+ });
+
+ window.getHistory().setColor(color);
+ parent.addWindow(window);
+ window.setVisible(true);
+ window.setPositionX(positionX);
+ window.setPositionY(positionY);
+
+ } else if (!parent.equals(window.getParent())) {
+
+ window.setRGBTabVisible(rgbVisible);
+ window.setHSVTabVisible(hsvVisible);
+ window.setSwatchesTabVisible(swatchesVisible);
+ window.setHistoryVisible(historyVisible);
+ window.setPreviewVisible(textfieldVisible);
+
+ window.setColor(color);
+ window.getHistory().setColor(color);
+ window.setVisible(true);
+ parent.addWindow(window);
+ }
+
+ } else if (window != null) {
+ window.setVisible(false);
+ parent.removeWindow(window);
+ }
+ getState().popupVisible = open;
+ }
+
+ /**
+ * Set whether the caption text is rendered as HTML or not. You might need
+ * to re-theme component to allow higher content than the original text
+ * style.
+ *
+ * If set to true, the captions are passed to the browser as html and the
+ * developer is responsible for ensuring no harmful html is used. If set to
+ * false, the content is passed to the browser as plain text.
+ *
+ * @param htmlContentAllowed
+ * <code>true</code> if caption is rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+ getState().htmlContentAllowed = htmlContentAllowed;
+ }
+
+ /**
+ * Return HTML rendering setting
+ *
+ * @return <code>true</code> if the caption text is to be rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public boolean isHtmlContentAllowed() {
+ return getState().htmlContentAllowed;
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/ColorPicker.java b/server/src/com/vaadin/ui/ColorPicker.java
new file mode 100644
index 0000000000..1e729badcc
--- /dev/null
+++ b/server/src/com/vaadin/ui/ColorPicker.java
@@ -0,0 +1,64 @@
+package com.vaadin.ui;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+
+/**
+ * A class that defines default (button-like) implementation for a color picker
+ * component.
+ *
+ * @since 7.0.0
+ *
+ * @see ColorPickerArea
+ *
+ */
+public class ColorPicker extends AbstractColorPicker {
+
+ /**
+ * Instantiates a new color picker.
+ */
+ public ColorPicker() {
+ super();
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * caption of the color select popup
+ */
+ public ColorPicker(String popupCaption) {
+ super(popupCaption);
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * caption of the color select popup
+ * @param initialColor
+ * the initial color
+ */
+ public ColorPicker(String popupCaption, Color initialColor) {
+ super(popupCaption, initialColor);
+ setDefaultCaptionEnabled(true);
+ }
+
+ @Override
+ protected void setDefaultStyles() {
+ setPrimaryStyleName(STYLENAME_BUTTON);
+ addStyleName(STYLENAME_DEFAULT);
+ }
+
+ @Override
+ public void beforeClientResponse(boolean initial) {
+ super.beforeClientResponse(initial);
+
+ if (isDefaultCaptionEnabled()
+ && ((getState().caption == null || ""
+ .equals(getState().caption)))
+ && "".equals(getState().width)) {
+ getState().width = "100px";
+ }
+ }
+
+}
diff --git a/server/src/com/vaadin/ui/ColorPickerArea.java b/server/src/com/vaadin/ui/ColorPickerArea.java
new file mode 100644
index 0000000000..31deed4449
--- /dev/null
+++ b/server/src/com/vaadin/ui/ColorPickerArea.java
@@ -0,0 +1,62 @@
+package com.vaadin.ui;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+
+/**
+ * A class that defines area-like implementation for a color picker component.
+ *
+ * @since 7.0.0
+ *
+ * @see ColorPicker
+ *
+ */
+public class ColorPickerArea extends AbstractColorPicker {
+
+ /**
+ * Instantiates a new color picker.
+ */
+ public ColorPickerArea() {
+ super();
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * caption of the color select popup
+ */
+ public ColorPickerArea(String popupCaption) {
+ super(popupCaption);
+ }
+
+ /**
+ * Instantiates a new color picker.
+ *
+ * @param popupCaption
+ * caption of the color select popup
+ * @param initialColor
+ * the initial color
+ */
+ public ColorPickerArea(String popupCaption, Color initialColor) {
+ super(popupCaption, initialColor);
+ setDefaultCaptionEnabled(false);
+ }
+
+ @Override
+ protected void setDefaultStyles() {
+ // state already has correct default
+ }
+
+ @Override
+ public void beforeClientResponse(boolean initial) {
+ super.beforeClientResponse(initial);
+
+ if ("".equals(getState().height)) {
+ getState().height = "30px";
+ }
+ if ("".equals(getState().width)) {
+ getState().width = "30px";
+ }
+ }
+
+}
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorChangeEvent.java b/server/src/com/vaadin/ui/components/colorpicker/ColorChangeEvent.java
new file mode 100644
index 0000000000..8ad935f9d3
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorChangeEvent.java
@@ -0,0 +1,28 @@
+package com.vaadin.ui.components.colorpicker;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Component.Event;
+
+/**
+ * The color changed event which is passed to the listeners when a color change
+ * occurs.
+ *
+ * @since 7.0.0
+ */
+public class ColorChangeEvent extends Event {
+ private final Color color;
+
+ public ColorChangeEvent(Component source, Color color) {
+ super(source);
+
+ this.color = color;
+ }
+
+ /**
+ * Returns the new color.
+ */
+ public Color getColor() {
+ return color;
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorChangeListener.java b/server/src/com/vaadin/ui/components/colorpicker/ColorChangeListener.java
new file mode 100644
index 0000000000..9f8ea0ff26
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorChangeListener.java
@@ -0,0 +1,27 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.io.Serializable;
+
+/**
+ * The listener interface for receiving colorChange events. The class that is
+ * interested in processing a {@link ColorChangeEvent} implements this
+ * interface, and the object created with that class is registered with a
+ * component using the component's <code>addColorChangeListener</code> method.
+ * When the colorChange event occurs, that object's appropriate method is
+ * invoked.
+ *
+ * @since 7.0.0
+ *
+ * @see ColorChangeEvent
+ */
+public interface ColorChangeListener extends Serializable {
+
+ /**
+ * Called when a new color has been selected.
+ *
+ * @param event
+ * An event containing information about the color change.
+ */
+ void colorChanged(ColorChangeEvent event);
+
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java
new file mode 100644
index 0000000000..ddd61f37b2
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java
@@ -0,0 +1,129 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.lang.reflect.Method;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGradientServerRpc;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGradientState;
+import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
+import com.vaadin.ui.AbstractComponent;
+
+/**
+ * A component that represents a color gradient within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerGradient extends AbstractComponent implements
+ ColorSelector {
+
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ private ColorPickerGradientServerRpc rpc = new ColorPickerGradientServerRpc() {
+
+ @Override
+ public void select(int cursorX, int cursorY) {
+ x = cursorX;
+ y = cursorY;
+ color = converter.calculate(x, y);
+
+ fireColorChanged(color);
+ }
+ };
+
+ /** The converter. */
+ private final Coordinates2Color converter;
+
+ /** The foreground color. */
+ private Color color;
+
+ /** The x-coordinate. */
+ private int x = 0;
+
+ /** The y-coordinate. */
+ private int y = 0;
+
+ /** The background color. */
+ private Color backgroundColor;
+
+ /**
+ * Instantiates a new color picker gradient.
+ *
+ * @param id
+ * the id
+ * @param converter
+ * the converter
+ */
+ public ColorPickerGradient(String id, Coordinates2Color converter) {
+ registerRpc(rpc);
+ getState().id = id;
+ // width and height must be set here instead of in theme, otherwise
+ // coordinate calculations fail
+ getState().width = "220px";
+ getState().height = "220px";
+ this.converter = converter;
+ }
+
+ @Override
+ public void setColor(Color c) {
+ color = c;
+
+ int[] coords = converter.calculate(c);
+ x = coords[0];
+ y = coords[1];
+
+ getState().cursorX = x;
+ getState().cursorY = y;
+
+ }
+
+ @Override
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ @Override
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ /**
+ * Sets the background color.
+ *
+ * @param color
+ * the new background color
+ */
+ public void setBackgroundColor(Color color) {
+ backgroundColor = color;
+ getState().bgColor = color.getCSS();
+ }
+
+ @Override
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Notifies the listeners that the color has changed
+ *
+ * @param color
+ * The color which it changed to
+ */
+ public void fireColorChanged(Color color) {
+ fireEvent(new ColorChangeEvent(this, color));
+ }
+
+ @Override
+ protected ColorPickerGradientState getState() {
+ return (ColorPickerGradientState) super.getState();
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGrid.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGrid.java
new file mode 100644
index 0000000000..37e70c328f
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGrid.java
@@ -0,0 +1,240 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.awt.Point;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGridServerRpc;
+import com.vaadin.shared.ui.colorpicker.ColorPickerGridState;
+import com.vaadin.ui.AbstractComponent;
+
+/**
+ * A component that represents a color selection grid within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerGrid extends AbstractComponent implements ColorSelector {
+
+ private static final String STYLENAME = "v-colorpicker-grid";
+
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ private ColorPickerGridServerRpc rpc = new ColorPickerGridServerRpc() {
+
+ @Override
+ public void select(int x, int y) {
+ ColorPickerGrid.this.x = x;
+ ColorPickerGrid.this.y = y;
+
+ fireColorChanged(colorGrid[y][x]);
+ }
+
+ @Override
+ public void refresh() {
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < columns; col++) {
+ changedColors.put(new Point(row, col), colorGrid[row][col]);
+ }
+ }
+ sendChangedColors();
+ markAsDirty();
+ }
+ };
+
+ /** The x-coordinate. */
+ private int x = 0;
+
+ /** The y-coordinate. */
+ private int y = 0;
+
+ /** The rows. */
+ private int rows;
+
+ /** The columns. */
+ private int columns;
+
+ /** The color grid. */
+ private Color[][] colorGrid = new Color[1][1];
+
+ /** The changed colors. */
+ private final Map<Point, Color> changedColors = new HashMap<Point, Color>();
+
+ /**
+ * Instantiates a new color picker grid.
+ */
+ public ColorPickerGrid() {
+ registerRpc(rpc);
+ setPrimaryStyleName(STYLENAME);
+ setColorGrid(new Color[1][1]);
+ setColor(Color.WHITE);
+ }
+
+ /**
+ * Instantiates a new color picker grid.
+ *
+ * @param rows
+ * the rows
+ * @param columns
+ * the columns
+ */
+ public ColorPickerGrid(int rows, int columns) {
+ registerRpc(rpc);
+ setPrimaryStyleName(STYLENAME);
+ setColorGrid(new Color[rows][columns]);
+ setColor(Color.WHITE);
+ }
+
+ /**
+ * Instantiates a new color picker grid.
+ *
+ * @param colors
+ * the colors
+ */
+ public ColorPickerGrid(Color[][] colors) {
+ registerRpc(rpc);
+ setPrimaryStyleName(STYLENAME);
+ setColorGrid(colors);
+ }
+
+ private void setColumnCount(int columns) {
+ this.columns = columns;
+ getState().columnCount = columns;
+ }
+
+ private void setRowCount(int rows) {
+ this.rows = rows;
+ getState().rowCount = rows;
+ }
+
+ private void sendChangedColors() {
+ if (!changedColors.isEmpty()) {
+ String[] colors = new String[changedColors.size()];
+ String[] XCoords = new String[changedColors.size()];
+ String[] YCoords = new String[changedColors.size()];
+ int counter = 0;
+ for (Point p : changedColors.keySet()) {
+ Color c = changedColors.get(p);
+ if (c == null) {
+ continue;
+ }
+
+ String color = c.getCSS();
+
+ colors[counter] = color;
+ XCoords[counter] = String.valueOf((int) p.getX());
+ YCoords[counter] = String.valueOf((int) p.getY());
+ counter++;
+ }
+ getState().changedColor = colors;
+ getState().changedX = XCoords;
+ getState().changedY = YCoords;
+
+ changedColors.clear();
+ }
+ }
+
+ /**
+ * Sets the color grid.
+ *
+ * @param colors
+ * the new color grid
+ */
+ public void setColorGrid(Color[][] colors) {
+ setRowCount(colors.length);
+ setColumnCount(colors[0].length);
+ colorGrid = colors;
+
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < columns; col++) {
+ changedColors.put(new Point(row, col), colorGrid[row][col]);
+ }
+ }
+ sendChangedColors();
+
+ markAsDirty();
+ }
+
+ /**
+ * Adds a color change listener
+ *
+ * @param listener
+ * The color change listener
+ */
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ @Override
+ public Color getColor() {
+ return colorGrid[x][y];
+ }
+
+ /**
+ * Removes a color change listener
+ *
+ * @param listener
+ * The listener
+ */
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ @Override
+ public void setColor(Color color) {
+ colorGrid[x][y] = color;
+ changedColors.put(new Point(x, y), color);
+ sendChangedColors();
+ markAsDirty();
+ }
+
+ /**
+ * Sets the position.
+ *
+ * @param x
+ * the x
+ * @param y
+ * the y
+ */
+ public void setPosition(int x, int y) {
+ if (x >= 0 && x < columns && y >= 0 && y < rows) {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
+ /**
+ * Gets the position.
+ *
+ * @return the position
+ */
+ public int[] getPosition() {
+ return new int[] { x, y };
+ }
+
+ /**
+ * Notifies the listeners that a color change has occurred
+ *
+ * @param color
+ * The color which it changed to
+ */
+ public void fireColorChanged(Color color) {
+ fireEvent(new ColorChangeEvent(this, color));
+ }
+
+ @Override
+ protected ColorPickerGridState getState() {
+ return (ColorPickerGridState) super.getState();
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java
new file mode 100644
index 0000000000..81d521237e
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java
@@ -0,0 +1,200 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.CustomComponent;
+
+/**
+ * A component that represents color selection history within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerHistory extends CustomComponent implements
+ ColorSelector, ColorChangeListener {
+
+ private static final String STYLENAME = "v-colorpicker-history";
+
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ /** The rows. */
+ private static final int rows = 4;
+
+ /** The columns. */
+ private static final int columns = 15;
+
+ /** Temporary color history for when the component is detached. */
+ private ArrayBlockingQueue<Color> tempHistory = new ArrayBlockingQueue<Color>(
+ rows * columns);
+
+ /** The grid. */
+ private final ColorPickerGrid grid;
+
+ /**
+ * Instantiates a new color picker history.
+ */
+ public ColorPickerHistory() {
+ setPrimaryStyleName(STYLENAME);
+
+ grid = new ColorPickerGrid(rows, columns);
+ grid.setWidth("100%");
+ grid.setPosition(0, 0);
+ grid.addColorChangeListener(this);
+
+ setCompositionRoot(grid);
+ }
+
+ @Override
+ public void attach() {
+ super.attach();
+ createColorHistoryIfNecessary();
+ }
+
+ private void createColorHistoryIfNecessary() {
+ List<Color> tempColors = new ArrayList<Color>(tempHistory);
+ if (getSession().getAttribute("colorPickerHistory") == null) {
+ getSession().setAttribute("colorPickerHistory",
+ new ArrayBlockingQueue<Color>(rows * columns));
+ }
+ for (Color color : tempColors) {
+ setColor(color);
+ }
+ tempHistory.clear();
+ }
+
+ @SuppressWarnings("unchecked")
+ private ArrayBlockingQueue<Color> getColorHistory() {
+ if (getSession() != null) {
+ Object colorHistory = getSession().getAttribute(
+ "colorPickerHistory");
+ if (colorHistory instanceof ArrayBlockingQueue<?>) {
+ return (ArrayBlockingQueue<Color>) colorHistory;
+ }
+ }
+ return tempHistory;
+ }
+
+ @Override
+ public void setHeight(String height) {
+ super.setHeight(height);
+ grid.setHeight(height);
+ }
+
+ @Override
+ public void setColor(Color color) {
+
+ ArrayBlockingQueue<Color> colorHistory = getColorHistory();
+
+ // Check that the color does not already exist
+ boolean exists = false;
+ Iterator<Color> iter = colorHistory.iterator();
+ while (iter.hasNext()) {
+ if (color.equals(iter.next())) {
+ exists = true;
+ break;
+ }
+ }
+
+ // If the color does not exist then add it
+ if (!exists) {
+ if (!colorHistory.offer(color)) {
+ colorHistory.poll();
+ colorHistory.offer(color);
+ }
+ }
+
+ List<Color> colorList = new ArrayList<Color>(colorHistory);
+
+ // Invert order of colors
+ Collections.reverse(colorList);
+
+ // Move the selected color to the front of the list
+ Collections.swap(colorList, colorList.indexOf(color), 0);
+
+ // Create 2d color map
+ Color[][] colors = new Color[rows][columns];
+ iter = colorList.iterator();
+
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < columns; col++) {
+ if (iter.hasNext()) {
+ colors[row][col] = iter.next();
+ } else {
+ colors[row][col] = Color.WHITE;
+ }
+ }
+ }
+
+ grid.setColorGrid(colors);
+ grid.markAsDirty();
+ }
+
+ @Override
+ public Color getColor() {
+ return getColorHistory().peek();
+ }
+
+ /**
+ * Gets the history.
+ *
+ * @return the history
+ */
+ public List<Color> getHistory() {
+ ArrayBlockingQueue<Color> colorHistory = getColorHistory();
+ Color[] array = colorHistory.toArray(new Color[colorHistory.size()]);
+ return Collections.unmodifiableList(Arrays.asList(array));
+ }
+
+ /**
+ * Checks if the history contains given color.
+ *
+ * @param c
+ * the color
+ *
+ * @return true, if successful
+ */
+ public boolean hasColor(Color c) {
+ return getColorHistory().contains(c);
+ }
+
+ /**
+ * Adds a color change listener
+ *
+ * @param listener
+ * The listener
+ */
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ /**
+ * Removes a color change listener
+ *
+ * @param listener
+ * The listener
+ */
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ @Override
+ public void colorChanged(ColorChangeEvent event) {
+ fireEvent(new ColorChangeEvent(this, event.getColor()));
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java
new file mode 100644
index 0000000000..ddfbf7381e
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java
@@ -0,0 +1,766 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.shared.ui.MarginInfo;
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.Slider;
+import com.vaadin.ui.Slider.ValueOutOfBoundsException;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+/**
+ * A component that represents color selection popup within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerPopup extends Window implements ClickListener,
+ ColorChangeListener, ColorSelector {
+
+ private static final String STYLENAME = "v-colorpicker-popup";
+
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ /** The tabs. */
+ private final TabSheet tabs = new TabSheet();
+
+ private Component rgbTab;
+
+ private Component hsvTab;
+
+ private Component swatchesTab;
+
+ /** The layout. */
+ private final VerticalLayout layout;
+
+ /** The ok button. */
+ private final Button ok = new Button("OK");
+
+ /** The cancel button. */
+ private final Button cancel = new Button("Cancel");
+
+ /** The resize button. */
+ private final Button resize = new Button("show/hide history");
+
+ /** The selected color. */
+ private Color selectedColor = Color.WHITE;
+
+ /** The history. */
+ private ColorPickerHistory history;
+
+ /** The history container. */
+ private Layout historyContainer;
+
+ /** The rgb gradient. */
+ private ColorPickerGradient rgbGradient;
+
+ /** The hsv gradient. */
+ private ColorPickerGradient hsvGradient;
+
+ /** The red slider. */
+ private Slider redSlider;
+
+ /** The green slider. */
+ private Slider greenSlider;
+
+ /** The blue slider. */
+ private Slider blueSlider;
+
+ /** The hue slider. */
+ private Slider hueSlider;
+
+ /** The saturation slider. */
+ private Slider saturationSlider;
+
+ /** The value slider. */
+ private Slider valueSlider;
+
+ /** The preview on the rgb tab. */
+ private ColorPickerPreview rgbPreview;
+
+ /** The preview on the hsv tab. */
+ private ColorPickerPreview hsvPreview;
+
+ /** The preview on the swatches tab. */
+ private ColorPickerPreview selPreview;
+
+ /** The color select. */
+ private ColorPickerSelect colorSelect;
+
+ /** The selectors. */
+ private final Set<ColorSelector> selectors = new HashSet<ColorSelector>();
+
+ /**
+ * Set true while the slider values are updated after colorChange. When
+ * true, valueChange reactions from the sliders are disabled, because
+ * otherwise the set color may become corrupted as it is repeatedly re-set
+ * in valueChangeListeners using values from sliders that may not have been
+ * updated yet.
+ */
+ private boolean updatingColors = false;
+
+ /**
+ * Instantiates a new color picker popup.
+ */
+ public ColorPickerPopup(Color initialColor) {
+ super();
+
+ selectedColor = initialColor;
+
+ // Set the layout
+ layout = new VerticalLayout();
+ layout.setSpacing(false);
+ layout.setMargin(false);
+ layout.setWidth("100%");
+ layout.setHeight(null);
+
+ setContent(layout);
+ setStyleName(STYLENAME);
+ setResizable(false);
+ setImmediate(true);
+
+ initContents();
+ }
+
+ private void initContents() {
+ // Create the history
+ history = new ColorPickerHistory();
+ history.addColorChangeListener(this);
+
+ // Create the preview on the rgb tab
+ rgbPreview = new ColorPickerPreview(selectedColor);
+ rgbPreview.setWidth("240px");
+ rgbPreview.setHeight("20px");
+ rgbPreview.addColorChangeListener(this);
+ selectors.add(rgbPreview);
+
+ // Create the preview on the hsv tab
+ hsvPreview = new ColorPickerPreview(selectedColor);
+ hsvPreview.setWidth("240px");
+ hsvPreview.setHeight("20px");
+ hsvPreview.addColorChangeListener(this);
+ selectors.add(hsvPreview);
+
+ // Create the preview on the swatches tab
+ selPreview = new ColorPickerPreview(selectedColor);
+ selPreview.setWidth("100%");
+ selPreview.setHeight("20px");
+ selPreview.addColorChangeListener(this);
+ selectors.add(selPreview);
+
+ // Create the tabs
+ rgbTab = createRGBTab(selectedColor);
+ tabs.addTab(rgbTab, "RGB", null);
+
+ hsvTab = createHSVTab(selectedColor);
+ tabs.addTab(hsvTab, "HSV", null);
+
+ swatchesTab = createSelectTab();
+ tabs.addTab(swatchesTab, "Swatches", null);
+
+ // Add the tabs
+ tabs.setWidth("100%");
+
+ layout.addComponent(tabs);
+
+ // Add the history
+ history.setWidth("97%");
+ history.setHeight("22px");
+
+ // Create the default colors
+ List<Color> defaultColors = new ArrayList<Color>();
+ defaultColors.add(Color.BLACK);
+ defaultColors.add(Color.WHITE);
+
+ // Create the history
+ VerticalLayout innerContainer = new VerticalLayout();
+ innerContainer.setWidth("100%");
+ innerContainer.setHeight(null);
+ innerContainer.addComponent(history);
+
+ VerticalLayout outerContainer = new VerticalLayout();
+ outerContainer.setWidth("99%");
+ outerContainer.setHeight("27px");
+ outerContainer.addComponent(innerContainer);
+ historyContainer = outerContainer;
+
+ layout.addComponent(historyContainer);
+
+ // Add the resize button for the history
+ resize.addClickListener(this);
+ resize.setData(new Boolean(false));
+ resize.setWidth("100%");
+ resize.setHeight("10px");
+ resize.setPrimaryStyleName("resize-button");
+ layout.addComponent(resize);
+
+ // Add the buttons
+ ok.setWidth("70px");
+ ok.addClickListener(this);
+
+ cancel.setWidth("70px");
+ cancel.addClickListener(this);
+
+ HorizontalLayout buttons = new HorizontalLayout();
+ buttons.addComponent(ok);
+ buttons.addComponent(cancel);
+ buttons.setWidth("100%");
+ buttons.setHeight("30px");
+ buttons.setComponentAlignment(ok, Alignment.MIDDLE_CENTER);
+ buttons.setComponentAlignment(cancel, Alignment.MIDDLE_CENTER);
+ layout.addComponent(buttons);
+ }
+
+ /**
+ * Creates the RGB tab.
+ *
+ * @return the component
+ */
+ private Component createRGBTab(Color color) {
+ VerticalLayout rgbLayout = new VerticalLayout();
+ rgbLayout.setMargin(new MarginInfo(false, false, true, false));
+ rgbLayout.addComponent(rgbPreview);
+ rgbLayout.setStyleName("rgbtab");
+
+ // Add the RGB color gradient
+ rgbGradient = new ColorPickerGradient("rgb-gradient", RGBConverter);
+ rgbGradient.setColor(color);
+ rgbGradient.addColorChangeListener(this);
+ rgbLayout.addComponent(rgbGradient);
+ selectors.add(rgbGradient);
+
+ // Add the RGB sliders
+ VerticalLayout sliders = new VerticalLayout();
+ sliders.setStyleName("rgb-sliders");
+
+ redSlider = createRGBSlider("Red", "red");
+
+ try {
+ redSlider.setValue(((Integer) color.getRed()).doubleValue());
+ } catch (ValueOutOfBoundsException e) {
+ }
+
+ redSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ double red = (Double) event.getProperty().getValue();
+ if (!updatingColors) {
+ Color newColor = new Color((int) red, selectedColor
+ .getGreen(), selectedColor.getBlue());
+ setColor(newColor);
+ }
+ }
+ });
+
+ sliders.addComponent(redSlider);
+
+ greenSlider = createRGBSlider("Green", "green");
+
+ try {
+ greenSlider.setValue(((Integer) color.getGreen()).doubleValue());
+ } catch (ValueOutOfBoundsException e) {
+ }
+
+ greenSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ double green = (Double) event.getProperty().getValue();
+ if (!updatingColors) {
+ Color newColor = new Color(selectedColor.getRed(),
+ (int) green, selectedColor.getBlue());
+ setColor(newColor);
+ }
+ }
+ });
+ sliders.addComponent(greenSlider);
+
+ blueSlider = createRGBSlider("Blue", "blue");
+
+ try {
+ blueSlider.setValue(((Integer) color.getBlue()).doubleValue());
+ } catch (ValueOutOfBoundsException e) {
+ }
+
+ blueSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ double blue = (Double) event.getProperty().getValue();
+ if (!updatingColors) {
+ Color newColor = new Color(selectedColor.getRed(),
+ selectedColor.getGreen(), (int) blue);
+ setColor(newColor);
+ }
+ }
+ });
+ sliders.addComponent(blueSlider);
+
+ rgbLayout.addComponent(sliders);
+
+ return rgbLayout;
+ }
+
+ private Slider createRGBSlider(String caption, String styleName) {
+ Slider redSlider = new Slider(caption, 0, 255);
+ redSlider.setImmediate(true);
+ redSlider.setStyleName("rgb-slider");
+ redSlider.setWidth("220px");
+ redSlider.addStyleName(styleName);
+ return redSlider;
+ }
+
+ /**
+ * Creates the hsv tab.
+ *
+ * @return the component
+ */
+ private Component createHSVTab(Color color) {
+ VerticalLayout hsvLayout = new VerticalLayout();
+ hsvLayout.setMargin(new MarginInfo(false, false, true, false));
+ hsvLayout.addComponent(hsvPreview);
+ hsvLayout.setStyleName("hsvtab");
+
+ // Add the hsv gradient
+ hsvGradient = new ColorPickerGradient("hsv-gradient", HSVConverter);
+ hsvGradient.setColor(color);
+ hsvGradient.addColorChangeListener(this);
+ hsvLayout.addComponent(hsvGradient);
+ selectors.add(hsvGradient);
+
+ float[] hsv = color.getHSV();
+ VerticalLayout sliders = new VerticalLayout();
+ sliders.setStyleName("hsv-sliders");
+
+ hueSlider = new Slider("Hue", 0, 360);
+ try {
+ hueSlider.setValue(((Float) hsv[0]).doubleValue());
+ } catch (ValueOutOfBoundsException e1) {
+ }
+
+ hueSlider.setStyleName("hsv-slider");
+ hueSlider.addStyleName("hue-slider");
+ hueSlider.setWidth("220px");
+ hueSlider.setImmediate(true);
+ hueSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ if (!updatingColors) {
+ float hue = (Float.parseFloat(event.getProperty()
+ .getValue().toString())) / 360f;
+ float saturation = (Float.parseFloat(saturationSlider
+ .getValue().toString())) / 100f;
+ float value = (Float.parseFloat(valueSlider.getValue()
+ .toString())) / 100f;
+
+ // Set the color
+ Color color = new Color(Color.HSVtoRGB(hue, saturation,
+ value));
+ setColor(color);
+
+ /*
+ * Set the background color of the hue gradient. This has to
+ * be done here since in the conversion the base color
+ * information is lost when color is black/white
+ */
+ Color bgColor = new Color(Color.HSVtoRGB(hue, 1f, 1f));
+ hsvGradient.setBackgroundColor(bgColor);
+ }
+ }
+ });
+ sliders.addComponent(hueSlider);
+
+ saturationSlider = new Slider("Saturation", 0, 100);
+
+ try {
+ saturationSlider.setValue(((Float) hsv[1]).doubleValue());
+ } catch (ValueOutOfBoundsException e1) {
+ }
+
+ saturationSlider.setStyleName("hsv-slider");
+ saturationSlider.setWidth("220px");
+ saturationSlider.setImmediate(true);
+ saturationSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ if (!updatingColors) {
+ float hue = (Float.parseFloat(hueSlider.getValue()
+ .toString())) / 360f;
+ float saturation = (Float.parseFloat(event.getProperty()
+ .getValue().toString())) / 100f;
+ float value = (Float.parseFloat(valueSlider.getValue()
+ .toString())) / 100f;
+ Color color = new Color(Color.HSVtoRGB(hue, saturation,
+ value));
+ setColor(color);
+ }
+ }
+ });
+ sliders.addComponent(saturationSlider);
+
+ valueSlider = new Slider("Value", 0, 100);
+
+ try {
+ valueSlider.setValue(((Float) hsv[2]).doubleValue());
+ } catch (ValueOutOfBoundsException e1) {
+ }
+
+ valueSlider.setStyleName("hsv-slider");
+ valueSlider.setWidth("220px");
+ valueSlider.setImmediate(true);
+ valueSlider.addValueChangeListener(new ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ if (!updatingColors) {
+ float hue = (Float.parseFloat(hueSlider.getValue()
+ .toString())) / 360f;
+ float saturation = (Float.parseFloat(saturationSlider
+ .getValue().toString())) / 100f;
+ float value = (Float.parseFloat(event.getProperty()
+ .getValue().toString())) / 100f;
+
+ Color color = new Color(Color.HSVtoRGB(hue, saturation,
+ value));
+ setColor(color);
+ }
+ }
+ });
+
+ sliders.addComponent(valueSlider);
+ hsvLayout.addComponent(sliders);
+
+ return hsvLayout;
+ }
+
+ /**
+ * Creates the select tab.
+ *
+ * @return the component
+ */
+ private Component createSelectTab() {
+ VerticalLayout selLayout = new VerticalLayout();
+ selLayout.setMargin(new MarginInfo(false, false, true, false));
+ selLayout.addComponent(selPreview);
+ selLayout.addStyleName("seltab");
+
+ colorSelect = new ColorPickerSelect();
+ colorSelect.addColorChangeListener(this);
+ selLayout.addComponent(colorSelect);
+
+ return selLayout;
+ }
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ // History resize was clicked
+ if (event.getButton() == resize) {
+ boolean state = (Boolean) resize.getData();
+
+ // minimize
+ if (state) {
+ historyContainer.setHeight("27px");
+ history.setHeight("22px");
+
+ // maximize
+ } else {
+ historyContainer.setHeight("90px");
+ history.setHeight("85px");
+ }
+
+ resize.setData(new Boolean(!state));
+ }
+
+ // Ok button was clicked
+ else if (event.getButton() == ok) {
+ history.setColor(getColor());
+ fireColorChanged();
+ close();
+ }
+
+ // Cancel button was clicked
+ else if (event.getButton() == cancel) {
+ close();
+ }
+
+ }
+
+ /**
+ * Notifies the listeners that the color changed
+ */
+ public void fireColorChanged() {
+ fireEvent(new ColorChangeEvent(this, getColor()));
+ }
+
+ /**
+ * Gets the history.
+ *
+ * @return the history
+ */
+ public ColorPickerHistory getHistory() {
+ return history;
+ }
+
+ @Override
+ public void setColor(Color color) {
+ if (color == null) {
+ return;
+ }
+
+ selectedColor = color;
+
+ hsvGradient.setColor(selectedColor);
+ hsvPreview.setColor(selectedColor);
+
+ rgbGradient.setColor(selectedColor);
+ rgbPreview.setColor(selectedColor);
+
+ selPreview.setColor(selectedColor);
+ }
+
+ @Override
+ public Color getColor() {
+ return selectedColor;
+ }
+
+ /**
+ * Gets the color history.
+ *
+ * @return the color history
+ */
+ public List<Color> getColorHistory() {
+ return Collections.unmodifiableList(history.getHistory());
+ }
+
+ @Override
+ public void colorChanged(ColorChangeEvent event) {
+ setColor(event.getColor());
+
+ updatingColors = true;
+ try {
+ redSlider
+ .setValue(((Integer) selectedColor.getRed()).doubleValue());
+ blueSlider.setValue(((Integer) selectedColor.getBlue())
+ .doubleValue());
+ greenSlider.setValue(((Integer) selectedColor.getGreen())
+ .doubleValue());
+
+ float[] hsv = selectedColor.getHSV();
+
+ hueSlider.setValue(((Float) (hsv[0] * 360f)).doubleValue());
+ saturationSlider.setValue(((Float) (hsv[1] * 100f)).doubleValue());
+ valueSlider.setValue(((Float) (hsv[2] * 100f)).doubleValue());
+
+ } catch (ValueOutOfBoundsException e) {
+ e.printStackTrace();
+ }
+ updatingColors = false;
+
+ for (ColorSelector s : selectors) {
+ if (event.getSource() != s && s != this
+ && s.getColor() != selectedColor) {
+ s.setColor(selectedColor);
+ }
+ }
+ }
+
+ @Override
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ @Override
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ /**
+ * Checks the visibility of the given tab
+ *
+ * @param tab
+ * The tab to check
+ * @return true if tab is visible, false otherwise
+ */
+ private boolean tabIsVisible(Component tab) {
+ Iterator<Component> tabIterator = tabs.getComponentIterator();
+ while (tabIterator.hasNext()) {
+ if (tabIterator.next() == tab) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * How many tabs are visible
+ *
+ * @return The number of tabs visible
+ */
+ private int tabsNumVisible() {
+ Iterator<Component> tabIterator = tabs.getComponentIterator();
+ int tabCounter = 0;
+ while (tabIterator.hasNext()) {
+ tabIterator.next();
+ tabCounter++;
+ }
+ return tabCounter;
+ }
+
+ /**
+ * Checks if tabs are needed and hides them if not
+ */
+ private void checkIfTabsNeeded() {
+ tabs.hideTabs(tabsNumVisible() == 1);
+ }
+
+ /**
+ * Set RGB tab visibility
+ *
+ * @param visible
+ * The visibility of the RGB tab
+ */
+ public void setRGBTabVisible(boolean visible) {
+ if (visible && !tabIsVisible(rgbTab)) {
+ tabs.addTab(rgbTab, "RGB", null);
+ checkIfTabsNeeded();
+ } else if (!visible && tabIsVisible(rgbTab)) {
+ tabs.removeComponent(rgbTab);
+ checkIfTabsNeeded();
+ }
+ }
+
+ /**
+ * Set HSV tab visibility
+ *
+ * @param visible
+ * The visibility of the HSV tab
+ */
+ public void setHSVTabVisible(boolean visible) {
+ if (visible && !tabIsVisible(hsvTab)) {
+ tabs.addTab(hsvTab, "HSV", null);
+ checkIfTabsNeeded();
+ } else if (!visible && tabIsVisible(hsvTab)) {
+ tabs.removeComponent(hsvTab);
+ checkIfTabsNeeded();
+ }
+ }
+
+ /**
+ * Set Swatches tab visibility
+ *
+ * @param visible
+ * The visibility of the Swatches tab
+ */
+ public void setSwatchesTabVisible(boolean visible) {
+ if (visible && !tabIsVisible(swatchesTab)) {
+ tabs.addTab(swatchesTab, "Swatches", null);
+ checkIfTabsNeeded();
+ } else if (!visible && tabIsVisible(swatchesTab)) {
+ tabs.removeComponent(swatchesTab);
+ checkIfTabsNeeded();
+ }
+ }
+
+ /**
+ * Set the History visibility
+ *
+ * @param visible
+ */
+ public void setHistoryVisible(boolean visible) {
+ historyContainer.setVisible(visible);
+ resize.setVisible(visible);
+ }
+
+ /**
+ * Set the preview visibility
+ *
+ * @param visible
+ */
+ public void setPreviewVisible(boolean visible) {
+ hsvPreview.setVisible(visible);
+ rgbPreview.setVisible(visible);
+ selPreview.setVisible(visible);
+ }
+
+ /** RGB color converter */
+ private Coordinates2Color RGBConverter = new Coordinates2Color() {
+
+ @Override
+ public Color calculate(int x, int y) {
+ float h = (x / 220f);
+ float s = 1f;
+ float v = 1f;
+
+ if (y < 110) {
+ s = y / 110f;
+ } else if (y > 110) {
+ v = 1f - (y - 110f) / 110f;
+ }
+
+ return new Color(Color.HSVtoRGB(h, s, v));
+ }
+
+ @Override
+ public int[] calculate(Color color) {
+
+ float[] hsv = color.getHSV();
+
+ int x = Math.round(hsv[0] * 220f);
+ int y = 0;
+
+ // lower half
+ if (hsv[1] == 1f) {
+ y = Math.round(110f - (hsv[1] + hsv[2]) * 110f);
+ } else {
+ y = Math.round(hsv[1] * 110f);
+ }
+
+ return new int[] { x, y };
+ }
+ };
+
+ /** HSV color converter */
+ Coordinates2Color HSVConverter = new Coordinates2Color() {
+ public int[] calculate(Color color) {
+
+ float[] hsv = color.getHSV();
+
+ // Calculate coordinates
+ int x = Math.round(hsv[2] * 220.0f);
+ int y = Math.round(220 - hsv[1] * 220.0f);
+
+ // Create background color of clean color
+ Color bgColor = new Color(Color.HSVtoRGB(hsv[0], 1f, 1f));
+ hsvGradient.setBackgroundColor(bgColor);
+
+ return new int[] { x, y };
+ }
+
+ public Color calculate(int x, int y) {
+ float saturation = 1f - (y / 220.0f);
+ float value = (x / 220.0f);
+ float hue = Float.parseFloat(hueSlider.getValue().toString()) / 360f;
+
+ Color color = new Color(Color.HSVtoRGB(hue, saturation, value));
+ return color;
+ }
+ };
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
new file mode 100644
index 0000000000..cb6dba3aab
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
@@ -0,0 +1,143 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.lang.reflect.Method;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.validator.RegexpValidator;
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.TextField;
+
+/**
+ * A component that represents color selection preview within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerPreview extends CssLayout implements ColorSelector,
+ ValueChangeListener {
+
+ private static final String STYLE_DARK_COLOR = "v-textfield-dark";
+ private static final String STYLE_LIGHT_COLOR = "v-textfield-light";
+
+ private static final Method COLOR_CHANGE_METHOD;
+ static {
+ try {
+ COLOR_CHANGE_METHOD = ColorChangeListener.class.getDeclaredMethod(
+ "colorChanged", new Class[] { ColorChangeEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in ColorPicker");
+ }
+ }
+
+ /** The color. */
+ private Color color;
+
+ /** The field. */
+ private final TextField field;
+
+ /** The old value. */
+ private String oldValue;
+
+ /**
+ * Instantiates a new color picker preview.
+ */
+ public ColorPickerPreview(Color color) {
+ setStyleName("v-colorpicker-preview");
+ setImmediate(true);
+
+ this.color = color;
+
+ field = new TextField();
+ field.setReadOnly(true);
+ field.setImmediate(true);
+ field.setSizeFull();
+ field.setStyleName("v-colorpicker-preview-textfield");
+ field.setData(this);
+ field.addValueChangeListener(this);
+ field.addValidator(new RegexpValidator("#[0-9a-fA-F]{6}", true, ""));
+ addComponent(field);
+
+ setColor(color);
+ }
+
+ @Override
+ public void setColor(Color color) {
+ this.color = color;
+
+ // Unregister listener
+ field.removeValueChangeListener(this);
+ field.setReadOnly(false);
+
+ String colorCSS = color.getCSS();
+ field.setValue(colorCSS);
+
+ if (field.isValid()) {
+ oldValue = colorCSS;
+ } else {
+ field.setValue(oldValue);
+ }
+
+ // Re-register listener
+ field.setReadOnly(true);
+ field.addValueChangeListener(this);
+
+ // Set the text color
+ field.removeStyleName(STYLE_DARK_COLOR);
+ field.removeStyleName(STYLE_LIGHT_COLOR);
+ if (this.color.getRed() + this.color.getGreen() + this.color.getBlue() < 3 * 128) {
+ field.addStyleName(STYLE_DARK_COLOR);
+ } else {
+ field.addStyleName(STYLE_LIGHT_COLOR);
+ }
+
+ markAsDirty();
+ }
+
+ @Override
+ public Color getColor() {
+ return color;
+ }
+
+ @Override
+ public void addColorChangeListener(ColorChangeListener listener) {
+ addListener(ColorChangeEvent.class, listener, COLOR_CHANGE_METHOD);
+ }
+
+ @Override
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ removeListener(ColorChangeEvent.class, listener);
+ }
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ String value = (String) event.getProperty().getValue();
+
+ if (!field.isValid()) {
+ field.setValue(oldValue);
+ return;
+ } else {
+ oldValue = value;
+ }
+
+ if (value != null && value.length() == 7) {
+ int red = Integer.parseInt(value.substring(1, 3), 16);
+ int green = Integer.parseInt(value.substring(3, 5), 16);
+ int blue = Integer.parseInt(value.substring(5, 7), 16);
+ color = new Color(red, green, blue);
+
+ fireEvent(new ColorChangeEvent((Component) field.getData(), color));
+ }
+ }
+
+ /**
+ * Called when the component is refreshing
+ */
+ @Override
+ protected String getCss(Component c) {
+ return "background: " + color.getCSS();
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java
new file mode 100644
index 0000000000..08747cce3f
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java
@@ -0,0 +1,218 @@
+package com.vaadin.ui.components.colorpicker;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * A component that represents color selection swatches within a color picker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerSelect extends CustomComponent implements
+ ColorSelector, ValueChangeListener {
+
+ /** The range. */
+ private final ComboBox range;
+
+ /** The grid. */
+ private final ColorPickerGrid grid;
+
+ /**
+ * The Enum ColorRangePropertyId.
+ */
+ private enum ColorRangePropertyId {
+ ALL("All colors"), RED("Red colors"), GREEN("Green colors"), BLUE(
+ "Blue colors");
+
+ /** The caption. */
+ private String caption;
+
+ /**
+ * Instantiates a new color range property id.
+ *
+ * @param caption
+ * the caption
+ */
+ ColorRangePropertyId(String caption) {
+ this.caption = caption;
+ }
+
+ @Override
+ public String toString() {
+ return caption;
+ }
+ }
+
+ /**
+ * Instantiates a new color picker select.
+ *
+ * @param rows
+ * the rows
+ * @param columns
+ * the columns
+ */
+ public ColorPickerSelect() {
+
+ VerticalLayout layout = new VerticalLayout();
+ setCompositionRoot(layout);
+
+ setStyleName("colorselect");
+ setWidth("100%");
+
+ range = new ComboBox();
+ range.setImmediate(true);
+ range.setImmediate(true);
+ range.setNullSelectionAllowed(false);
+ range.setNewItemsAllowed(false);
+ range.setWidth("100%");
+ range.addValueChangeListener(this);
+
+ for (ColorRangePropertyId id : ColorRangePropertyId.values()) {
+ range.addItem(id);
+ }
+ range.select(ColorRangePropertyId.ALL);
+
+ layout.addComponent(range);
+
+ grid = new ColorPickerGrid(createAllColors(14, 10));
+ grid.setWidth("100%");
+
+ layout.addComponent(grid);
+ }
+
+ /**
+ * Creates the all colors.
+ *
+ * @param rows
+ * the rows
+ * @param columns
+ * the columns
+ *
+ * @return the color[][]
+ */
+ private Color[][] createAllColors(int rows, int columns) {
+ Color[][] colors = new Color[rows][columns];
+
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < columns; col++) {
+
+ // Create the color grid by varying the saturation and value
+ if (row < (rows - 1)) {
+ // Calculate new hue value
+ float hue = ((float) col / (float) columns);
+ float saturation = 1f;
+ float value = 1f;
+
+ // For the upper half use value=1 and variable
+ // saturation
+ if (row < (rows / 2)) {
+ saturation = ((row + 1f) / (rows / 2f));
+ } else {
+ value = 1f - ((row - (rows / 2f)) / (rows / 2f));
+ }
+
+ colors[row][col] = new Color(Color.HSVtoRGB(hue,
+ saturation, value));
+ }
+
+ // The last row should have the black&white gradient
+ else {
+ float hue = 0f;
+ float saturation = 0f;
+ float value = 1f - ((float) col / (float) columns);
+
+ colors[row][col] = new Color(Color.HSVtoRGB(hue,
+ saturation, value));
+ }
+ }
+ }
+
+ return colors;
+ }
+
+ /**
+ * Creates the color.
+ *
+ * @param color
+ * the color
+ * @param rows
+ * the rows
+ * @param columns
+ * the columns
+ *
+ * @return the color[][]
+ */
+ private Color[][] createColors(Color color, int rows, int columns) {
+ Color[][] colors = new Color[rows][columns];
+
+ float[] hsv = color.getHSV();
+
+ float hue = hsv[0];
+ float saturation = 1f;
+ float value = 1f;
+
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < columns; col++) {
+
+ int index = row * columns + col;
+ saturation = 1f;
+ value = 1f;
+
+ if (index <= ((rows * columns) / 2)) {
+ saturation = index
+ / (((float) rows * (float) columns) / 2f);
+ } else {
+ index -= ((rows * columns) / 2);
+ value = 1f - index
+ / (((float) rows * (float) columns) / 2f);
+ }
+
+ colors[row][col] = new Color(Color.HSVtoRGB(hue, saturation,
+ value));
+ }
+ }
+
+ return colors;
+ }
+
+ @Override
+ public Color getColor() {
+ return grid.getColor();
+ }
+
+ @Override
+ public void setColor(Color color) {
+ grid.getColor();
+ }
+
+ @Override
+ public void addColorChangeListener(ColorChangeListener listener) {
+ grid.addColorChangeListener(listener);
+ }
+
+ @Override
+ public void removeColorChangeListener(ColorChangeListener listener) {
+ grid.removeColorChangeListener(listener);
+ }
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ if (grid == null) {
+ return;
+ }
+
+ if (event.getProperty().getValue() == ColorRangePropertyId.ALL) {
+ grid.setColorGrid(createAllColors(14, 10));
+ } else if (event.getProperty().getValue() == ColorRangePropertyId.RED) {
+ grid.setColorGrid(createColors(new Color(0xFF, 0, 0), 14, 10));
+ } else if (event.getProperty().getValue() == ColorRangePropertyId.GREEN) {
+ grid.setColorGrid(createColors(new Color(0, 0xFF, 0), 14, 10));
+ } else if (event.getProperty().getValue() == ColorRangePropertyId.BLUE) {
+ grid.setColorGrid(createColors(new Color(0, 0, 0xFF), 14, 10));
+ }
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorSelector.java b/server/src/com/vaadin/ui/components/colorpicker/ColorSelector.java
new file mode 100644
index 0000000000..8468666e26
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorSelector.java
@@ -0,0 +1,28 @@
+package com.vaadin.ui.components.colorpicker;
+
+import java.io.Serializable;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+
+/**
+ * An interface for a color selector.
+ *
+ * @since 7.0.0
+ */
+public interface ColorSelector extends Serializable, HasColorChangeListener {
+
+ /**
+ * Sets the color.
+ *
+ * @param color
+ * the new color
+ */
+ public void setColor(Color color);
+
+ /**
+ * Gets the color.
+ *
+ * @return the color
+ */
+ public Color getColor();
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/components/colorpicker/HasColorChangeListener.java b/server/src/com/vaadin/ui/components/colorpicker/HasColorChangeListener.java
new file mode 100644
index 0000000000..25b3d3c6da
--- /dev/null
+++ b/server/src/com/vaadin/ui/components/colorpicker/HasColorChangeListener.java
@@ -0,0 +1,19 @@
+package com.vaadin.ui.components.colorpicker;
+
+public interface HasColorChangeListener {
+
+ /**
+ * Adds a {@link ColorChangeListener} to the component.
+ *
+ * @param listener
+ */
+ void addColorChangeListener(ColorChangeListener listener);
+
+ /**
+ * Removes a {@link ColorChangeListener} from the component.
+ *
+ * @param listener
+ */
+ void removeColorChangeListener(ColorChangeListener listener);
+
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
index f24638e6a7..250fa3f771 100644
--- a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
+++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
@@ -50,16 +50,17 @@ public class TestStreamVariableMapping extends TestCase {
public void testAddStreamVariable() {
String targetUrl = cm.getStreamVariableTargetUrl(owner, variableName,
streamVariable);
- assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/1/myName/"));
+ assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/"
+ + owner.getConnectorId() + "/myName/"));
- ConnectorTracker tracker = UI.getCurrent().getConnectorTracker();
+ ConnectorTracker tracker = owner.getUI().getConnectorTracker();
StreamVariable streamVariable2 = tracker.getStreamVariable(
owner.getConnectorId(), variableName);
assertSame(streamVariable, streamVariable2);
}
- public void testRemoverVariable() {
- ConnectorTracker tracker = UI.getCurrent().getConnectorTracker();
+ public void testRemoveVariable() {
+ ConnectorTracker tracker = owner.getUI().getConnectorTracker();
cm.getStreamVariableTargetUrl(owner, variableName, streamVariable);
assertNotNull(tracker.getStreamVariable(owner.getConnectorId(),
variableName));
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/Color.java b/shared/src/com/vaadin/shared/ui/colorpicker/Color.java
new file mode 100644
index 0000000000..602821346e
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/Color.java
@@ -0,0 +1,378 @@
+package com.vaadin.shared.ui.colorpicker;
+
+/**
+ * Default implementation for color.
+ *
+ * @since 7.0.0
+ */
+public class Color {
+
+ public static final Color WHITE = new Color(255, 255, 255);
+ public static final Color BLACK = new Color(0, 0, 0);
+ public static final Color RED = new Color(255, 0, 0);
+ public static final Color GREEN = new Color(0, 255, 0);
+ public static final Color BLUE = new Color(0, 0, 255);
+ public static final Color YELLOW = new Color(255, 255, 0);
+ public static final Color MAGENTA = new Color(255, 0, 255);
+ public static final Color CYAN = new Color(0, 255, 255);
+
+ private int red;
+ private int green;
+ private int blue;
+ private int alpha;
+
+ private String OUTOFRANGE = "Value must be within the range [0-255]. Was: ";
+
+ /**
+ * Creates a color that has the specified red, green, blue, and alpha values
+ * within the range [0 - 255].
+ *
+ * @throws IllegalArgumentException
+ * if <code>red</code>, <code>green</code>, <code>blue</code> or
+ * <code>alpha</code> fall outside of the inclusive range from 0
+ * to 255
+ * @param red
+ * the red value
+ * @param green
+ * the green value
+ * @param blue
+ * the blue value
+ * @param alpha
+ * the alpha value
+ */
+ public Color(int red, int green, int blue, int alpha) {
+ checkRange(red, green, blue, alpha);
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ }
+
+ /**
+ * Creates a color that has the specified red, green, and blue values within
+ * the range [0 - 255]. Alpha gets the default value of 255.
+ *
+ * @throws IllegalArgumentException
+ * if <code>red</code>, <code>green</code> or <code>blue</code>
+ * fall outside of the inclusive range from 0 to 255
+ * @param red
+ * the red value
+ * @param green
+ * the green value
+ * @param blue
+ * the blue value
+ */
+ public Color(int red, int green, int blue) {
+ this(red, green, blue, 255);
+ }
+
+ /**
+ * Creates a color based on an RGB value.
+ *
+ * @throws IllegalArgumentException
+ * if converted values of <code>red</code>, <code>green</code>,
+ * <code>blue</code> or <code>alpha</code> fall outside of the
+ * inclusive range from 0 to 255
+ *
+ * @param rgb
+ * the RGB value
+ */
+ public Color(int rgb) {
+ int value = 0xff000000 | rgb;
+ int red = (value >> 16) & 0xFF;
+ int green = (value >> 8) & 0xFF;
+ int blue = (value >> 0) & 0xFF;
+ int alpha = (value >> 24) & 0xff;
+
+ checkRange(red, green, blue, alpha);
+
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ }
+
+ /**
+ * Checks that all values are within the acceptable range of [0, 255].
+ *
+ * @throws IllegalArgumentException
+ * if any of the values fall outside of the range
+ *
+ * @param red
+ * @param green
+ * @param blue
+ * @param alpha
+ */
+ private void checkRange(int red, int green, int blue, int alpha) {
+ if (!withinRange(red) || !withinRange(green) || !withinRange(blue)
+ || !withinRange(alpha)) {
+
+ String errorMessage = "All values must fall within range [0-255]. (red: "
+ + red
+ + ", green: "
+ + green
+ + ", blue: "
+ + blue
+ + ", alpha: " + alpha + ")";
+ throw new IllegalArgumentException(errorMessage);
+ }
+ }
+
+ /**
+ * Checks whether the value is within the acceptable range of [0, 255].
+ *
+ * @param value
+ * @return true if the value falls within the range, false otherwise
+ */
+ private boolean withinRange(int value) {
+ if (value < 0 || value > 255) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the red value of the color.
+ *
+ */
+ public int getRed() {
+ return red;
+ }
+
+ /**
+ * Sets the red value of the color. Value must be within the range [0, 255].
+ *
+ * @param red
+ * new red value
+ */
+ public void setRed(int red) {
+ if (withinRange(red)) {
+ this.red = red;
+ } else {
+ throw new IllegalArgumentException(OUTOFRANGE + red);
+ }
+ }
+
+ /**
+ * Returns the green value of the color.
+ *
+ */
+ public int getGreen() {
+ return green;
+ }
+
+ /**
+ * Sets the green value of the color. Value must be within the range [0,
+ * 255].
+ *
+ * @param green
+ * new green value
+ */
+ public void setGreen(int green) {
+ if (withinRange(green)) {
+ this.green = green;
+ } else {
+ throw new IllegalArgumentException(OUTOFRANGE + green);
+ }
+ }
+
+ /**
+ * Returns the blue value of the color.
+ *
+ */
+ public int getBlue() {
+ return blue;
+ }
+
+ /**
+ * Sets the blue value of the color. Value must be within the range [0,
+ * 255].
+ *
+ * @param blue
+ * new blue value
+ */
+ public void setBlue(int blue) {
+ if (withinRange(blue)) {
+ this.blue = blue;
+ } else {
+ throw new IllegalArgumentException(OUTOFRANGE + blue);
+ }
+ }
+
+ /**
+ * Returns the alpha value of the color.
+ *
+ */
+ public int getAlpha() {
+ return alpha;
+ }
+
+ /**
+ * Sets the alpha value of the color. Value must be within the range [0,
+ * 255].
+ *
+ * @param alpha
+ * new alpha value
+ */
+ public void setAlpha(int alpha) {
+ if (withinRange(alpha)) {
+ this.alpha = alpha;
+ } else {
+ throw new IllegalArgumentException(OUTOFRANGE + alpha);
+ }
+ }
+
+ /**
+ * Returns CSS representation of the Color, e.g. #000000.
+ */
+ public String getCSS() {
+ String redString = Integer.toHexString(red);
+ redString = redString.length() < 2 ? "0" + redString : redString;
+
+ String greenString = Integer.toHexString(green);
+ greenString = greenString.length() < 2 ? "0" + greenString
+ : greenString;
+
+ String blueString = Integer.toHexString(blue);
+ blueString = blueString.length() < 2 ? "0" + blueString : blueString;
+
+ return "#" + redString + greenString + blueString;
+ }
+
+ /**
+ * Returns RGB value of the color.
+ */
+ public int getRGB() {
+ return ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16)
+ | ((green & 0xFF) << 8) | ((blue & 0xFF) << 0);
+ }
+
+ /**
+ * Returns converted HSV components of the color.
+ *
+ */
+ public float[] getHSV() {
+ float[] hsv = new float[3];
+
+ int maxColor = (red > green) ? red : green;
+ if (blue > maxColor) {
+ maxColor = blue;
+ }
+ int minColor = (red < green) ? red : green;
+ if (blue < minColor) {
+ minColor = blue;
+ }
+
+ float value = maxColor / 255.0f;
+
+ float saturation = 0;
+ if (maxColor != 0) {
+ saturation = ((float) (maxColor - minColor)) / ((float) maxColor);
+ }
+
+ float hue = 0;
+ if (saturation != 0) {
+ float redF = ((float) (maxColor - red))
+ / ((float) (maxColor - minColor));
+ float greenF = ((float) (maxColor - green))
+ / ((float) (maxColor - minColor));
+ float blueF = ((float) (maxColor - blue))
+ / ((float) (maxColor - minColor));
+
+ if (red == maxColor) {
+ hue = blueF - greenF;
+ } else if (green == maxColor) {
+ hue = 2.0f + redF - blueF;
+ } else {
+ hue = 4.0f + greenF - redF;
+ }
+
+ hue = hue / 6.0f;
+ if (hue < 0) {
+ hue = hue + 1.0f;
+ }
+ }
+
+ hsv[0] = hue;
+ hsv[1] = saturation;
+ hsv[2] = value;
+ return hsv;
+ }
+
+ @Override
+ public int hashCode() {
+ return getRGB();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Color && ((Color) obj).getRGB() == getRGB();
+ }
+
+ /**
+ * <p>
+ * Converts HSV's hue, saturation and value into an RGB value.
+ * <p>
+ * The <code>saturation</code> and <code>value</code> components should be
+ * floating-point values within the range [0.0-1.0].
+ * <p>
+ *
+ * @param hue
+ * the hue of the color
+ * @param saturation
+ * the saturation of the color
+ * @param value
+ * the value of the color
+ * @return the RGB value of corresponding color
+ */
+ public static int HSVtoRGB(float hue, float saturation, float value) {
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+
+ if (saturation == 0) {
+ red = green = blue = (int) (value * 255.0f + 0.5f);
+ } else {
+ float h = (hue - (float) Math.floor(hue)) * 6.0f;
+ float f = h - (float) java.lang.Math.floor(h);
+ float p = value * (1.0f - saturation);
+ float q = value * (1.0f - saturation * f);
+ float t = value * (1.0f - (saturation * (1.0f - f)));
+
+ switch ((int) h) {
+ case 0:
+ red = (int) (value * 255.0f + 0.5f);
+ green = (int) (t * 255.0f + 0.5f);
+ blue = (int) (p * 255.0f + 0.5f);
+ break;
+ case 1:
+ red = (int) (q * 255.0f + 0.5f);
+ green = (int) (value * 255.0f + 0.5f);
+ blue = (int) (p * 255.0f + 0.5f);
+ break;
+ case 2:
+ red = (int) (p * 255.0f + 0.5f);
+ green = (int) (value * 255.0f + 0.5f);
+ blue = (int) (t * 255.0f + 0.5f);
+ break;
+ case 3:
+ red = (int) (p * 255.0f + 0.5f);
+ green = (int) (q * 255.0f + 0.5f);
+ blue = (int) (value * 255.0f + 0.5f);
+ break;
+ case 4:
+ red = (int) (t * 255.0f + 0.5f);
+ green = (int) (p * 255.0f + 0.5f);
+ blue = (int) (value * 255.0f + 0.5f);
+ break;
+ case 5:
+ red = (int) (value * 255.0f + 0.5f);
+ green = (int) (p * 255.0f + 0.5f);
+ blue = (int) (q * 255.0f + 0.5f);
+ break;
+ }
+ }
+
+ return 0xff000000 | (red << 16) | (green << 8) | (blue << 0);
+ }
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientServerRpc.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientServerRpc.java
new file mode 100644
index 0000000000..e5cf016815
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientServerRpc.java
@@ -0,0 +1,21 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * RPC interface for ColorPickerGradient.
+ *
+ * @since 7.0.0
+ *
+ */
+public interface ColorPickerGradientServerRpc extends ServerRpc {
+
+ /**
+ * ColorPickerGradient mouseUp event.
+ *
+ * @param cursorX
+ * @param cursorY
+ */
+ public void select(int cursorX, int cursorY);
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientState.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientState.java
new file mode 100644
index 0000000000..d8d2a5537d
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGradientState.java
@@ -0,0 +1,18 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.AbstractComponentState;
+
+/**
+ * Default shared state implementation for ColorPickerGradient.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerGradientState extends AbstractComponentState {
+
+ public int cursorX;
+
+ public int cursorY;
+
+ public String bgColor;
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridServerRpc.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridServerRpc.java
new file mode 100644
index 0000000000..e56b19c80d
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridServerRpc.java
@@ -0,0 +1,26 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * RPC interface for ColorPickerGrid.
+ *
+ * @since 7.0.0
+ *
+ */
+public interface ColorPickerGridServerRpc extends ServerRpc {
+
+ /**
+ * ColorPickerGrid click event.
+ *
+ * @param x
+ * @param y
+ */
+ public void select(int x, int y);
+
+ /**
+ * Call to refresh the grid.
+ */
+ public void refresh();
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridState.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridState.java
new file mode 100644
index 0000000000..e79a3c2b88
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerGridState.java
@@ -0,0 +1,22 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.AbstractComponentState;
+
+/**
+ * Default shared state implementation for ColorPickerGrid.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerGridState extends AbstractComponentState {
+
+ public int rowCount;
+
+ public int columnCount;
+
+ public String[] changedX;
+
+ public String[] changedY;
+
+ public String[] changedColor;
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerServerRpc.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerServerRpc.java
new file mode 100644
index 0000000000..7269923c83
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerServerRpc.java
@@ -0,0 +1,21 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * RPC interface for AbstractColorPicker.
+ *
+ * @since 7.0.0
+ *
+ */
+public interface ColorPickerServerRpc extends ServerRpc {
+
+ /**
+ * ColorPicker click event.
+ *
+ * @param openPopup
+ *
+ */
+ public void openPopup(boolean openPopup);
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerState.java b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerState.java
new file mode 100644
index 0000000000..1a914cfaa4
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerState.java
@@ -0,0 +1,25 @@
+package com.vaadin.shared.ui.colorpicker;
+
+import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.DelegateToWidget;
+
+/**
+ * Default shared state implementation for AbstractColorPicker.
+ *
+ * @since 7.0.0
+ */
+public class ColorPickerState extends AbstractComponentState {
+ {
+ primaryStyleName = "v-colorpicker";
+ }
+
+ @DelegateToWidget("setOpen")
+ public boolean popupVisible = false;
+
+ @DelegateToWidget("setColor")
+ public String color = null;
+
+ public boolean showDefaultCaption;
+
+ public boolean htmlContentAllowed;
+}
diff --git a/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml b/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml
index 495b6d00c9..f921bec167 100644
--- a/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml
+++ b/theme-compiler/ivymodule/smartsprites-ivy-0.2.3-itmill.xml
@@ -32,7 +32,7 @@
<dependency org="args4j" name="args4j" rev="2.0.9" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
<dependency org="commons-math" name="commons-math" rev="1.1" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
<dependency org="commons-io" name="commons-io" rev="1.4" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
- <dependency org="commons-lang" name="commons-lang" rev="2.3" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
+ <dependency org="commons-lang" name="commons-lang" rev="2.6" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
<dependency org="junit" name="junit" rev="4.4" force="true" conf="test->runtime(*),master(*)"/>
</dependencies>
</ivy-module>
diff --git a/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.html b/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.html
new file mode 100644
index 0000000000..fb8669b9f0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.html
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/run/com.vaadin.tests.components.colorpicker.ColorPickerTest?restartApplication" />
+<title>ColorPickerTest</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">ColorPickerTest</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.colorpicker.ColorPickerTest?restartApplication</td>
+ <td></td>
+</tr>
+
+<!-- change foreground color -->
+<tr>
+ <td>click</td>
+ <td>colorpicker1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Srgb-gradient/domChild[1]/domChild[4]</td>
+ <td>190,87</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+
+<!-- change background color -->
+<tr>
+ <td>click</td>
+ <td>colorpicker2</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Srgb-gradient/domChild[1]/domChild[4]</td>
+ <td>51,33</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>pink-on-yellow</td>
+</tr>
+
+<!-- change foreground color with area button -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker5/domChild[1]</td>
+ <td>10,15</td>
+</tr>
+<!-- expand history -->
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!-- choose from history -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VCustomComponent[0]/VColorPickerGrid[0]/domChild[0]/domChild[1]/domChild[0]/domChild[3]</td>
+ <td>9,9</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+
+<!-- change background color with area button -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker6/domChild[1]</td>
+ <td>12,24</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VCustomComponent[0]/VColorPickerGrid[0]/domChild[0]/domChild[1]/domChild[0]/domChild[1]</td>
+ <td>9,12</td>
+</tr>
+<!-- choose from history -->
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>black-on-white</td>
+</tr>
+
+<!-- open and close -->
+<tr>
+ <td>click</td>
+ <td>colorpicker1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>colorpicker1</td>
+ <td></td>
+</tr>
+
+<!-- open and close using area button -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker5/domChild[1]</td>
+ <td>11,17</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker5/domChild[1]</td>
+ <td>11,17</td>
+</tr>
+
+<!-- open background (using area button) to display HSV effects -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker6/domChild[1]</td>
+ <td>21,15</td>
+</tr>
+<!-- HSV tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>12,6</td>
+</tr>
+<!-- hue slider -->
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VSlider[0]/domChild[2]/domChild[0]</td>
+ <td>136,0</td>
+</tr>
+<!-- saturation slider -->
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VSlider[0]/domChild[2]/domChild[0]</td>
+ <td>100,0</td>
+</tr>
+<!-- value slider -->
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VVerticalLayout[0]/VOrderedLayout$Slot[2]/VSlider[0]/domChild[2]/domChild[0]</td>
+ <td>-60,0</td>
+</tr>
+<!-- Swatches tab (choose color) -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>43,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VCustomComponent[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VColorPickerGrid[0]/domChild[0]/domChild[1]/domChild[11]/domChild[9]</td>
+ <td>12,10</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>black-on-purple</td>
+</tr>
+
+<!-- open foreground (using area button) to display checkbox effects -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Scolorpicker5/domChild[1]</td>
+ <td>14,25</td>
+</tr>
+<!-- remove Swatches tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_SswaBox/domChild[0]</td>
+ <td>9,6</td>
+</tr>
+<!-- remove css field -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_StxtBox/domChild[0]</td>
+ <td>6,9</td>
+</tr>
+<!-- remove history -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_ShisBox/domChild[0]</td>
+ <td>6,7</td>
+</tr>
+<!-- remove RGB tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_SrgbBox/domChild[0]</td>
+ <td>6,7</td>
+</tr>
+<!-- return RGB tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_SrgbBox/domChild[0]</td>
+ <td>6,7</td>
+</tr>
+<!-- remove HSV tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_ShsvBox/domChild[0]</td>
+ <td>6,9</td>
+</tr>
+<!-- return HSV tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_ShsvBox/domChild[0]</td>
+ <td>6,9</td>
+</tr>
+<!-- return css field -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_StxtBox/domChild[0]</td>
+ <td>8,8</td>
+</tr>
+<!-- return history -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_ShisBox/domChild[0]</td>
+ <td>6,8</td>
+</tr>
+<!-- return Swatches tab -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_SswaBox/domChild[0]</td>
+ <td>4,8</td>
+</tr>
+<!-- close without choosing a new color -->
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[1]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+
+<!-- change color of the first shade button -->
+<tr>
+ <td>click</td>
+ <td>shadebutton_1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Srgb-gradient/domChild[1]/domChild[4]</td>
+ <td>148,127</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>blue-first-button</td>
+</tr>
+
+<!-- reset the color back to black -->
+<tr>
+ <td>click</td>
+ <td>shadebutton_1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VCustomComponent[0]/VColorPickerGrid[0]/domChild[0]/domChild[1]/domChild[0]/domChild[6]</td>
+ <td>10,7</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+
+<!-- change color of the last shade area -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Sshadearea_16/domChild[1]</td>
+ <td>10,-65</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Srgb-gradient/domChild[1]/domChild[4]</td>
+ <td>36,93</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>yellow-last-area</td>
+</tr>
+
+<!-- reset the color back to white -->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::PID_Sshadearea_16/domChild[1]</td>
+ <td>19,-65</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[1]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VCustomComponent[0]/VColorPickerGrid[0]/domChild[0]/domChild[1]/domChild[0]/domChild[4]</td>
+ <td>6,7</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscolorpickerColorPickerTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VOrderedLayout$Slot[3]/VHorizontalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>final</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.java b/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.java
new file mode 100644
index 0000000000..0f7e639725
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/colorpicker/ColorPickerTest.java
@@ -0,0 +1,492 @@
+package com.vaadin.tests.components.colorpicker;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.imageio.ImageIO;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.server.StreamResource;
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.AbstractColorPicker;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ColorPicker;
+import com.vaadin.ui.ColorPickerArea;
+import com.vaadin.ui.Embedded;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
+import com.vaadin.ui.components.colorpicker.ColorChangeListener;
+
+public class ColorPickerTest extends TestBase implements ColorChangeListener {
+
+ @Override
+ protected String getDescription() {
+ return "Vaadin 7 compatible ColorPicker";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 9201;
+ }
+
+ /** The foreground color. */
+ private Color foregroundColor = Color.BLACK; // The currently selected
+
+ /** The background color. */
+ private Color backgroundColor = Color.WHITE; // The currently selected
+
+ // The display box where the image is rendered
+ /** The display. */
+ private Embedded display;
+
+ private AbstractColorPicker colorpicker1;
+ private AbstractColorPicker colorpicker2;
+ private AbstractColorPicker colorpicker3;
+ private AbstractColorPicker colorpicker4;
+ private AbstractColorPicker colorpicker5;
+ private AbstractColorPicker colorpicker6;
+
+ private boolean rgbVisible = true;
+ private boolean hsvVisible = true;
+ private boolean swaVisible = true;
+ private boolean historyVisible = true;
+ private boolean txtfieldVisible = true;
+
+ private final CheckBox rgbBox = new CheckBox("RGB tab visible");
+ private final CheckBox hsvBox = new CheckBox("HSV tab visible");
+ private final CheckBox swaBox = new CheckBox("Swatches tab visible");
+ private final CheckBox hisBox = new CheckBox("History visible");
+ private final CheckBox txtBox = new CheckBox("CSS field visible");
+
+ /**
+ * This class is used to represent the preview of the color selection.
+ */
+ public class MyImageSource implements StreamResource.StreamSource {
+
+ /** The imagebuffer. */
+ private java.io.ByteArrayOutputStream imagebuffer = null;
+
+ /** The bg color. */
+ private final java.awt.Color bgColor;
+
+ /** The fg color. */
+ private final java.awt.Color fgColor;
+
+ /**
+ * Instantiates a new my image source.
+ *
+ * @param fg
+ * the foreground
+ * @param bg
+ * the background
+ */
+ public MyImageSource(java.awt.Color fg, java.awt.Color bg) {
+ fgColor = fg;
+ bgColor = bg;
+ }
+
+ /* Must implement this method that returns the resource as a stream. */
+ @Override
+ public InputStream getStream() {
+
+ /* Create an image and draw something on it. */
+ BufferedImage image = new BufferedImage(270, 270,
+ BufferedImage.TYPE_INT_RGB);
+ Graphics drawable = image.getGraphics();
+ drawable.setColor(bgColor);
+ drawable.fillRect(0, 0, 270, 270);
+ drawable.setColor(fgColor);
+ drawable.fillOval(25, 25, 220, 220);
+ drawable.setColor(java.awt.Color.blue);
+ drawable.drawRect(0, 0, 269, 269);
+ drawable.setColor(java.awt.Color.black);
+ drawable.drawString(
+ "r=" + String.valueOf(fgColor.getRed()) + ",g="
+ + String.valueOf(fgColor.getGreen()) + ",b="
+ + String.valueOf(fgColor.getBlue()), 50, 100);
+ drawable.drawString(
+ "r=" + String.valueOf(bgColor.getRed()) + ",g="
+ + String.valueOf(bgColor.getGreen()) + ",b="
+ + String.valueOf(bgColor.getBlue()), 5, 15);
+
+ try {
+ /* Write the image to a buffer. */
+ imagebuffer = new ByteArrayOutputStream();
+ ImageIO.write(image, "png", imagebuffer);
+
+ /* Return a stream from the buffer. */
+ return new ByteArrayInputStream(imagebuffer.toByteArray());
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ }
+
+ private void setPopupVisibilities() {
+
+ rgbBox.setEnabled(!(rgbVisible && !hsvVisible && !swaVisible));
+ hsvBox.setEnabled(!(!rgbVisible && hsvVisible && !swaVisible));
+ swaBox.setEnabled(!(!rgbVisible && !hsvVisible && swaVisible));
+
+ colorpicker1.setRGBVisibility(rgbVisible);
+ colorpicker2.setRGBVisibility(rgbVisible);
+ colorpicker3.setRGBVisibility(rgbVisible);
+ colorpicker4.setRGBVisibility(rgbVisible);
+ colorpicker5.setRGBVisibility(rgbVisible);
+ colorpicker6.setRGBVisibility(rgbVisible);
+
+ colorpicker1.setHSVVisibility(hsvVisible);
+ colorpicker2.setHSVVisibility(hsvVisible);
+ colorpicker3.setHSVVisibility(hsvVisible);
+ colorpicker4.setHSVVisibility(hsvVisible);
+ colorpicker5.setHSVVisibility(hsvVisible);
+ colorpicker6.setHSVVisibility(hsvVisible);
+
+ colorpicker1.setSwatchesVisibility(swaVisible);
+ colorpicker2.setSwatchesVisibility(swaVisible);
+ colorpicker3.setSwatchesVisibility(swaVisible);
+ colorpicker4.setSwatchesVisibility(swaVisible);
+ colorpicker5.setSwatchesVisibility(swaVisible);
+ colorpicker6.setSwatchesVisibility(swaVisible);
+
+ colorpicker1.setHistoryVisibility(historyVisible);
+ colorpicker2.setHistoryVisibility(historyVisible);
+ colorpicker3.setHistoryVisibility(historyVisible);
+ colorpicker4.setHistoryVisibility(historyVisible);
+ colorpicker5.setHistoryVisibility(historyVisible);
+ colorpicker6.setHistoryVisibility(historyVisible);
+
+ colorpicker1.setTextfieldVisibility(txtfieldVisible);
+ colorpicker2.setTextfieldVisibility(txtfieldVisible);
+ colorpicker3.setTextfieldVisibility(txtfieldVisible);
+ colorpicker4.setTextfieldVisibility(txtfieldVisible);
+ colorpicker5.setTextfieldVisibility(txtfieldVisible);
+ colorpicker6.setTextfieldVisibility(txtfieldVisible);
+ }
+
+ @Override
+ protected void setup() {
+ getLayout().setWidth("1000px");
+ getLayout().setHeight(null);
+ getLayout().addStyleName("colorpicker-mainwindow-content");
+
+ // Create an instance of the preview and add it to the window
+ display = new Embedded("Color preview");
+ display.setWidth("270px");
+ display.setHeight("270px");
+
+ // Add the foreground and background colorpickers to a layout
+ HorizontalLayout mainLayout = new HorizontalLayout();
+ mainLayout.addStyleName("colorpicker-mainlayout");
+ mainLayout.setWidth("100%");
+ mainLayout.setHeight(null);
+ mainLayout.setMargin(true);
+ mainLayout.setSpacing(true);
+ getLayout().addComponent(mainLayout);
+
+ VerticalLayout layoutLeft = new VerticalLayout();
+ layoutLeft.setWidth("450px");
+ layoutLeft.setHeight(null);
+ layoutLeft.setSpacing(true);
+
+ GridLayout optLayout = new GridLayout(3, 2);
+ optLayout.setWidth("100%");
+ optLayout.setHeight(null);
+ optLayout.setMargin(true);
+ optLayout.setSpacing(true);
+
+ rgbBox.setValue(rgbVisible);
+ rgbBox.addValueChangeListener(new CheckBox.ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ rgbVisible = (Boolean) event.getProperty().getValue();
+ setPopupVisibilities();
+ }
+ });
+ rgbBox.setImmediate(true);
+ rgbBox.setId("rgbBox");
+ optLayout.addComponent(rgbBox);
+
+ hsvBox.setValue(hsvVisible);
+ hsvBox.addValueChangeListener(new CheckBox.ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ hsvVisible = (Boolean) event.getProperty().getValue();
+ setPopupVisibilities();
+ }
+ });
+ hsvBox.setImmediate(true);
+ hsvBox.setId("hsvBox");
+ optLayout.addComponent(hsvBox);
+
+ swaBox.setValue(swaVisible);
+ swaBox.addValueChangeListener(new CheckBox.ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ swaVisible = (Boolean) event.getProperty().getValue();
+ setPopupVisibilities();
+ }
+ });
+ swaBox.setImmediate(true);
+ swaBox.setId("swaBox");
+ optLayout.addComponent(swaBox);
+
+ hisBox.setValue(historyVisible);
+ hisBox.addValueChangeListener(new CheckBox.ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ historyVisible = (Boolean) event.getProperty().getValue();
+ setPopupVisibilities();
+ }
+ });
+ hisBox.setImmediate(true);
+ hisBox.setId("hisBox");
+ optLayout.addComponent(hisBox);
+
+ txtBox.setValue(txtfieldVisible);
+ txtBox.addValueChangeListener(new CheckBox.ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ txtfieldVisible = (Boolean) event.getProperty().getValue();
+ setPopupVisibilities();
+ }
+ });
+ txtBox.setImmediate(true);
+ txtBox.setId("txtBox");
+ optLayout.addComponent(txtBox);
+
+ Panel optPanel = new Panel("Customize the color picker popup window",
+ optLayout);
+ layoutLeft.addComponent(optPanel);
+
+ HorizontalLayout layout1 = createHorizontalLayout();
+
+ colorpicker1 = new ColorPicker("Foreground", foregroundColor);
+ colorpicker1.setHtmlContentAllowed(true);
+ colorpicker1.addColorChangeListener(this);
+ colorpicker1.setId("colorpicker1");
+ layout1.addComponent(colorpicker1);
+ layout1.setComponentAlignment(colorpicker1, Alignment.MIDDLE_CENTER);
+
+ colorpicker2 = new ColorPicker("Background", backgroundColor);
+ colorpicker2.addColorChangeListener(this);
+ colorpicker2.setId("colorpicker2");
+ layout1.addComponent(colorpicker2);
+ layout1.setComponentAlignment(colorpicker2, Alignment.MIDDLE_CENTER);
+
+ Panel panel1 = new Panel(
+ "Button-like colorpicker with current color and CSS code",
+ layout1);
+ layoutLeft.addComponent(panel1);
+
+ HorizontalLayout layout2 = createHorizontalLayout();
+
+ colorpicker3 = new ColorPicker("Foreground", foregroundColor);
+ colorpicker3.addColorChangeListener(this);
+ colorpicker3.setWidth("120px");
+ colorpicker3.setCaption("Foreground");
+ colorpicker3.setId("colorpicker3");
+ layout2.addComponent(colorpicker3);
+ layout2.setComponentAlignment(colorpicker3, Alignment.MIDDLE_CENTER);
+
+ colorpicker4 = new ColorPicker("Background", backgroundColor);
+ colorpicker4.addColorChangeListener(this);
+ colorpicker4.setWidth("120px");
+ colorpicker4.setCaption("Background");
+ colorpicker4.setId("colorpicker4");
+ layout2.addComponent(colorpicker4);
+ layout2.setComponentAlignment(colorpicker4, Alignment.MIDDLE_CENTER);
+
+ Panel panel2 = new Panel(
+ "Button-like colorpicker with current color and custom caption",
+ layout2);
+ layoutLeft.addComponent(panel2);
+
+ HorizontalLayout layout3 = createHorizontalLayout();
+
+ colorpicker5 = new ColorPickerArea("Foreground", foregroundColor);
+ colorpicker5.setCaption("Foreground");
+ colorpicker5.addColorChangeListener(this);
+ colorpicker5.setId("colorpicker5");
+ layout3.addComponent(colorpicker5);
+ layout3.setComponentAlignment(colorpicker5, Alignment.MIDDLE_CENTER);
+
+ colorpicker6 = new ColorPickerArea("Background", backgroundColor);
+ colorpicker6.setCaption("Background");
+ colorpicker6.setDefaultCaptionEnabled(false);
+ colorpicker6.addColorChangeListener(this);
+ colorpicker6.setId("colorpicker6");
+ layout3.addComponent(colorpicker6);
+ layout3.setComponentAlignment(colorpicker6, Alignment.MIDDLE_CENTER);
+
+ Panel panel3 = new Panel("Color area colorpicker with caption", layout3);
+ panel3.setWidth("100%");
+ panel3.setHeight(null);
+ layoutLeft.addComponent(panel3);
+
+ Label divider1 = new Label("<hr>", ContentMode.HTML);
+ layoutLeft.addComponent(divider1);
+
+ Label divider2 = new Label("<hr>", ContentMode.HTML);
+ layoutLeft.addComponent(divider2);
+
+ HorizontalLayout layout4 = createHorizontalLayout();
+
+ addShadeButton(new Color(Integer.parseInt("000000", 16)), layout4);
+ addShadeButton(new Color(Integer.parseInt("333333", 16)), layout4);
+ addShadeButton(new Color(Integer.parseInt("666666", 16)), layout4);
+ addShadeButton(new Color(Integer.parseInt("999999", 16)), layout4);
+ addShadeButton(new Color(Integer.parseInt("cccccc", 16)), layout4);
+ addShadeButton(new Color(Integer.parseInt("ffffff", 16)), layout4);
+
+ Panel panel4 = new Panel(
+ "Button-like colorpickers with disabled caption (no effect on fg/bg colors)",
+ layout4);
+ layoutLeft.addComponent(panel4);
+
+ HorizontalLayout layout5 = createHorizontalLayout();
+
+ addShadeArea(new Color(Integer.parseInt("000000", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("111111", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("222222", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("333333", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("444444", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("555555", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("666666", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("777777", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("888888", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("999999", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("aaaaaa", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("bbbbbb", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("cccccc", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("dddddd", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("eeeeee", 16)), layout5);
+ addShadeArea(new Color(Integer.parseInt("ffffff", 16)), layout5);
+
+ Panel panel5 = new Panel(
+ "Area colorpickers with no given caption (no effect on fg/bg colors)",
+ layout5);
+ layoutLeft.addComponent(panel5);
+
+ mainLayout.addComponent(layoutLeft);
+
+ mainLayout.addComponent(display);
+
+ updateDisplay(foregroundColor, backgroundColor);
+ }
+
+ private HorizontalLayout createHorizontalLayout() {
+ HorizontalLayout layout = new HorizontalLayout();
+ layout.setWidth("100%");
+ layout.setHeight(null);
+ layout.setMargin(true);
+ return layout;
+ }
+
+ private int shadeButtonCounter = 1;
+
+ private void addShadeButton(Color color, HorizontalLayout layout) {
+ AbstractColorPicker colorPicker = new ColorPicker(color.toString(),
+ color);
+ colorPicker.setDefaultCaptionEnabled(false);
+ colorPicker.setWidth("41px");
+ colorPicker.setId("shadebutton_" + shadeButtonCounter);
+ layout.addComponent(colorPicker);
+ layout.setComponentAlignment(colorPicker, Alignment.MIDDLE_CENTER);
+
+ ++shadeButtonCounter;
+ }
+
+ private int shadeAreaCounter = 1;
+
+ private void addShadeArea(Color color, HorizontalLayout layout) {
+ AbstractColorPicker colorPicker = new ColorPickerArea(color.toString(),
+ color);
+ colorPicker.setWidth("20px");
+ colorPicker.setHeight("20px");
+ colorPicker.setId("shadearea_" + shadeAreaCounter);
+ layout.addComponent(colorPicker);
+ layout.setComponentAlignment(colorPicker, Alignment.MIDDLE_CENTER);
+
+ ++shadeAreaCounter;
+ }
+
+ // This is called whenever a colorpicker popup is closed
+ /**
+ * Update display.
+ *
+ * @param fg
+ * the fg
+ * @param bg
+ * the bg
+ */
+ public void updateDisplay(Color fg, Color bg) {
+ java.awt.Color awtFg = new java.awt.Color(fg.getRed(), fg.getGreen(),
+ fg.getBlue());
+ java.awt.Color awtBg = new java.awt.Color(bg.getRed(), bg.getGreen(),
+ bg.getBlue());
+ StreamResource.StreamSource imagesource = new MyImageSource(awtFg,
+ awtBg);
+
+ Date now = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("hhmmss");
+
+ StreamResource imageresource = new StreamResource(imagesource,
+ "myimage" + format.format(now) + ".png");
+ imageresource.setCacheTime(0);
+
+ display.setSource(imageresource);
+ }
+
+ @Override
+ public void colorChanged(ColorChangeEvent event) {
+ if (event.getSource() == colorpicker1
+ || event.getSource() == colorpicker3
+ || event.getSource() == colorpicker5) {
+ foregroundColor = event.getColor();
+
+ if (event.getSource() != colorpicker1) {
+ colorpicker1.setColor(event.getColor());
+ }
+ if (event.getSource() != colorpicker3) {
+ colorpicker3.setColor(event.getColor());
+ }
+ if (event.getSource() != colorpicker5) {
+ colorpicker5.setColor(event.getColor());
+ }
+
+ } else if (event.getSource() == colorpicker2
+ || event.getSource() == colorpicker4
+ || event.getSource() == colorpicker6) {
+ backgroundColor = event.getColor();
+
+ if (event.getSource() != colorpicker2) {
+ colorpicker2.setColor(event.getColor());
+ }
+ if (event.getSource() != colorpicker4) {
+ colorpicker4.setColor(event.getColor());
+ }
+ if (event.getSource() != colorpicker6) {
+ colorpicker6.setColor(event.getColor());
+ }
+
+ } else {
+ return;
+ }
+
+ updateDisplay(foregroundColor, backgroundColor);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/customfield/AddressField.java b/uitest/src/com/vaadin/tests/components/customfield/AddressField.java
index 2daeb7bf25..595a2e2cde 100644
--- a/uitest/src/com/vaadin/tests/components/customfield/AddressField.java
+++ b/uitest/src/com/vaadin/tests/components/customfield/AddressField.java
@@ -38,7 +38,7 @@ public class AddressField extends CustomField<Address> {
// make sure field changes are sent early
addressForm.setImmediate(true);
-
+ addressForm.setFooter(null);
return addressForm;
}
diff --git a/uitest/src/com/vaadin/tests/components/uitest/reindeer_theme_test.html b/uitest/src/com/vaadin/tests/components/uitest/reindeer_theme_test.html
index 3c2d97ec17..e764d62b12 100644
--- a/uitest/src/com/vaadin/tests/components/uitest/reindeer_theme_test.html
+++ b/uitest/src/com/vaadin/tests/components/uitest/reindeer_theme_test.html
@@ -129,7 +129,7 @@
<tr>
<td>screenCapture</td>
<td></td>
- <td>selects-first-popup</td>
+ <td>selects-first-open</td>
</tr>
<tr>
<td>mouseClick</td>
@@ -139,7 +139,7 @@
<tr>
<td>screenCapture</td>
<td></td>
- <td>selects-second-popup</td>
+ <td>selects-second-open</td>
</tr>
<tr>
<td>mouseClick</td>
@@ -149,7 +149,7 @@
<tr>
<td>screenCapture</td>
<td></td>
- <td>selects-third-popup</td>
+ <td>selects-third-open</td>
</tr>
<tr>
<td>mouseClick</td>
@@ -159,7 +159,7 @@
<tr>
<td>screenCapture</td>
<td></td>
- <td>selects-fourth-popup</td>
+ <td>selects-fourth-open</td>
</tr>
<tr>
<td>mouseClick</td>