* ColorTextField, helper methods, and regex for validating and handling text input * Refactored structure to avoid creating new component for validation * Style to adapt to error indicator * Tests for validating input in ColorPickerPreview component's TextField * Merge branch 'master' into colorpicker_validation * Fix path to server class * Fix test: Submit the new value * Fix test: ignore Phantom JS * Fix hsl+hsla validation patterns to accept '%', test value tweaking * Merge branch 'master' of github.com:vaadin/framework into colorpicker_validation * Fix: remove warning when color is updated from elsewhere * Revisions: input validation only once, Logging level WARN * Revisions: unit tests for color pattern matching * Revisions: moved parsing to utility class, tests for parsing all accepted input formats * Fixed import in tests, comments * Revisions: Logger as constant, ignore utility class in serialization test * Corner case tests * Revisions: protected method for parsing error text, fix to test * Revisions: NPE fixtags/8.5.0.alpha1
package com.vaadin.ui.components.colorpicker; | package com.vaadin.ui.components.colorpicker; | ||||
import java.util.Objects; | import java.util.Objects; | ||||
import java.util.logging.Level; | |||||
import java.util.logging.Logger; | |||||
import com.vaadin.data.HasValue; | import com.vaadin.data.HasValue; | ||||
import com.vaadin.server.AbstractErrorMessage.ContentMode; | |||||
import com.vaadin.server.ErrorMessage; | |||||
import com.vaadin.server.UserError; | |||||
import com.vaadin.shared.Registration; | import com.vaadin.shared.Registration; | ||||
import com.vaadin.shared.ui.ErrorLevel; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | import com.vaadin.shared.ui.colorpicker.Color; | ||||
import com.vaadin.ui.Component; | import com.vaadin.ui.Component; | ||||
import com.vaadin.ui.CssLayout; | import com.vaadin.ui.CssLayout; | ||||
* @since 7.0.0 | * @since 7.0.0 | ||||
*/ | */ | ||||
public class ColorPickerPreview extends CssLayout implements HasValue<Color> { | public class ColorPickerPreview extends CssLayout implements HasValue<Color> { | ||||
private static final Logger LOGGER = Logger | |||||
.getLogger(ColorPickerPreview.class.getName()); | |||||
private static final String STYLE_DARK_COLOR = "v-textfield-dark"; | private static final String STYLE_DARK_COLOR = "v-textfield-dark"; | ||||
private static final String STYLE_LIGHT_COLOR = "v-textfield-light"; | private static final String STYLE_LIGHT_COLOR = "v-textfield-light"; | ||||
String colorCSS = color.getCSS(); | String colorCSS = color.getCSS(); | ||||
field.setValue(colorCSS); | field.setValue(colorCSS); | ||||
field.setComponentError(null); | |||||
oldValue = colorCSS; | oldValue = colorCSS; | ||||
} | } | ||||
private void valueChange(ValueChangeEvent<String> event) { | private void valueChange(ValueChangeEvent<String> event) { | ||||
ErrorMessage errorMessage = null; | |||||
String value = event.getValue(); | String value = event.getValue(); | ||||
value = Objects.toString(value, "").trim(); | |||||
Color oldColor = color; | Color oldColor = color; | ||||
try { | try { | ||||
if (value != null) { | |||||
/* | |||||
* Description of supported formats see | |||||
* http://www.w3schools.com/cssref/css_colors_legal.asp | |||||
*/ | |||||
if (value.length() == 7 && value.startsWith("#")) { | |||||
// CSS color format (e.g. #000000) | |||||
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); | |||||
} else if (value.startsWith("rgb")) { | |||||
// RGB color format rgb/rgba(255,255,255,0.1) | |||||
String[] colors = value.substring(value.indexOf('(') + 1, | |||||
value.length() - 1).split(","); | |||||
int red = Integer.parseInt(colors[0]); | |||||
int green = Integer.parseInt(colors[1]); | |||||
int blue = Integer.parseInt(colors[2]); | |||||
if (colors.length > 3) { | |||||
int alpha = (int) (Double.parseDouble(colors[3]) | |||||
* 255d); | |||||
color = new Color(red, green, blue, alpha); | |||||
} else { | |||||
color = new Color(red, green, blue); | |||||
} | |||||
} else if (value.startsWith("hsl")) { | |||||
// HSL color format hsl/hsla(100,50%,50%,1.0) | |||||
String[] colors = value.substring(value.indexOf('(') + 1, | |||||
value.length() - 1).split(","); | |||||
int hue = Integer.parseInt(colors[0]); | |||||
int saturation = Integer | |||||
.parseInt(colors[1].replace("%", "")); | |||||
int lightness = Integer | |||||
.parseInt(colors[2].replace("%", "")); | |||||
int rgb = Color.HSLtoRGB(hue, saturation, lightness); | |||||
if (colors.length > 3) { | |||||
int alpha = (int) (Double.parseDouble(colors[3]) | |||||
* 255d); | |||||
color = new Color(rgb); | |||||
color.setAlpha(alpha); | |||||
} else { | |||||
color = new Color(rgb); | |||||
} | |||||
} | |||||
oldValue = value; | |||||
fireEvent(new ValueChangeEvent<>(this, oldColor, | |||||
event.isUserOriginated())); | |||||
} | |||||
} catch (NumberFormatException nfe) { | |||||
// Revert value | |||||
field.setValue(oldValue); | |||||
/* | |||||
* Description of supported formats see | |||||
* http://www.w3schools.com/cssref/css_colors_legal.asp | |||||
*/ | |||||
color = ColorUtil.stringToColor(value); | |||||
oldValue = value; | |||||
fireEvent(new ValueChangeEvent<>(this, oldColor, | |||||
event.isUserOriginated())); | |||||
} catch (NumberFormatException e) { | |||||
// Pattern matching ensures the validity of | |||||
// the input, this should never happen | |||||
LOGGER.log(Level.INFO, e.getMessage()); | |||||
errorMessage = new UserError(getUserErrorText(value), | |||||
ContentMode.TEXT, ErrorLevel.WARNING); | |||||
} | } | ||||
field.setComponentError(errorMessage); | |||||
} | } | ||||
@Override | @Override | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | |||||
/** | |||||
* Get the client error message text for color input parsing error. | |||||
* | |||||
* @param value | |||||
* input which caused the error | |||||
* @return error message text | |||||
*/ | |||||
protected String getUserErrorText(String value) { | |||||
return value.isEmpty() ? "Input cannot be empty" | |||||
: "Input '".concat(value) | |||||
.concat("' is not in any recognized format"); | |||||
} | |||||
} |
/* | |||||
* Copyright 2000-2018 Vaadin Ltd. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||||
* use this file except in compliance with the License. You may obtain a copy of | |||||
* the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||||
* License for the specific language governing permissions and limitations under | |||||
* the License. | |||||
*/ | |||||
package com.vaadin.ui.components.colorpicker; | |||||
import java.util.regex.Matcher; | |||||
import java.util.regex.Pattern; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
/** | |||||
* Utility class for matching and parsing {@link Color} objects from | |||||
* {@code String} input. | |||||
* | |||||
* Description of supported formats see | |||||
* http://www.w3schools.com/cssref/css_colors_legal.asp | |||||
* | |||||
* @since | |||||
*/ | |||||
public class ColorUtil { | |||||
private ColorUtil() { | |||||
} | |||||
/** | |||||
* Parses {@link Color} from any of the following {@link String} inputs: | |||||
* <br> | |||||
* - RGB hex (e.g. "#FFAA00"), {@link #HEX_PATTERN}<br> | |||||
* - RGB "function" (e.g. "rgb(128,0,255)"), {@link #RGB_PATTERN}<br> | |||||
* - RGBA "function" (e.g. "rgba(50,50,50,0.2)"), {@link #RGBA_PATTERN}<br> | |||||
* - HSL "function" (e.g. "hsl(50,50,50)"), {@link #HSL_PATTERN}<br> | |||||
* - HSLA "function" (e.g. "hsl(50,50,50,0.2)"), {@link #HSLA_PATTERN} | |||||
* <p> | |||||
* Parsing is case-insensitive. | |||||
* | |||||
* @param input | |||||
* String input | |||||
* @return {@link Color} parsed from input | |||||
* @throws NumberFormatException | |||||
* Input does not match any recognized pattern | |||||
*/ | |||||
public static Color stringToColor(String input) { | |||||
Matcher m = HEX_PATTERN.matcher(input); | |||||
if (m.matches()) { | |||||
return getHexPatternColor(m); | |||||
} | |||||
m = RGB_PATTERN.matcher(input); | |||||
if (m.matches()) { | |||||
return getRGBPatternColor(m); | |||||
} | |||||
m = RGBA_PATTERN.matcher(input); | |||||
if (m.matches()) { | |||||
return getRGBAPatternColor(m); | |||||
} | |||||
m = HSL_PATTERN.matcher(input); | |||||
if (m.matches()) { | |||||
return getHSLPatternColor(m); | |||||
} | |||||
m = HSLA_PATTERN.matcher(input); | |||||
if (m.matches()) { | |||||
return getHSLAPatternColor(m); | |||||
} | |||||
throw new NumberFormatException("Parsing color from input failed."); | |||||
} | |||||
/** | |||||
* Parses {@link Color} from matched hexadecimal {@link Matcher}. | |||||
* | |||||
* @param matcher | |||||
* {@link Matcher} matching hexadecimal pattern with named regex | |||||
* groups {@code red}, {@code green}, and {@code blue} | |||||
* @return {@link Color} parsed from {@link Matcher} | |||||
*/ | |||||
public static Color getHexPatternColor(Matcher matcher) { | |||||
int red = Integer.parseInt(matcher.group("red"), 16); | |||||
int green = Integer.parseInt(matcher.group("green"), 16); | |||||
int blue = Integer.parseInt(matcher.group("blue"), 16); | |||||
return new Color(red, green, blue); | |||||
} | |||||
/** | |||||
* Parses {@link Color} from matched RGB {@link Matcher}. | |||||
* | |||||
* @param matcher | |||||
* {@link Matcher} matching RGB pattern with named regex groups | |||||
* {@code red}, {@code green}, and {@code blue} | |||||
* @return {@link Color} parsed from {@link Matcher} | |||||
*/ | |||||
public static Color getRGBPatternColor(Matcher matcher) { | |||||
int red = Integer.parseInt(matcher.group("red")); | |||||
int green = Integer.parseInt(matcher.group("green")); | |||||
int blue = Integer.parseInt(matcher.group("blue")); | |||||
return new Color(red, green, blue); | |||||
} | |||||
/** | |||||
* Parses {@link Color} from matched RGBA {@link Matcher}. | |||||
* | |||||
* @param matcher | |||||
* {@link Matcher} matching RGBA pattern with named regex groups | |||||
* {@code red}, {@code green}, {@code blue}, and {@code alpha} | |||||
* @return {@link Color} parsed from {@link Matcher} | |||||
*/ | |||||
public static Color getRGBAPatternColor(Matcher matcher) { | |||||
Color c = getRGBPatternColor(matcher); | |||||
c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d)); | |||||
return c; | |||||
} | |||||
/** | |||||
* Parses {@link Color} from matched HSL {@link Matcher}. | |||||
* | |||||
* @param matcher | |||||
* {@link Matcher} matching HSL pattern with named regex groups | |||||
* {@code hue}, {@code saturation}, and {@code light} | |||||
* @return {@link Color} parsed from {@link Matcher} | |||||
*/ | |||||
public static Color getHSLPatternColor(Matcher matcher) { | |||||
int hue = Integer.parseInt(matcher.group("hue")); | |||||
int saturation = Integer.parseInt(matcher.group("saturation")); | |||||
int light = Integer.parseInt(matcher.group("light")); | |||||
int rgb = Color.HSLtoRGB(hue, saturation, light); | |||||
return new Color(rgb); | |||||
} | |||||
/** | |||||
* Parses {@link Color} from matched HSLA {@link Matcher}. | |||||
* | |||||
* @param matcher | |||||
* {@link Matcher} matching HSLA pattern with named regex groups | |||||
* {@code hue}, {@code saturation}, {@code light}, and | |||||
* {@code alpha} | |||||
* @return {@link Color} parsed from {@link Matcher} | |||||
*/ | |||||
public static Color getHSLAPatternColor(Matcher matcher) { | |||||
Color c = getHSLPatternColor(matcher); | |||||
c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d)); | |||||
return c; | |||||
} | |||||
/** | |||||
* Case-insensitive {@link Pattern} with regular expression matching the | |||||
* default hexadecimal color presentation pattern:<br> | |||||
* '#' followed by six <code>[\da-fA-F]</code> characters. | |||||
* <p> | |||||
* Pattern contains named groups <code>red</code>, <code>green</code>, and | |||||
* <code>blue</code>, which represent the individual values. | |||||
*/ | |||||
public static final Pattern HEX_PATTERN = Pattern.compile( | |||||
"(?i)^#\\s*(?<red>[\\da-f]{2})(?<green>[\\da-f]{2})(?<blue>[\\da-f]{2}" | |||||
+ ")\\s*$"); | |||||
/** | |||||
* Case-insensitive {@link Pattern} with regular expression matching common | |||||
* RGB color presentation patterns:<br> | |||||
* 'rgb' followed by three [0-255] number values. Values can be separated | |||||
* with either comma or whitespace. | |||||
* <p> | |||||
* Pattern contains named groups <code>red</code>, <code>green</code>, and | |||||
* <code>blue</code>, which represent the individual values. | |||||
*/ | |||||
public static final Pattern RGB_PATTERN = Pattern.compile( | |||||
"(?i)^rgb\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|\\" | |||||
+ "s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s*[," | |||||
+ "+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\" | |||||
+ ")$"); | |||||
/** | |||||
* Case-insensitive {@link Pattern} with regular expression matching common | |||||
* RGBA presentation patterns:<br> | |||||
* 'rgba' followed by three [0-255] values and one [0.0-1.0] value. Values | |||||
* can be separated with either comma or whitespace. The only accepted | |||||
* decimal marker is point ('.'). | |||||
* <p> | |||||
* Pattern contains named groups <code>red</code>, <code>green</code>, | |||||
* <code>blue</code>, and <code>alpha</code>, which represent the individual | |||||
* values. | |||||
*/ | |||||
public static final Pattern RGBA_PATTERN = Pattern.compile( | |||||
"(?i)^rgba\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|" | |||||
+ "\\s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s" | |||||
+ "*[,+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?" | |||||
+ ":\\s*[,+|\\s+]\\s*)(?<alpha>0(?:\\.\\d{1,2})?|0?(?:\\.\\" | |||||
+ "d{1,2})|1(?:\\.0{1,2})?)\\s*\\)$"); | |||||
/** | |||||
* Case-insensitive {@link Pattern} with regular expression matching common | |||||
* HSL presentation patterns:<br> | |||||
* 'hsl' followed by one [0-360] value and two [0-100] percentage value. | |||||
* Values can be separated with either comma or whitespace. The percent sign | |||||
* ('%') is optional. | |||||
* <p> | |||||
* Pattern contains named groups <code>hue</code>,<code>saturation</code>, | |||||
* and <code>light</code>, which represent the individual values. | |||||
*/ | |||||
public static final Pattern HSL_PATTERN = Pattern.compile( | |||||
"(?i)hsl\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+]" | |||||
+ "\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\" | |||||
+ "s*)(?<light>\\d{1,2}|100)(?:\\s*%?\\s*)\\)$"); | |||||
/** | |||||
* Case-insensitive {@link Pattern} with regular expression matching common | |||||
* HSLA presentation patterns:<br> | |||||
* 'hsla' followed by one [0-360] value, two [0-100] percentage values, and | |||||
* one [0.0-1.0] value. Values can be separated with either comma or | |||||
* whitespace. The percent sign ('%') is optional. The only accepted decimal | |||||
* marker is point ('.'). | |||||
* <p> | |||||
* Pattern contains named groups <code>hue</code>,<code>saturation</code>, | |||||
* <code>light</code>, and <code>alpha</code>, which represent the | |||||
* individual values. | |||||
*/ | |||||
public static final Pattern HSLA_PATTERN = Pattern.compile( | |||||
"(?i)hsla\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+" | |||||
+ "]\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\s*" | |||||
+ ")(?<light>\\d{1,2}|100)(?:\\s*%?[,+|\\s+]\\s*)(?<alpha>" | |||||
+ "0(?:\\.\\d{1,2})?|0?(?:\\.\\d{1,2})|1(?:\\.0{1,2})?)" | |||||
+ "\\s*\\)$"); | |||||
} |
"com\\.vaadin\\.server\\.JsonCodec\\$1", // | "com\\.vaadin\\.server\\.JsonCodec\\$1", // | ||||
"com\\.vaadin\\.server\\.communication\\.PushConnection", // | "com\\.vaadin\\.server\\.communication\\.PushConnection", // | ||||
"com\\.vaadin\\.server\\.communication\\.AtmospherePushConnection.*", // | "com\\.vaadin\\.server\\.communication\\.AtmospherePushConnection.*", // | ||||
"com\\.vaadin\\.ui\\.components\\.colorpicker\\.ColorUtil", // | |||||
"com\\.vaadin\\.util\\.ConnectorHelper", // | "com\\.vaadin\\.util\\.ConnectorHelper", // | ||||
"com\\.vaadin\\.server\\.VaadinSession\\$FutureAccess", // | "com\\.vaadin\\.server\\.VaadinSession\\$FutureAccess", // | ||||
"com\\.vaadin\\.external\\..*", // | "com\\.vaadin\\.external\\..*", // |
package com.vaadin.tests.server.component.colorpicker; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import java.util.regex.Matcher; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.junit.runners.Parameterized; | |||||
import org.junit.runners.Parameterized.Parameter; | |||||
import org.junit.runners.Parameterized.Parameters; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.ui.components.colorpicker.ColorUtil; | |||||
@RunWith(value = Parameterized.class) | |||||
public class HSLAPatternParsingTest { | |||||
@Parameter(value = 0) | |||||
public String input; | |||||
@Parameter(value = 1) | |||||
public int expectedHue; | |||||
@Parameter(value = 2) | |||||
public int expectedSaturation; | |||||
@Parameter(value = 3) | |||||
public int expectedLight; | |||||
@Parameter(value = 4) | |||||
public int expectedAlpha; | |||||
@Parameter(value = 5) | |||||
public boolean expectedMatches; | |||||
@Parameters(name = "{index}: testHSLAData({0}) = ({1},{2},{3},{4},{5})") | |||||
public static Collection<Object[]> hsladata() { | |||||
Object[][] validValues = { { "hsla(0,0,0,0)", 0, 0, 0, 0, true }, | |||||
{ "HSLA(0, 0, 0, 0)", 0, 0, 0, 0, true }, | |||||
{ "hsla(0,0%,0%, 0.1)", 0, 0, 0, 25, true }, | |||||
{ "hsla(0 0 0 0.00 )", 0, 0, 0, 0, true }, | |||||
{ "hsla(0 0% 0% 0.50)", 0, 0, 0, 127, true }, | |||||
{ "hsla(360,100,100,1.0)", 360, 100, 100, 255, true }, | |||||
{ "hsla(360, 100, 100, 1.0)", 360, 100, 100, 255, true }, | |||||
{ "hsla(360, 100%, 100%, 1.00)", 360, 100, 100, 255, true }, | |||||
{ "hsla(360 100% 100% 1.00)", 360, 100, 100, 255, true }, | |||||
{ "hsla(20, 10, 10, 0.24)", 20, 10, 10, 61, true }, | |||||
{ "hsla(100, 0, 50, 0.8)", 100, 0, 50, 204, true }, | |||||
{ "hsla(269, 50, 0, .6)", 269, 50, 0, 153, true }, }; | |||||
Object[][] invalidValues = { { "hsla(361,0,0,0)", 0, 0, 0, 0, false }, | |||||
{ "hsla(0.0, 0, 0, 0)", 0, 0, 0, 0, false }, | |||||
{ "hsla(0,0%,0%, 1.1)", 0, 0, 0, 0, false }, | |||||
{ "hsla(0 0 0 0.009 )", 0, 0, 0, 0, false }, | |||||
{ "hsla(0 0% -100% 0.50)", 0, 0, 0, 0, false }, | |||||
{ "hsla(360,1000,100,1.0)", 0, 0, 0, 0, false }, | |||||
{ "hsla(0, 100, 100, 2.0)", 0, 0, 0, 0, false }, | |||||
{ "hsla(360, 100%, 100%, 10.00)", 0, 0, 0, 0, false }, | |||||
{ "hsl a(360 100% 100% 1.)", 0, 0, 0, 0, false }, | |||||
{ "hsla(20, -10, 10, 0.24)", 0, 0, 0, 0, false }, | |||||
{ "hsla(400, 0, 50, 0.8)", 0, 0, 0, 0, false }, | |||||
{ "hsla(200, 50, 0, 0.996)", 0, 0, 0, 0, false }, | |||||
{ "hsla 200, 50, 0, 0.9", 0, 0, 0, 0, false }, | |||||
{ "hsla(0,0,0,0.)", 0, 0, 0, 0, false } }; | |||||
ArrayList<Object[]> values = new ArrayList<>(); | |||||
Collections.addAll(values, validValues); | |||||
Collections.addAll(values, invalidValues); | |||||
return values; | |||||
} | |||||
@Test | |||||
public void testHSLAData() { | |||||
Matcher m = ColorUtil.HSLA_PATTERN.matcher(input); | |||||
boolean matches = m.matches(); | |||||
if (expectedMatches) { | |||||
Color expectedColor = new Color(Color.HSLtoRGB(expectedHue, | |||||
expectedSaturation, expectedLight)); | |||||
expectedColor.setAlpha(expectedAlpha); | |||||
Color c1 = ColorUtil.getHSLAPatternColor(m); | |||||
assertTrue(expectedColor.equals(c1)); | |||||
} else { | |||||
assertTrue(!matches); | |||||
} | |||||
} | |||||
} |
package com.vaadin.tests.server.component.colorpicker; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import java.util.regex.Matcher; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.junit.runners.Parameterized; | |||||
import org.junit.runners.Parameterized.Parameter; | |||||
import org.junit.runners.Parameterized.Parameters; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.ui.components.colorpicker.ColorUtil; | |||||
@RunWith(value = Parameterized.class) | |||||
public class HSLPatternParsingTest { | |||||
@Parameter(value = 0) | |||||
public String input; | |||||
@Parameter(value = 1) | |||||
public Color expectedColor; | |||||
@Parameter(value = 2) | |||||
public boolean expectedMatches; | |||||
@Parameters(name = "{index}: testHSLData({0}) = ({1},{2})") | |||||
public static Collection<Object[]> hsldata() { | |||||
Object[][] validValues = { | |||||
{ "hsl(0,0,0)", new Color(Color.HSLtoRGB(0, 0, 0)), true }, | |||||
{ "hsl(0, 0, 0)", new Color(Color.HSLtoRGB(0, 0, 0)), true }, | |||||
{ "hsl(0,0%,0% )", new Color(Color.HSLtoRGB(0, 0, 0)), true }, | |||||
{ "hsl(0 0 0)", new Color(Color.HSLtoRGB(0, 0, 0)), true }, | |||||
{ "hsl(0 0% 0%)", new Color(Color.HSLtoRGB(0, 0, 0)), true }, | |||||
{ "hsl(360,100,100)", new Color(Color.HSLtoRGB(360, 100, 100)), | |||||
true }, | |||||
{ "hsl(360, 100, 100)", | |||||
new Color(Color.HSLtoRGB(360, 100, 100)), true }, | |||||
{ "hsl(360, 100%, 100%)", | |||||
new Color(Color.HSLtoRGB(360, 100, 100)), true }, | |||||
{ "hsl(360 100% 100%)", | |||||
new Color(Color.HSLtoRGB(360, 100, 100)), true }, | |||||
{ "hsl(20, 10, 10)", new Color(Color.HSLtoRGB(20, 10, 10)), | |||||
true }, | |||||
{ "hsl(100, 0, 50)", new Color(Color.HSLtoRGB(100, 0, 50)), | |||||
true }, | |||||
{ "hsl(200, 50, 0)", new Color(Color.HSLtoRGB(200, 50, 0)), | |||||
true }, | |||||
{ "hsl(200, 50, 05)", new Color(Color.HSLtoRGB(200, 50, 5)), | |||||
true } }; | |||||
Object[][] invalidValues = { { "hsl(361,0,0)", null, false }, | |||||
{ "hsl(-0, 0, 0)", null, false }, | |||||
{ "hsl (100%,0%,0% )", null, false }, | |||||
{ "hsl(0 101 0)", null, false }, | |||||
{ "hsl(0 0% -99%)", null, false }, | |||||
{ "hsl(360,100,10 0)", null, false }, | |||||
{ "hsl(360, 100, 101)", null, false }, | |||||
{ "hsl(360, 110%, 100%)", null, false }, | |||||
{ "hsl(3600 100% 100%)", null, false }, | |||||
{ "hs l(420, 10, 10)", null, false }, | |||||
{ "hsl(100, 0, 5,0)", null, false }, | |||||
{ "hsla(200, 50, 0)", null, false }, | |||||
{ "hsl(0,0,0", null, false }, { "rgb\\(\\.*", null, false }, | |||||
{ "hsl(\\.*)", null, false }, { "#\\d.*", null, false }, | |||||
{ "", null, false } }; | |||||
ArrayList<Object[]> values = new ArrayList<>(); | |||||
Collections.addAll(values, validValues); | |||||
Collections.addAll(values, invalidValues); | |||||
return values; | |||||
} | |||||
@Test | |||||
public void testHSLData() { | |||||
Matcher m = ColorUtil.HSL_PATTERN.matcher(input); | |||||
boolean matches = m.matches(); | |||||
if (expectedMatches) { | |||||
Color c1 = ColorUtil.getHSLPatternColor(m); | |||||
assertTrue(expectedColor.equals(c1)); | |||||
} else { | |||||
assertTrue(!matches); | |||||
} | |||||
} | |||||
} |
package com.vaadin.tests.server.component.colorpicker; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import java.util.regex.Matcher; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.junit.runners.Parameterized; | |||||
import org.junit.runners.Parameterized.Parameter; | |||||
import org.junit.runners.Parameterized.Parameters; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.ui.components.colorpicker.ColorUtil; | |||||
@RunWith(value = Parameterized.class) | |||||
public class HexPatternParsingTest { | |||||
@Parameter(value = 0) | |||||
public String input; | |||||
@Parameter(value = 1) | |||||
public int expectedRed; | |||||
@Parameter(value = 2) | |||||
public int expectedGreen; | |||||
@Parameter(value = 3) | |||||
public int expectedBlue; | |||||
@Parameter(value = 4) | |||||
public boolean expectedMatches; | |||||
@Parameters(name = "{index}: textValidHEX({0}) = ({1},{2},{3},{4})") | |||||
public static Collection<Object[]> hexdata() { | |||||
Object[][] validValues = { { "#000000", 0, 0, 0, true }, | |||||
{ "#ffffff", 255, 255, 255, true }, | |||||
{ "#FF00ff", 255, 0, 255, true }, { "#aa90e3",170,144,227, true }, | |||||
{ "#016953", 1, 105, 83, true }, | |||||
{ "#bC64D0", 188, 100, 208, true }, | |||||
{ "#F100FF", 241, 0, 255, true }, | |||||
{ "#F0E9a5", 240, 233, 165, true }, | |||||
{ "#990077", 153, 0, 119, true } }; | |||||
Object[][] invalidValues = { { "#0000000", 0, 0, 0, false }, | |||||
{ "#ffgfff", 0, 0, 0, false }, { "#FF10f", 0, 0, 0, false }, | |||||
{ "#aa9", 0, 0, 0, false }, { "#03", 0, 0, 0, false }, | |||||
{ "#aab3c4c", 0, 0, 0, false }, { "#6010", 0, 0, 0, false }, | |||||
{ "#CCCC", 0, 0, 0, false }, { "#9", 0, 0, 0, false }, | |||||
{ "#10 10 10", 0, 0, 0, false }, { "101010", 0, 0, 0, false }, | |||||
{ "#10101q", 0, 0, 0, false }, | |||||
{ "\\s%\\d[0-9]", 0, 0, 0, false }, | |||||
{ "#\\d.*", 0, 0, 0, false }, { "rgb\\(\\.*", 0, 0, 0, false }, | |||||
{ "#\\d\\d\\d", 0, 0, 0, false }, { "#\\d.*", 0, 0, 0, false }, | |||||
{ "", 0, 0, 0, false }, { "hsl(25,25,25)", 0, 0, 0, false } }; | |||||
ArrayList<Object[]> values = new ArrayList<>(); | |||||
Collections.addAll(values, validValues); | |||||
Collections.addAll(values, invalidValues); | |||||
return values; | |||||
} | |||||
@Test | |||||
public void testValidHEX() { | |||||
Matcher m = ColorUtil.HEX_PATTERN.matcher(input); | |||||
boolean matches = m.matches(); | |||||
if (expectedMatches) { | |||||
Color c = new Color(expectedRed, expectedGreen, expectedBlue); | |||||
Color c1 = ColorUtil.getHexPatternColor(m); | |||||
assertTrue(c.equals(c1)); | |||||
} else { | |||||
assertTrue(!matches); | |||||
} | |||||
} | |||||
} |
package com.vaadin.tests.server.component.colorpicker; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import java.util.regex.Matcher; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.junit.runners.Parameterized; | |||||
import org.junit.runners.Parameterized.Parameter; | |||||
import org.junit.runners.Parameterized.Parameters; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.ui.components.colorpicker.ColorUtil; | |||||
@RunWith(value = Parameterized.class) | |||||
public class RGBAPatternParsingTest { | |||||
@Parameter(value = 0) | |||||
public String input; | |||||
@Parameter(value = 1) | |||||
public int expectedRed; | |||||
@Parameter(value = 2) | |||||
public int expectedGreen; | |||||
@Parameter(value = 3) | |||||
public int expectedBlue; | |||||
@Parameter(value = 4) | |||||
public int expectedAlpha; | |||||
@Parameter(value = 5) | |||||
public boolean expectedMatches; | |||||
@Parameters(name = "{index}: testRGBAData({0}) = ({1},{2},{3},{4},{5})") | |||||
public static Collection<Object[]> rgbdata() { | |||||
Object[][] validValues = { { "rgba(0,0,0,0)", 0, 0, 0, 0, true }, | |||||
{ "RGBA(0, 0, 0, 0 )", 0, 0, 0, 0, true }, | |||||
{ "rgba(0 0 0 0.00)", 0, 0, 0, 0, true }, | |||||
{ "rgba(1 1 1 1.00)", 1, 1, 1, 255, true }, | |||||
{ "rgba(0 100 200 0.50)", 0, 100, 200, 127, true }, | |||||
{ "rgba(255,255,255,1.0)", 255, 255, 255, 255, true }, | |||||
{ "rgba(255, 255, 255, 1.0)", 255, 255, 255, 255, true }, | |||||
{ "rgba(255 255 255 0)", 255, 255, 255, 0, true }, | |||||
{ "rgba(1, 10, 100, 0.00)", 1, 10, 100, 0, true } }; | |||||
Object[][] invalidValues = { { "rgba(256,0,0,0)", 0, 0, 0, 0, false }, | |||||
{ "rgba(0, 256, 0, -0 )", 0, 0, 0, 0, false }, | |||||
{ "rgba(0,0,10.0, 00)", 0, 0, 0, 0, false }, | |||||
{ "rgba(0 0 0 2.00)", 0, 0, 0, 0, false }, | |||||
{ "rgba(0 -99 0 0.50)", 0, 0, 0, 0, false }, | |||||
{ "rgba(0,255%,255,1.0)", 0, 0, 0, 0, false }, | |||||
{ "rgba(255, 255, 255, 1.05)", 0, 0, 0, 0, false }, | |||||
{ "rgba(255, 255, 255, 1.50)", 0, 0, 0, 0, false }, | |||||
{ "rgb a(255 255 0.005)", 0, 0, 0, 0, false }, | |||||
{ "rgba(163, 256, 1000, 0.24)", 0, 0, 0, 0, false }, | |||||
{ "rgba(100, 0.5, 250, 0.8)", 0, 0, 0, 0, false }, | |||||
{ "rgba(, 50, 0, 0.6)", 0, 0, 0, 0, false }, | |||||
{ "rgba(200, 50, 0, 10.6)", 0, 0, 0, 0, false }, | |||||
{ "rgba 200, 50, 0, 1.", 0, 0, 0, 0, false }, | |||||
{ "rgba(0,0,0,0.)", 0, 0, 0, 0, false }, | |||||
{ "rgb(200, 50, 0)", 0, 0, 0, 0, false }, | |||||
{ "hsla,0(10,0,0)", 0, 0, 0, 0, false }, | |||||
{ "rgba(\\s.*\\d[0-9])", 0, 0, 0, 0, false }, | |||||
{ "rgba(\\.*,255,255, 0)", 0, 0, 0, 0, false }, | |||||
{ "#\\d.*", 0, 0, 0, 0, false }, { "", 0, 0, 0, 0, false }, | |||||
{ "rgba(\\d,\\d,\\d,0.0)", 0, 0, 0, 0, false }, | |||||
{ "^rgba\\( \\.*)", 0, 0, 0, 0, false } }; | |||||
ArrayList<Object[]> values = new ArrayList<>(); | |||||
Collections.addAll(values, validValues); | |||||
Collections.addAll(values, invalidValues); | |||||
return values; | |||||
} | |||||
@Test | |||||
public void testRGBAData() { | |||||
Matcher m = ColorUtil.RGBA_PATTERN.matcher(input); | |||||
boolean matches = m.matches(); | |||||
if (expectedMatches) { | |||||
Color expectedColor = new Color(expectedRed, expectedGreen, | |||||
expectedBlue, expectedAlpha); | |||||
Color c1 = ColorUtil.getRGBAPatternColor(m); | |||||
assertTrue(expectedColor.equals(c1)); | |||||
} else { | |||||
assertTrue(!matches); | |||||
} | |||||
} | |||||
} |
package com.vaadin.tests.server.component.colorpicker; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import java.util.regex.Matcher; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.junit.runners.Parameterized; | |||||
import org.junit.runners.Parameterized.Parameter; | |||||
import org.junit.runners.Parameterized.Parameters; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.ui.components.colorpicker.ColorUtil; | |||||
@RunWith(value = Parameterized.class) | |||||
public class RGBPatternParsingTest { | |||||
@Parameter(value = 0) | |||||
public String input; | |||||
@Parameter(value = 1) | |||||
public int expectedRed; | |||||
@Parameter(value = 2) | |||||
public int expectedGreen; | |||||
@Parameter(value = 3) | |||||
public int expectedBlue; | |||||
@Parameter(value = 4) | |||||
public boolean expectedMatches; | |||||
@Parameters(name = "{index}: testRGBData({0}) = ({1},{2},{3},{4})") | |||||
public static Collection<Object[]> rgbdata() { | |||||
Object[][] validValues = { { "rgb(0,0,0)", 0, 0, 0, true }, | |||||
{ "rgb(0, 0, 0)", 0, 0, 0, true }, | |||||
{ "rgb(0 0 0)", 0, 0, 0, true }, | |||||
{ "rgb(1 1 1)", 1, 1, 1, true }, | |||||
{ "rgb(0 100 255)", 0, 100, 255, true }, | |||||
{ "rgb(255,255,255)", 255, 255, 255, true }, | |||||
{ "RGB(255, 255, 255 )", 255, 255, 255, true }, | |||||
{ "rgb(255 255 255)", 255, 255, 255, true }, | |||||
{ "rgb(1, 10, 100)", 1, 10, 100, true } }; | |||||
Object[][] invalidValues = { { "rgb(,0,0)", 0, 0, 0, false }, | |||||
{ "rgb(0, 0, 0, )", 0, 0, 0, false }, | |||||
{ "rgb(0.0,0,0)", 0, 0, 0, false }, | |||||
{ "rgb( 0 0 -1 )", 0, 0, 0, false }, | |||||
{ "rgb(1 00)", 0, 0, 0, false }, | |||||
{ "rgb(255,255,255.)", 0, 0, 0, false }, | |||||
{ "r gb(255, 256, 255)", 0, 0, 0, false }, | |||||
{ "rgb( 255, 255, 256 )", 0, 0, 0, false }, | |||||
{ "rgb(163, 2%, 210)", 0, 0, 0, false }, | |||||
{ "rGb(000)", 0, 0, 0, false }, | |||||
{ "rgb(255255255)", 0, 0, 0, false }, | |||||
{ "rGBA(255,255,255)", 0, 0, 0, false }, | |||||
{ "rgb 255 255 255)", 0, 0, 0, false }, | |||||
{ "255, 255, 0", 0, 0, 0, false }, | |||||
{ "hsl(10,0,0)", 0, 0, 0, false }, | |||||
{ "\\s%\\d[0-9]", 0, 0, 0, false }, | |||||
{ "rgb(\\.*,255,255)", 0, 0, 0, false }, | |||||
{ "#\\d.*", 0, 0, 0, false }, { "", 0, 0, 0, false }, | |||||
{ "rgb(\\d,\\d,\\d)", 0, 0, 0, false }, | |||||
{ "^rgb\\( \\.*)", 0, 0, 0, false } }; | |||||
ArrayList<Object[]> values = new ArrayList<>(); | |||||
Collections.addAll(values, validValues); | |||||
Collections.addAll(values, invalidValues); | |||||
return values; | |||||
} | |||||
@Test | |||||
public void testRGBData() { | |||||
Matcher m = ColorUtil.RGB_PATTERN.matcher(input); | |||||
boolean matches = m.matches(); | |||||
if (expectedMatches) { | |||||
Color expectedColor = new Color(expectedRed, expectedGreen, | |||||
expectedBlue); | |||||
Color c1 = ColorUtil.getRGBPatternColor(m); | |||||
assertTrue(expectedColor.equals(c1)); | |||||
} else { | |||||
assertTrue(!matches); | |||||
} | |||||
} | |||||
} |
*/ | */ | ||||
package com.vaadin.testbench.elements; | package com.vaadin.testbench.elements; | ||||
import java.util.List; | |||||
import org.openqa.selenium.Keys; | |||||
import org.openqa.selenium.WebElement; | |||||
import com.vaadin.testbench.By; | |||||
import com.vaadin.testbench.elementsbase.ServerClass; | import com.vaadin.testbench.elementsbase.ServerClass; | ||||
@ServerClass("com.vaadin.ui.ColorPickerPreview") | |||||
@ServerClass("com.vaadin.ui.components.colorpicker.ColorPickerPreview") | |||||
public class ColorPickerPreviewElement extends CssLayoutElement { | public class ColorPickerPreviewElement extends CssLayoutElement { | ||||
/** | |||||
* Get whether TextField in ColorPickerPreview has validation errors. | |||||
* | |||||
* @return true if field has errors, false otherwise | |||||
* | |||||
* @since | |||||
*/ | |||||
public boolean getColorFieldContainsErrors() { | |||||
List<WebElement> caption = findElements( | |||||
By.className("v-caption-v-colorpicker-preview-textfield")); | |||||
boolean noCaption = caption.isEmpty(); | |||||
return noCaption ? noCaption | |||||
: caption.get(0).findElements(By.className("v-errorindicator")) | |||||
.isEmpty(); | |||||
} | |||||
/** | |||||
* Get the value of the input element TextField in ColorPickerPreview. | |||||
* | |||||
* @return the value of the attribute 'value' of the input element | |||||
* | |||||
* @since | |||||
*/ | |||||
public String getColorFieldValue() { | |||||
return getColorTextField().getAttribute("value"); | |||||
} | |||||
/** | |||||
* Set value of TextField in ColorPickerPreview. Any existing value in the | |||||
* field is replaced. | |||||
* | |||||
* @param value | |||||
* text to insert | |||||
* | |||||
* @since | |||||
*/ | |||||
public void setColorTextFieldValue(String value) { | |||||
// Select all text | |||||
getColorTextField().sendKeys(Keys.chord(Keys.CONTROL, "a")); | |||||
getColorTextField().sendKeys(value); | |||||
} | |||||
/** | |||||
* @return <code>WebElement</code> representing TextField in | |||||
* ColorPickerPreviewComponent | |||||
* | |||||
* @since | |||||
*/ | |||||
public WebElement getColorTextField() { | |||||
return findElement(By.className("v-colorpicker-preview-textfield")); | |||||
} | |||||
} | } |
width: 100% !important; | width: 100% !important; | ||||
height: auto !important; | height: auto !important; | ||||
padding: round($v-unit-size/4); | padding: round($v-unit-size/4); | ||||
display: inline-flex; | |||||
} | } | ||||
.#{$primary-stylename}-preview-textfield { | .#{$primary-stylename}-preview-textfield { |
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.annotations.Widgetset; | |||||
import com.vaadin.data.HasValue.ValueChangeEvent; | |||||
import com.vaadin.server.StreamResource; | |||||
import com.vaadin.server.VaadinRequest; | |||||
import com.vaadin.shared.ui.ContentMode; | |||||
import com.vaadin.shared.ui.colorpicker.Color; | |||||
import com.vaadin.tests.components.AbstractTestUI; | |||||
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; | |||||
@Widgetset("com.vaadin.DefaultWidgetSet") | |||||
public class ValoColorPickerTestUI extends AbstractTestUI { | |||||
@Override | |||||
public String getTestDescription() { | |||||
return "Vaadin 8 Valo theme ColorPicker"; | |||||
} | |||||
@Override | |||||
protected Integer getTicketNumber() { | |||||
return 10802; | |||||
} | |||||
/** 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 ByteArrayOutputStream imagebuffer; | |||||
/** 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(VaadinRequest request) { | |||||
getLayout().setWidth("1100px"); | |||||
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("550px"); | |||||
layoutLeft.setHeight(null); | |||||
layoutLeft.setSpacing(true); | |||||
GridLayout optLayout = new GridLayout(2, 3); | |||||
optLayout.setWidth("100%"); | |||||
optLayout.setHeight(null); | |||||
optLayout.setMargin(true); | |||||
optLayout.setSpacing(true); | |||||
rgbBox.setValue(rgbVisible); | |||||
rgbBox.addValueChangeListener(event -> { | |||||
rgbVisible = event.getValue(); | |||||
setPopupVisibilities(); | |||||
}); | |||||
rgbBox.setId("rgbBox"); | |||||
optLayout.addComponent(rgbBox); | |||||
hsvBox.setValue(hsvVisible); | |||||
hsvBox.addValueChangeListener(event -> { | |||||
hsvVisible = event.getValue(); | |||||
setPopupVisibilities(); | |||||
}); | |||||
hsvBox.setId("hsvBox"); | |||||
optLayout.addComponent(hsvBox); | |||||
swaBox.setValue(swaVisible); | |||||
swaBox.addValueChangeListener(event -> { | |||||
swaVisible = event.getValue(); | |||||
setPopupVisibilities(); | |||||
}); | |||||
swaBox.setId("swaBox"); | |||||
optLayout.addComponent(swaBox); | |||||
hisBox.setValue(historyVisible); | |||||
hisBox.addValueChangeListener(event -> { | |||||
historyVisible = event.getValue(); | |||||
setPopupVisibilities(); | |||||
}); | |||||
hisBox.setId("hisBox"); | |||||
optLayout.addComponent(hisBox); | |||||
txtBox.setValue(txtfieldVisible); | |||||
txtBox.addValueChangeListener(event -> { | |||||
txtfieldVisible = event.getValue(); | |||||
setPopupVisibilities(); | |||||
}); | |||||
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.setCaptionAsHtml(true); | |||||
colorpicker1.addValueChangeListener(this::colorChanged); | |||||
colorpicker1.setId("colorpicker1"); | |||||
layout1.addComponent(colorpicker1); | |||||
layout1.setComponentAlignment(colorpicker1, Alignment.MIDDLE_CENTER); | |||||
colorpicker2 = new ColorPicker("Background", backgroundColor); | |||||
colorpicker2.addValueChangeListener(this::colorChanged); | |||||
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.addValueChangeListener(this::colorChanged); | |||||
colorpicker3.setWidth("130px"); | |||||
colorpicker3.setCaption("Foreground"); | |||||
colorpicker3.setId("colorpicker3"); | |||||
layout2.addComponent(colorpicker3); | |||||
layout2.setComponentAlignment(colorpicker3, Alignment.MIDDLE_CENTER); | |||||
colorpicker4 = new ColorPicker("Background", backgroundColor); | |||||
colorpicker4.addValueChangeListener(this::colorChanged); | |||||
colorpicker4.setWidth("130px"); | |||||
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.addValueChangeListener(this::colorChanged); | |||||
colorpicker5.setId("colorpicker5"); | |||||
layout3.addComponent(colorpicker5); | |||||
layout3.setComponentAlignment(colorpicker5, Alignment.MIDDLE_CENTER); | |||||
colorpicker6 = new ColorPickerArea("Background", backgroundColor); | |||||
colorpicker6.setCaption("Background"); | |||||
colorpicker6.setDefaultCaptionEnabled(false); | |||||
colorpicker6.addValueChangeListener(this::colorChanged); | |||||
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); | |||||
} | |||||
private void colorChanged(ValueChangeEvent<Color> event) { | |||||
if (event.getSource() == colorpicker1 | |||||
|| event.getSource() == colorpicker3 | |||||
|| event.getSource() == colorpicker5) { | |||||
foregroundColor = event.getValue(); | |||||
if (event.getSource() != colorpicker1) { | |||||
colorpicker1.setValue(event.getValue()); | |||||
} | |||||
if (event.getSource() != colorpicker3) { | |||||
colorpicker3.setValue(event.getValue()); | |||||
} | |||||
if (event.getSource() != colorpicker5) { | |||||
colorpicker5.setValue(event.getValue()); | |||||
} | |||||
} else if (event.getSource() == colorpicker2 | |||||
|| event.getSource() == colorpicker4 | |||||
|| event.getSource() == colorpicker6) { | |||||
backgroundColor = event.getValue(); | |||||
if (event.getSource() != colorpicker2) { | |||||
colorpicker2.setValue(event.getValue()); | |||||
} | |||||
if (event.getSource() != colorpicker4) { | |||||
colorpicker4.setValue(event.getValue()); | |||||
} | |||||
if (event.getSource() != colorpicker6) { | |||||
colorpicker6.setValue(event.getValue()); | |||||
} | |||||
} else { | |||||
return; | |||||
} | |||||
updateDisplay(foregroundColor, backgroundColor); | |||||
} | |||||
} |
package com.vaadin.tests.components.colorpicker; | |||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.assertFalse; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.List; | |||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
import org.openqa.selenium.Keys; | |||||
import org.openqa.selenium.WebElement; | |||||
import org.openqa.selenium.remote.DesiredCapabilities; | |||||
import com.vaadin.testbench.elements.ColorPickerElement; | |||||
import com.vaadin.testbench.elements.ColorPickerPreviewElement; | |||||
import com.vaadin.testbench.parallel.Browser; | |||||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||||
/** | |||||
* Test legal color values according to | |||||
* http://www.w3schools.com/cssref/css_colors_legal.asp | |||||
*/ | |||||
public class ValoColorPickerInputFormatsTest extends MultiBrowserTest { | |||||
@Override | |||||
public List<DesiredCapabilities> getBrowsersToTest() { | |||||
// Ignoring Phantom JS | |||||
return getBrowserCapabilities(Browser.IE11, Browser.FIREFOX, | |||||
Browser.CHROME); | |||||
} | |||||
private ColorPickerPreviewElement previewElement; | |||||
@Before | |||||
public void setUp() { | |||||
openTestURL(); | |||||
getPreviewElement(); | |||||
} | |||||
private void getPreviewElement() { | |||||
ColorPickerElement cpElement = $(ColorPickerElement.class) | |||||
.id("colorpicker1"); | |||||
// Open ColorPicker | |||||
cpElement.click(); | |||||
// Find preview element | |||||
previewElement = $(ColorPickerPreviewElement.class).first(); | |||||
} | |||||
@Override | |||||
protected Class<?> getUIClass() { | |||||
return ValoColorPickerTestUI.class; | |||||
} | |||||
@Test | |||||
public void testRGBValue() throws Exception { | |||||
setColorpickerValue("rgb(100 100 100)"); | |||||
assertEquals("#646464", previewElement.getColorFieldValue()); | |||||
} | |||||
@Test | |||||
public void testRGBAValue() { | |||||
setColorpickerValue("rgba(100,100,100, 0.5)"); | |||||
assertEquals("#646464", previewElement.getColorFieldValue()); | |||||
} | |||||
@Test | |||||
public void testHSLValue() { | |||||
setColorpickerValue("hsl(120,100%, 50%)"); | |||||
assertEquals("#00ff00", previewElement.getColorFieldValue()); | |||||
} | |||||
@Test | |||||
public void testHSLAValue() { | |||||
setColorpickerValue("hsla(120, 0, 50%, 0.3)"); | |||||
assertEquals("#00ff00", previewElement.getColorFieldValue()); | |||||
} | |||||
@Test | |||||
public void testHexTextInputValidation() { | |||||
// set valid hex value to ColorTextField | |||||
setColorpickerValue("#AAbb33"); | |||||
assertFalse(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testRGBTextInputValidation() { | |||||
String rgbString = "rgb(255 10 0)"; | |||||
// set valid rgb value to ColorTextField | |||||
setColorpickerValue(rgbString); | |||||
assertFalse(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testHSLTextInputValidation() { | |||||
String hslString = "HSL(300, 60, 100)"; | |||||
setColorpickerValue(hslString); | |||||
assertFalse(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testHexTextInputValidationError() { | |||||
// set invalid hex value to ColorTextField | |||||
setColorpickerValue("#xyz"); | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testRGBTextInputValidationError() { | |||||
String rgbString = "rgb(300, 60, 90)"; | |||||
// set invalid rgb value to ColorTextField | |||||
setColorpickerValue(rgbString); | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testRGBATextInputValidationError() { | |||||
String rgbaString = "rgba(250, 0, 10, 6.0)"; | |||||
// set invalid rgba value to ColorTextField | |||||
setColorpickerValue(rgbaString); | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testHSLTextInputValidationError() { | |||||
String hslString = "hsl(370,60%,120%)"; | |||||
// set invalid hsl value to ColorTextField | |||||
setColorpickerValue(hslString); | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testHSLATextInputValidationError() { | |||||
String hslaString = "hsla(300, 50, 10, 1.1)"; | |||||
// set invalid hsla value to ColorTextField | |||||
setColorpickerValue(hslaString); | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
} | |||||
@Test | |||||
public void testFailedValidationResult() { | |||||
// set invalid hex value to ColorTextField | |||||
setColorpickerValue("#xyz"); | |||||
// verify there are errors | |||||
assertTrue(previewElement.getColorFieldContainsErrors()); | |||||
// verify value has not been changed | |||||
assertEquals(previewElement.getColorFieldValue(), "#xyz"); | |||||
} | |||||
private void setColorpickerValue(String value) { | |||||
WebElement field = previewElement.getColorTextField(); | |||||
// Select all text | |||||
field.sendKeys(Keys.chord(Keys.CONTROL, "a")); | |||||
// Replace with new value | |||||
field.sendKeys(value); | |||||
// Submit | |||||
field.sendKeys(Keys.RETURN); | |||||
} | |||||
} |