diff options
author | Anna Koskinen <anna@vaadin.com> | 2012-11-27 10:33:53 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2012-12-10 13:11:13 +0000 |
commit | 97834440254dcb03ed267fbf5f453f4dc435a291 (patch) | |
tree | 69ce018cfdec938dcc01d1bf1cfe5dff06bff8f8 | |
parent | d2b69dbee663bc2607a9d268e4c751e9dbdc53a5 (diff) | |
download | vaadin-framework-97834440254dcb03ed267fbf5f453f4dc435a291.tar.gz vaadin-framework-97834440254dcb03ed267fbf5f453f4dc435a291.zip |
Vaadin 7 compatible ColorPicker (#9201)
Change-Id: I44962ceedd5ef607e2fbe2af0d96808e0aef9cc5
46 files changed, 4909 insertions, 1 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 Binary files differnew file mode 100644 index 0000000000..def063a8ab --- /dev/null +++ b/WebContent/VAADIN/themes/base/colorpicker/images/gradient.png diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png b/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png Binary files differnew file mode 100644 index 0000000000..f51ed752a7 --- /dev/null +++ b/WebContent/VAADIN/themes/base/colorpicker/images/gradient2.png diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png Binary files differnew file mode 100644 index 0000000000..6e56ec0cc7 --- /dev/null +++ b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg-selected.png diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png Binary files differnew file mode 100644 index 0000000000..b6e3532713 --- /dev/null +++ b/WebContent/VAADIN/themes/base/colorpicker/images/resizebg.png diff --git a/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png b/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png Binary files differnew file mode 100644 index 0000000000..bcef2c5575 --- /dev/null +++ b/WebContent/VAADIN/themes/base/colorpicker/images/slider_hue_bg.png 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/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/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/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/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/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); + } +} |